Suppose I have set groupId
to com.example
, and artifactId
to fancy.project
, and now I want to create a archetype, such that when created, expands into the following structure:
|--src
|--main
|--com
|--example
|-fancy
|-project
|-App.java
That is, I wonder how to expand a variable into a nested directory.
I understand that the dual-underscore-wrapped variables will be substituted in file/directory names, but I can only get the following with __groupId__
.
|--src
|--main
|--com.example
|-fancy.project
|-App.java
As input to the archetype you can specify the package
option (which would then follow your input, the groupId and artifactId concatenation if you want, even though it is not always the case and hence provide even more flexibility).
Then, in your archetype you can use the packageInPathFormat
option (available since archetype 2.2) which would replace any dot .
into slash \
and as such transforming it to a path into the generated project.
However, the option is not officially documented (pity) even though supported and works fine for such a scenario.
Looking at the code, the DefaultFilesetArchetypeGenerator
and its getPackageInPathFormat
provide the concerned transformation from the package
option to a path, while the org.apache.maven.archetype.common.Constants.PACKAGE_IN_PATH_FORMAT is the official entry point for this option.
Some externals pointers on the usage of this option:
- http://geekofficedog.blogspot.be/2013/08/creating-maven-archetypes-tutorial.html
- http://www.theotherian.com/2012/05/maven-archetypes-part-2-how-do-i-create.html
To further explain:
- You can have the
__packageInPathFormat__
folder under your src/main/java, for example
- The
__packageInPathFormat
would then be replaced by the package
option transforming dots into slashes
- The
package
option has a default value to groupId
, so if you don't specify it, for a groupId
with value com.sample
, the path would be com/sample
- You can hence specify at invocation time the package desired via
-Dpackage=your.package
repeating the values for -DgroupId
and -DartifactId
(a bit verbose and error prone though), the final result will actually be what you expected (transformed to correct path).
You can specify new default values via a archetype-metada.xml
file, as specified in the official documentation, via the requiredProperties
section, you could have something like:
<requiredProperties>
<requiredProperty key="package">
<defaultValue>__groupId__.__artifactId__</defaultValue>
</requiredProperty>
</requiredProperties>
However, the generated path would then be com.sample/artifactid
rather than com/sample/artifactid
. Hence it would not work as expected due to the processing workflow which would replace the placeholders after transforming it to a path (pity!).
(Note: it would transform the dot we provided as configured value, but would then not transform dots into the replaced placeholders).
As of a quick code analysis, seems like the DefaultFilesetArchetypeGenerator
class in its generateArchetype
method is preparing the context too early (in its prepareVelocityContext
method, where the packageInPathFormat
is transformed and added to the context), then the context is passed to processArchetypeTemplate*
methods which would eventually invoke the Velocity engine (which is going to replace placeholders then). I am not a Velocity expert though, hence I may miss some glue, but the observed behavior and the code workflow seem to lead to this conclusion.