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.