wurbelizer:test-wurbel
Full name:
org.wurbelizer:wurbelizer-maven-plugin:25.7.0.0:test-wurbel
Description:
Wurbel test sources.
Scans the test sources for @wurblet anchors and executes the wurblets. The generated code from the wurblets is merged into the test sources.
Attributes:
- Requires a Maven project to be executed.
- Requires dependency resolution of artifacts in scope:
test. - The goal is thread-safe and supports parallel builds.
- Binds by default to the lifecycle phase:
process-test-sources.
Required Parameters
| Name | Type | Since | Description |
|---|---|---|---|
<analyzeDir> |
File |
- |
Directory for additional files generated by preceding phases provided for wurblets. Default: ${project.build.directory}/test-analyzeUser Property: wurbel.testAnalyzeDir |
<sourceDir> |
File |
- |
Directory holding the sources to be wurbelized.
Defaults to all java test sources of the current project. If this is not desired, filesets must be used. Default: ${project.build.testSourceDirectory}User Property: wurbel.testSourceDir |
<wurbelDir> |
File |
- |
Target directory for all files referenced by wurblets. Default: ${project.build.directory}/wurbelUser Property: wurbel.wurbelDir |
<wurbletPaths> |
List<String> |
- |
Classpaths for loading wurblets.
Used for all non-fully-qualified wurblet anchors. |
Optional Parameters
| Name | Type | Since | Description |
|---|---|---|---|
<charset> |
String |
- |
The charset used to read and write files. Default: ${project.build.sourceEncoding} |
<dryRun> |
boolean |
- |
Dry run.
Don't run any wurblets, just parse the files. |
<excludeAnchors> |
List<String> |
- |
Optional list of regular expressions describing the guarded names used in the wurblet anchors to exclude.
Same as includeAnchors
, but those wurblet anchors will not be processed. |
<excludeWurblets> |
List<String> |
- |
Optional list of regular expressions describing the wurblet names used in the wurblet anchors to exclude.
Same as includeWurblets
, but those wurblets will not be processed. |
<filesets> |
List<FileSet> |
- |
The list of file sets to wurbile or wurbel.
If set, the source directory is ignored. |
<firstPhase> |
int |
- |
Optional wurbel phase to start with.
Default is 0 (collect heredocs). |
<includeAnchors> |
List<String> |
- |
Optional list of regular expressions describing the guarded names used in the wurblet anchors.
If given, only those wurblet anchors will be processed. |
<includeWurblets> |
List<String> |
- |
Optional list of regular expressions describing the wurblet names used in the wurblet anchors.
If given, only those wurblets will be processed. |
<lastPhase> |
int |
- |
Optional wurbel phase to end with (including).
Default is Integer.MAX_VALUE, i.e. unlimited. |
<skip> |
Boolean |
- |
Skips processing.
Defaults to true if packaging is "pom". |
<verbosity> |
String |
- |
The verbosity.
One of "default", "info" or "debug". Debug is also turned on (if not set explicitly) by Maven's global debug flag (see command line switch -X).Default: ${wurbel.verbosity} |
<wurbletDependencies> |
List<WurbletDependency> |
- |
The artifacts containing the wurblets.
Each entry is a regular Maven dependency with groupId, artifactId, version and optionally classifier and type:
<wurbletDependencies>
<wurbletDependency>
<groupId>org.example</groupId>
<artifactId>example-wurblets</artifactId>
<version>1.0</version>
</wurbletDependency>
</wurbletDependencies>
The artifacts are resolved, together with their transitive runtime dependencies and with respect to the project's dependency management, each time the mojo is executed. They are loaded by a separate classloader, a child realm of the plugin's classrealm, created for this execution only. The wurbelizer core packages are imported from the plugin's classrealm. The realm becomes the thread's context classloader, is available to the wurblets via org.wurbelizer.wurbel.WurbelContext.getWurbletClassLoader()
and is disposed of when the execution ends.
wurbletDependencies versus plugin dependencies
Wurblets built in the same reactor
<dependency> <groupId>org.example</groupId> <artifactId>example-wurblets</artifactId> <version>1.0</version> <type>pom</type> <scope>provided</scope> </dependency> Parallel builds and thread safety
@Override
public boolean isThreadSafe() {
ClassLoader loader = WurbelContext.current().getWurbletClassLoader();
return loader != null && getClass().getClassLoader() == loader;
}
The Tentackle wurblets, for example, implement this check in org.tentackle.wurblet.WurbletThreadSafety.isIsolated(Class). They run concurrently if declared as wurbletDependencies and fall back to sequential execution if declared as plugin dependencies.See also: org.wurbelizer.wurblet.Wurblet.isThreadSafe(), org.wurbelizer.wurbel.WurbelContext.getWurbletClassLoader() |
<wurbletProperties> |
Properties |
- |
Properties used by wurblets.
Properties referring to directories or files should prepend ${wurbelDir} in their path. This is a predefined property pointing to wurbelDir
. The values may refer to other predefined properties such as $project or $projectRoot. |
Parameter Details
<analyzeDir>
- Type:
java.io.File - Required:
Yes - User Property:
wurbel.testAnalyzeDir - Default:
${project.build.directory}/test-analyze
<charset>
- Type:
java.lang.String - Required:
No - Default:
${project.build.sourceEncoding}
<dryRun>
Don't run any wurblets, just parse the files.
- Type:
boolean - Required:
No
<excludeAnchors>
Same as
includeAnchors
, but those wurblet anchors will not be processed.- Type:
java.util.List<java.lang.String> - Required:
No
<excludeWurblets>
Same as
includeWurblets
, but those wurblets will not be processed.- Type:
java.util.List<java.lang.String> - Required:
No
<filesets>
If set, the source directory is ignored.
- Type:
java.util.List<org.apache.maven.shared.model.fileset.FileSet> - Required:
No
<firstPhase>
Default is 0 (collect heredocs).
- Type:
int - Required:
No
<includeAnchors>
If given, only those wurblet anchors will be processed.
- Type:
java.util.List<java.lang.String> - Required:
No
<includeWurblets>
If given, only those wurblets will be processed.
- Type:
java.util.List<java.lang.String> - Required:
No
<lastPhase>
Default is
Integer.MAX_VALUE, i.e. unlimited.- Type:
int - Required:
No
<skip>
Defaults to true if packaging is "pom".
- Type:
java.lang.Boolean - Required:
No
<sourceDir>
Defaults to all java test sources of the current project. If this is not desired, filesets must be used.
- Type:
java.io.File - Required:
Yes - User Property:
wurbel.testSourceDir - Default:
${project.build.testSourceDirectory}
<verbosity>
One of "default", "info" or "debug". Debug is also turned on (if not set explicitly) by Maven's global debug flag (see command line switch
-X).- Type:
java.lang.String - Required:
No - Default:
${wurbel.verbosity}
<wurbelDir>
- Type:
java.io.File - Required:
Yes - User Property:
wurbel.wurbelDir - Default:
${project.build.directory}/wurbel
<wurbletDependencies>
Each entry is a regular Maven dependency with
groupId, artifactId, version and optionally classifier and type:
<wurbletDependencies>
<wurbletDependency>
<groupId>org.example</groupId>
<artifactId>example-wurblets</artifactId>
<version>1.0</version>
</wurbletDependency>
</wurbletDependencies>
The artifacts are resolved, together with their transitive runtime dependencies and with respect to the project's dependency management, each time the mojo is executed. They are loaded by a separate classloader, a child realm of the plugin's classrealm, created for this execution only. The wurbelizer core packages are imported from the plugin's classrealm. The realm becomes the thread's context classloader, is available to the wurblets via org.wurbelizer.wurbel.WurbelContext.getWurbletClassLoader()
and is disposed of when the execution ends.
wurbletDependencies versus plugin dependencies
Wurblets can also be added to the <dependencies> of the plugin declaration. They are then loaded by the plugin's classrealm itself. Maven creates this realm only once per build and caches it, so all modules and all executions of the build share the same wurblet classes and thus the same static state, such as models, caches and other singletons. In that case org.wurbelizer.wurbel.WurbelContext.getWurbletClassLoader() returns null. With wurbletDependencies, on the contrary, each execution gets fresh classes with fresh static state. Different modules may even use different versions of the same wurblet artifact.
Wurblets built in the same reactor
If the wurblets are compiled with the wurbile goal in a module of the same multi-module build, the wurbletDependencies are resolved from the reactor at the time the consuming module is wurbeled. Hence, the wurblets just built are used and not a stale copy cached in the plugin's classrealm or in the local repository.
However, Maven does not interpret the plugin's configuration when it determines the build order of the modules. Unlike a plugin dependency, a wurbletDependency does not make the consuming module depend on the wurblet module. In a sequential build, the order of the <modules> usually hides this. In a parallel build (mvn -T ...), however, only declared dependencies count, and the consuming module may start before the wurblet module is built. It then picks up an outdated artifact from the local repository or fails. Therefore, the consuming module should additionally declare a regular dependency on the wurblet module to enforce the build order. With type pom and scope provided, the dependency affects only the build order and does not put the wurblets on the compile classpath:
<dependency> <groupId>org.example</groupId> <artifactId>example-wurblets</artifactId> <version>1.0</version> <type>pom</type> <scope>provided</scope> </dependency>
Parallel builds and thread safety
Wurblets that are not thread-safe are executed one at a time within the JVM, even if Maven builds several modules in parallel. Only wurblets returning true from isThreadSafe() run concurrently. Since each execution processes its sources sequentially, wurblets that keep their state in singletons are thread-safe nonetheless, as long as they are isolated in the classloader of the current execution. This holds only if they are loaded via wurbletDependencies. The wurblets can check that at runtime:
@Override
public boolean isThreadSafe() {
ClassLoader loader = WurbelContext.current().getWurbletClassLoader();
return loader != null && getClass().getClassLoader() == loader;
}
The Tentackle wurblets, for example, implement this check in org.tentackle.wurblet.WurbletThreadSafety.isIsolated(Class). They run concurrently if declared as wurbletDependencies and fall back to sequential execution if declared as plugin dependencies.See also: org.wurbelizer.wurblet.Wurblet.isThreadSafe(), org.wurbelizer.wurbel.WurbelContext.getWurbletClassLoader()
- Type:
java.util.List<org.wurbelizer.maven.WurbletDependency> - Required:
No
<wurbletPaths>
Used for all non-fully-qualified wurblet anchors.
- Type:
java.util.List<java.lang.String> - Required:
Yes
<wurbletProperties>
Properties referring to directories or files should prepend
${wurbelDir} in their path. This is a predefined property pointing to wurbelDir
. The values may refer to other predefined properties such as $project or $projectRoot.- Type:
java.util.Properties - Required:
No
Wurbelizer