Creating Maven archetype using required properties - maven

I have created my own archetype which defines in archetype-metadata.xml a required property:
<requiredProperty key="version.wildfly">
<defaultValue>16.0.0.Final</defaultValue>
</requiredProperty>
This property needs to be used in src/main/resources/archetype-resources/pom.xml as a property:
<properties>
<version.server.bom>${version.wildfly}</version.server.bom>
</properties>
Indeed, when I create a project using this archetype, I'm being asked to confirm the default value for the property:
version.wildfly: 16.0.0.Final
Y: : Y
However, in the generated project's pom.xml, it is not specified anywhere to use this property. The pom.xml merely contains:
<properties>
<version.server.bom>${version.wildfly}</version.server.bom>
</properties>
And thus the build fails. Did I use any wrong pattern to inject the property in the pom.xml ?
Thanks

Don't use dot, try version-wildfly.
looks like archetype consider dot-split property as internal use. see Custom Properties

Related

Modify properties tag in POM.xml file from Jenkins

I have following properties in pom.xml file :-
<properties>
<cm_java_home>C:/Java/jdk1.8.0-102/bin</cm_java_home>
</properties>
But, I need to change this during building job from Jenkins, and it should look like as given below:-
<properties>
<cm_java_home>/home/abc/Java/jdk-1.8.0-102/jre</cm_java_home>
</properties>
How to modify my properties tag in pom.xml file using Jenkins job configuration ?
Simply, to modify any property of pom.xml file, use -D=value.
For instance, in my case,
I used the following:-
mvn clean install -Dcm_java_home="/home/abc/Java/jdk1.8.0_102/jre"

Extending property from parent pom in child pom with maven

I am working in a large project where we have multiple modules, each as their own maven project with a common parent pom.
Among other things, the parent pom defines the Sonar integration on our build server. Our Sonar plugin on the build server evaluates the property "sonar.exclusions" in order to skip files which we do not want to be analysed.
For that purpose, we define a property in the parent pom:
<properties>
<sonar.exclusion>**/generated/**/*,**/migration/**/*</sonar.exclusions>
</properties>
Now, in one of our projects, we want to add to this exclusion list. I do not want to replace those exclusions defined in the parent but I also do not want to repeat them. What I am looking for is something along these lines:
<properties>
<sonar.exclusions>${sonar.exclusions},**/shadow/compare/**/*</sonar.exclusions>
</properties>
In the end, I want the content of ${sonar.exclusions} to be
**/generated/**/*,**/migration/**/*,**/shadow/compare/**/*
However, trying the above results in an error:
pom.xml has 1 error [main] ERROR org.apache.maven.cli.MavenCli - Resolving expression: ${sonar.exclusions}': Detected the following recursive expression cycle in 'sonar.exclusions': [sonar.exclusions]
Is there a way to achieve what I want?
You can define a property <sonar.standard.exclusions> in your parent POM that contains your standard exclusions and set <sonar.exclusions>${sonar.standard.exclusions}</sonar.exclusions>
Then you can overwrite the property in your POM as
<sonar.exclusions>${sonar.standard.exclusions},**/shadow/compare/**/*</sonar.exclusions>

is there a placeholder for src/main/webapp/WEB-INF directory in Maven

Is there a predefined placeholder for src/main/webapp/WEB-INF directory in maven which can be referred by ${XYZ} ?
If not, is there a way to define such a placeholder?
There isn't really a need for predefined variables that are very much tied to a particular type of project module and packaging standard, with $basedir you have access to any module folder you want. So also ${basedir}/src/main/webapp/WEB-INF.
And Maven allows you to define your own properties.
<project>
<properties>
<webinf.basedir>${basedir}/src/main/webapp/WEB-INF</webinf.basedir>
</properties>
...
</project>
Then you simply have access to the path as ${webinf.basedir}. Use whatever property name you like of course.
Refer to the Maven documentation for a nice overview of available path properties.

Maven archetype - optional property, empty by default

I want to be able to generate a project from my archetype with one of the properties being empty by default, or populated if specified so on the command line.
This is my archetype-metadata.xml:
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="basic">
<requiredProperties>
<requiredProperty key="compilerVersion"/>
<requiredProperty key="dependencyClassifier">
<defaultValue></defaultValue>
</requiredProperty>
</requiredProperties>
</archetype-descriptor>
This is not working. If there is any non-whitespace value in dependencyClassifier, then it works flawlessly. However, I cannot get it to work with the default value being "empty".
The error I get when defaultValue is empty/null is:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-archetype-plugin:2.4:generate (default-cli) on project standalone-pom: Archetype com.avast.archetype:compile-java:1.0.21 is not configured
[ERROR] Property dependencyClassifier is missing.
[ERROR] -> [Help 1]
Alternatively, I would accept being able to pass an empty-value (or "whitespace" value) on the command line. Again, using "-DdependencyClassifier= " does not work.
How do I specify a property should be empty by default?
Thanks
What I want to achieve with this is to be able to create a project from an archetype, which contains a dependency declaration:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>artifact</artifactId>
<version>${dependencyVersion}</version>
<classifier>${dependencyClassifier}</classifier>
</dependency>
</dependencies>
and I need to be able to instantiate ${dependencyClassifier} on archetype creation. This is possible for ${dependencyVersion}, because that will never be empty. Classifier, however, should be empty by default.
This is how I successed meeting your requirements:
In the template pom.xml file for the to-be-generated Maven project, place an empty property, but don't use it as placeholder of the classifier value, there you will still use the archetype requiredProperty placeholder as following:
<properties>
<!-- empty placeholder, document it accordingly -->
<empty.property></empty.property>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
<classifier>${dependencyClassifier}</classifier>
</dependency>
</dependencies>
Then, in your archetype-metadata.xml have the following:
<requiredProperties>
<requiredProperty key="dependencyClassifier">
<defaultValue>${empty.property}</defaultValue>
</requiredProperty>
</requiredProperties>
Note the matchings:
The ${empty.property} default value here is just a non existing property for the Archetype Plugin, which is accepted (an empty value would not work indeed).
The dependencyClassifier now has a default value, which is ${empty.property}
On the generated project though, empty.property would be empty (if dependencyClassifier was not specified during the mvn archetype:generate call), because it exists as Maven property, with empty value, which makes the whole valid for Maven: the property value injected by the archetype is a declared property in the final pom and as such not breaking anything.
The classifier will hence have either dependencyClassifier value (specified at runtime) or empty.property (its default value), which is empty
An empty classifier is treated by Maven as no classifier, as such providing us both behaviors.
To summarize:
Invoking
mvn archetype:generate ... -DdependencyClassifier=something
Would effectively populate the classifier element with something, our desired classifier at runtime.
Instead, not specifying any value will leave classifier with ${empty.property}, that is, empty. An Maven will no look for any classifier (nor complain).
The only drawback of this approach is to keep an empty.property property for no much meaning in your final pom.xml, it's a trick which may shock some purists, but does the job.
I had a similar case and, applied to your use case, solved it like this:
In archetype-metadata.xml, define _UNDEFINED_ (or some other magic string) as the default value:
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor name="basic">
<requiredProperties>
<requiredProperty key="compilerVersion"/>
<requiredProperty key="dependencyClassifier">
<defaultValue>_UNDEFINED_</defaultValue>
</requiredProperty>
</requiredProperties>
</archetype-descriptor>
In the <dependency> section of the template pom.xml, use a VTL #if directive:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>artifact</artifactId>
<version>${dependencyVersion}</version>
#if( ${dependencyClassifier} != "_UNDEFINED_" )
<classifier>${dependencyClassifier}</classifier>
#end
</dependency>
</dependencies>
So your final pom.xml just does not contain a <classifier> definition at all if you omit -DdependencyClassifier=something with archetype:generate. Which I guess is definitely satisfying purists. Even if the code in the archetype itself may not.
Note: According to the dependency list of archetype-common, the current version 3.1.2 of Maven archetype plugin uses Apache Velocity Engine 1.7.

how is the properties set in this pom.xml?

This is the snippet of pom.xml from my project.
<properties>
<Port>2020</Port>
<threads>20</threads>
<test.suite />
<test.suite.path />
<useTag />
<useTestCase />
<args>-Dthreads=${threads} -Dtest.suite.path=${test.suite.path} -Dappenv=${test.app.env} -Dtest.suite=${test.suite} -DuseTag=${useTag} -DuseTestCase=${useTestCase}</args>
</properties>
when maven build is made, I am wondering how the variables test.suite, test.suite.path, useTestCase are set? I do not see it anywhere in the pom. but the Jenkins build is working fine and it has substituted values for these placeholders.
what is the use of using this kind of property setting. <variable/> rather than <variable>...</variable> ?
To say exactly how those properties are set in your case we need to see the entire pom structure including the parent pom(s) as well as your Jenkins job configuration.
However, I know of two ways that these properties can be set:
Through a profile in one of your parent poms
Through system properties when maven is invoked
My guess is that you have a profile in one of your parents that sets these properties. Something like this:
<profile>
<id>jenkins</id>
<properties>
<test.suite>...</test.suite>
...
</properties>
</profile>
And that this profile is activated on your Jenkins server. Look here for information how the profile can be activated.
The other option is that these properties are specified as system properties when maven is invoked from Jenkins.
As for why <variable/> is used over <variable></variable> it is a matter of taste. <variable/> means the same thing as <variable></variable> in XML.

Resources