Veripacks already allows to specify and verify which classes should be visible outside of a package (in a package-transitive way) as well as require importing and import packages within a project. This makes it possible to eliminate some build modules, while still keeping their strict isolation (which can be checked by running Veripacks).
However, what if we would like to verify that a 3rd party library is used only in a specific portion of the code? For example, let’s say we want the Hibernate classes to be used only by the dao
module, and we want this to be verified at build time. The usual approach could be:
- create a
dao-api
build module - create a
dao
build module with adao-api
and Hibernate dependencies - implement the DAOs
- add the
dao-api
module as a dependency to all other modules which use the DAOs - add the
dao
module as a dependency to the module which builds the distribution (e.g. war)
If we are using Maven, that’s quite a lot of xml to write and directories to create. Could it be simpler?
Veripacks 0.4 aims at making this exact case simpler, using package-level annotations. When creating an instance of Veripacks, it is now possible to specify which packages should require importing. To use classes from such packages, you just need to add an @Import
annotation to the package – and Veripacks will check that everything is used only where allowed:
// test case which runs Veripacks
VeripacksBuilder
.requireImportOf("org.hibernate")
.build
.verify("com.foo.project")
.throwIfNotOk()
// package in which we want to use Hibernate classes
// package-info.java
@Import("org.hibernate")
package com.foo.project.db.dao;
import org.veripacks.Import;
Veripacks itself uses these annotations to constraint the usage of the ASM bytecode-reading library; see the VeripacksSelfTest
class and the annotation on the org.veripacks.reader
package.
The improved process of constraining usage of a 3rd party library code to a specific part of our code now is:
- create a
dao.api
anddao.impl
packages (these are just example names; Veripacks doesn’t require using any specific naming convention) - add Hibernate as a dependency to the project
- implement the DAOs
@Import
thedao.api
package in packages which use the DAOs
That’s a lot less XML to write (none), a bit more package-info.java
to write, and only three directories to create.
Note however, that for project-packages, you should still use the @RequiresImport
annotation. The VeripacksBuilder.requireImportOf
and .doNotRequireImportOf
methods are only intended to be used with 3rd party packages.
The new release also contains two other features. Firstly, it is now possible to skip verification in a class using the @NotVerified
annotation. This may be useful for bootstrap-like classes, where wiring of the class instances is done, and implementation-classes form various packages are used.
Secondly, when building Veripacks, you can provide an implementation of the CustomAccessDefinitionsReader
trait, and specify metadata in a programmatic way. E.g. if the project has a com.[company].[project].[module].[submodule]
package naming convention, and we would like all module-packages to always require import, instead of adding an @RequiresImport
annotation to each such package, we can do:
VeripacksBuilder
.withCustomAccessDefinitionReader(new CustomAccessDefinitionsReader {
override def isRequiresImport(pkg: Pkg) = pkg.name.split(".").length == 4
})
.build
.verify(List("com.[company].[project]"))
.throwIfNotOk()
As always Veripacks is available in the Maven central repository, and the sources on GitHub under the Apache2 license. Have fun!
Adam
comments powered by Disqus