Setting dynamic velocity properties for archetype maven projects

maven archetype properties
maven create archetype from existing project
which archetype to select while creating maven project
mvn archetype:generate

I am creating an archetype and want to create a project wide available property containing things like the current date and an all lower case variant of the artifact id. I found the following post on Stackoverflow, that shows how it normally should be possible.

I tried adding this to the archetype-metadata.xml like so:

    ...
    <requiredProperty key="artifactIdLower">
        <defaultValue>${artifactId.toLowerCase()}</defaultValue>
    </requiredProperty>
    <requiredProperty key="ldt">
        <defaultValue>${package.getClass().forName("java.time.LocalDateTime").getMethod("now").invoke(null)}</defaultValue>
    </requiredProperty>
    <requiredProperty key="dtf">
        <defaultValue>${package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke(null, "dd MMM yyyy")}</defaultValue>
    </requiredProperty>
    <requiredProperty key="date">
        <defaultValue>${ldt.format($dtf)}</defaultValue>
    </requiredProperty>
    ...

The property artifactIdLower works like a charm, but the ldt, dtf and date don't seem to work, giving the error:

Null reference [template 'dtf', line 1, column 1] : ${package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke(null, "dd MMM yyyy")} cannot be resolved.

After that I tried to see where in the chain this null reference comes from. I was able to set pkgClass to $package.getClass() (or to $package.Class),

but after that I was unable to set $strClass to $package.getClass().forName("java.lang.String") or to $pkgClass.forName("java.lang.String") (funnily enough, both pkgClass and strClass should be a Class object).

This made me wonder if there is a restriction on using reflection inside the archetype-metadata.xml.

My question is: how can I set dynamically generated property values (like above) that can be used project wide?

I don't want to have to define these properties in every file that I create, because there might be more properties that I want to add later.

Edit: I tried to instead create a generalproperties.vm file that contained the #set directives. This file would then be loaded by every file on the first line using #parse("generalproperties.vm"). While I did get the file to be parsed from within the pom.xml file, it didnt behave as I wanted.

The following input

test
$null
#set( $ldtClass = $package.getClass().forName("java.time.LocalDateTime") )
$ldtClass.Name
$ldtClass.getMethod("now")
#set( $ldtNowMethod = $ldtClass.getMethod("now") )
$ldtNowMethod.Name
#set( $clsLoader = $package.getClass().getClassLoader() )
$clsLoader
#set( $ldtClass2 = $clsLoader.loadClass("java.time.LocalDateTime") )
$ldtClass2.Name
$ldtClass2.getMethod("now")
#set( $ldtNowMethod2 = $ldtClass2.getMethod("now") )
$ldtNowMethod2.Name
#set( $ldt = $ldtNowMethod2.invoke($null) )
$ldt
#set( $dtf = $package.getClass().forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.getClass().forName("java.lang.String")).invoke($null, "yyyy/MM/dd HH:mm:ss") )
$dtf

Generated the following output:

test
$null
java.time.LocalDateTime
$ldtClass.getMethod("now")
$ldtNowMethod.Name
$clsLoader
$ldtClass2.Name
$ldtClass2.getMethod("now")
$ldtNowMethod2.Name
$ldt
$dtf

The first 3 outputs are as expected, but after that I don't get the results I want. If someone is able to solve either of the above issues (with the metadata file or the generalproperties file), it would be highly appreciated.

This should work:

...
<requiredProperty key="date">
    <defaultValue>${package.getClass().forName("java.time.LocalDateTime").getMethod("now").invoke(null).format($package.Class.forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.Class).invoke(null, "dd MMM yyyy"))}</defaultValue>
</requiredProperty>
...

Maven Archetype Plugin – Create an archetype with a property file, archetype properties. How to vary the generated class? By default maven has a set of standard variables defined that can be varied when the  In my archetype-metadata.xml, I have a property defined like: <requiredProperties> <requiredProperty key="foo"/> </requiredProperties> I can use Velocity for manipulation of text inside files, for example:

Maybe it could help somebody what I noticed.

When I had something like:

<requiredProperty key="packageId"></requiredProperty>
<requiredProperty key="packageIdInPathFormat">
    <defaultValue>${package.getClass().getMethod("replace").invoke($packageId, ".", "/")}</defaultValue>
</requiredProperty>

It was not evaluating expression in property packageIdInPathFormat.

But when I did something like:

<requiredProperty key="packageId"></requiredProperty>

<requiredProperty key="tempPackageId">
   <defaultValue>${packageId}</defaultValue>
</requiredProperty>

<requiredProperty key="packageIdInPathFormat">
   <defaultValue>${tempPackageId.replace(".", "/")}</defaultValue>
</requiredProperty>

Expression was evaluated.

Create an archetype from a multi-module project, Or, could you remove unused dependencies and clean up properties files and integrated into a multi-module Maven setup to automate new projects This archetype gets built as part of a Maven multi-module setup, A filtered fileSet means that the included files will be processed as Velocity templates,  When creating a project from this archetype, the Velocity variable substitution for ${rootArtifactId} doesn’t resolve at all. SOLUTION. After reading Maven Archetype Plugin’s source code here and here, the Velocity variable substitutions are only performed on the following file extensions:-

The only restriction I could think of is if you are using the SecureUberspector instead of the standard Uberspector in your Velocity configuration properties. But you wouldn't be able to get the java.time.LocalDateTime class, so it's not the case, unless maybe if you are using an old Velocity version. With Velocity 1.7 I am able to get a reference to the now() method and to call it.

Also, are you sure that the direct Java version is working properly? For instance, I read in the Class.getClassLoader() javadoc that "some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader."

Creating maven archetype using create-from-project, Dynamic framework for developing, deploying and managing distributed systems composed of Java services. Rio provides a custom Maven archetype for creating a Rio project. [INFO] No goals needed for project - skipping [INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.​velocity. There are two ways to kickoff an archetype project: 1. Build the project layout by scratch and add files as need 2. Run the Maven archetype plugin on an existing project and configure from there. Since we already have a sample project I’m going to cover option two.

Implementing a Maven Archetype to Generate Spring Boot-Based , Maven archetypes are project templates for starting new projects. Run the Maven archetype plugin on an existing project and configure from there. to add it in src/test/resources/projects/basic/archetype.properties as a key/value pair. Velocity can be used for dynamic file generation, it can use java  Maven archetypes can be created easily using the create-from-project maven command. To create an archetype from a project run the command from the directory where the template project is present. To create an archetype from a project run the command from the directory where the template project is present.

Rio Archetype, This maven tutorial describes how to create an archetype to create projects Here is an EclipseSW external tool configuration to create an archetype project. Literal [INFO] Loaded System Directive: org.apache.velocity.runtime.directive. Reduces lots of time in setting up the project structure, increasing developer’s productivity by quick start to actual work. Reduces code review effort, by ensuring that the project structure and intended artifacts are in place. Create Custom Archetype. Maven has already provided one new archetype maven-archetype-archetype to create new archetypes.

Create a Maven Archetype from an existing project, I am creating an archetype and want to create a project wide available property containing things li. Using maven-archetype-quickstart (org.apache.maven.archetypes:maven-archetype-quickstart:1.0) Choose archetype: 1: local -> archetype-with-properties (archetype-with-properties) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1 Define value for groupId: : foo Define value for artifactId: : bar Define value for version: 1.0-SNAPSHOT: : Define value for package: foo: : Confirm properties configuration: an_additional_property: my specific value groupId

Comments
  • I am still getting the following error: INFO: Null reference [template 'date', line 1, column 1] : ${package.getClass().forName("java.time.LocalDateTime").getMethod("now").invoke(null).format($package.Class.forName("java.time.format.DateTimeFormatter").getMethod("ofPattern", $package.Class).invoke(null, "dd MMM yyyy"))} cannot be resolved. I'm using IntelliJ IDEA 2017.1.3 Ultimate edition
  • What's the version of your maven-archetype-plugin ? I use 3.0.1
  • I am also using that version. How do you create your archetype?
  • What do you mean? How do I generate a project? with archetype:generate.
  • What is your Maven version? Mine is 3.5.0
  • It looks like properties are evaluated in some alphabetic order...
  • I am using the latest version of maven archetype which uses velocity 1.7 I think. The weird thing is the inconsistency between the archetype-metadata file and the parsed file. The parsed file is unable to get the method now where the metadata file cannot even reach the class by using forName. Any thought on that?