Accessing configuration value from another configuration in the Maven Release plugin - maven

Is it possible in Maven to access a configuration value from another configuration value? For example, in the Release Plugin it is possible to access the project.version key during configuration of the tagNameFormat element. What I would like to do is to then use the tagNameFormat value in another element named completionGoals. See below:
<!-- Snippet from a POM -->
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<tagNameFormat>${my.pom.property}#{project.version}-${my.pom.property.extra}</tagNameFormat>
<checkModificationExcludes>
<checkModificationExclude>pom.xml</checkModificationExclude>
</checkModificationExcludes>
<completionGoals>clean verify help:evaluate -Dexpression=${tagNameFormat}</completionGoals>
</configuration>
<executions>
<execution>
<id>default</id>
<goals>
<goal>prepare</goal>
<goal>perform</goal>
</goals>
<configuration>
<pomFileName>${release.pom.path}pom.xml</pomFileName>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
Notably, in the above configuration, I can see that the tagNameFormat itself is populated with both the standard POM version property and my own custom property (that incidentally is runtime-defined at the command-line). However, when I try to access the value to define another configuration element, completionGoals, completionGoals appears as a variable placeholder, e.g. "${tagNameFormat}" literally appears in the resulting command. (Verified by running Maven with the -X and -e flags.)
Question(s):
Is it possible to get a populated plugin configuration value from the Maven plugin configuration in the POM?
Am I referring to the tagNameFormat configuration element correctly? How could I do this with the Release plugin?
What does the '#' versus the '$' mean? (Guess: Dynamically versus statically evaluated?)

The only way I'm aware of is to define another POM property:
<property>
<my.pom.property>...</my.pom.property>
<my.pom.property.extra>...</my.pom.property.extra>
...
<myTagNameFormat>${my.pom.property}#{project.version}-${my.pom.property.extra}</myTagNameFormat>
</property>
and to use it accordingly:
<tagNameFormat>${myTagNameFormat}</tagNameFormat>
...
<completionGoals>clean verify help:evaluate -Dexpression=${myTagNameFormat}</completionGoals>
Re 3.: AFAIK, the variable delimiters ${...} and #...# are equivalent and I've never read or heard the contrary. But, to be honest, I've never ever used #...# since I'm used to ${...} from Bash and that's also the only one mentioned on the Filter doc page. (#...# is only mentioned at Escape filtering and such I didn't know that it even exists for a long time.)

Related

Use maven filtering in server.xml without breaking mvn liberty:dev

I would like to use maven filtering, in my src/main/liberty/config/server.xml without breaking the use of liberty:dev from the maven-liberty-plugin. My biggest problem seems to be that the liberty-maven-plugin does not honor filtering.
For example, consider this webApplication element:
<webApplication id="${project.artifactId}" contextRoot="/"
location="${server.config.dir}/apps/${project.artifactId}.war">
</webApplication>
Without any other guidance, this file is copied to target/liberty/wlp/usr/servers/defaultServer/server.xml without any filtering, so the runtime cannot find the WAR file.
Let's say I manually turn on the filtering using maven-resources-plugin:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>01-liberty-config</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/liberty/wlp/usr/servers/defaultServer</outputDirectory>
<resources>
<resource>
<directory>src/main/liberty/config</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Now the filtering works and the file is in the correct location. Unfortunately, I observe that when I run mvn liberty:dev, this gets overwritten by the unfiltered server.xml from src/main/liberty/config/server.xml.
Is it possible to use maven filtering in a server.xml?
BACKGROUND
This is essentially not supported today. The liberty-maven-plugin doesn't let you do this, and the way in which the liberty-maven-plugin manages and controls the Liberty config also doesn't make it easy for you to use standard Maven plugins like 'dependency' or 'resources' plugin either.
Since this issue was raised before I shared a sample approach which you might find useful, though it has the feel of a workaround.
SOLUTION OVERVIEW
Basically, although although we can't substitute into server.xml itself via filters we can substitute into a config snippet that gets included by server.xml, and copy this into place using the resources plugin, rather than liberty-maven-plugin.
SOLUTION DETAIL
Say I wanted to use a "filter"-style Maven variable substitution ${tidal.url} for a URL in Liberty server config.
1. src/main/filtered-config/environment.xml
First define a config snippet, which we are going to apply the filter to.
<server description="environment">
<!-- Expect to come from filter -->
<variable name="tidal.url" value="${tidal.url}"/>
</server>
2. pom.xml
Configure an execution of resources:copy-resources copying the "environment.xml" snippet above to the shared config dir location, target/liberty/wlp/usr/shared/config, with filtering enabled:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>default-cli</id>
<phase>none</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<!-- This location can persist across a server recreate, where the refresh can annoyingly wipe out your earlier copy -->
<outputDirectory>target/liberty/wlp/usr/shared/config</outputDirectory>
<resources>
<resource>
<directory>src/main/filtered-config</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
3. server.xml
In your main server.xml config file, add an <include> of the config snippet you copied into the shared config dir via "copy-resources".
Also shown is how we finally use or "consume" the value applied via the filter, here in this <jndiEntry>, in this sample:
<include location="${shared.config.dir}/environment.xml"/>
<!-- This is how I'm ultimately going to "consume" the filtered value -->
<jndiEntry jndiName="url/tidal-api" value="${tidal.url}" id="TidalJNDI" />
4. Run dev mode, invoking the extra goal first, and activating your filter somehow
E.g.:
mvn resources:copy-resources liberty:dev
As far as activating your filter, maybe you have a filter defined in your build (via build.filters.filter like in my sample repo) or maybe you're just using -Dtidal.url=<value>.
FOLLOW-UP
Besides being complicated a significant limitation of the above is that you only get a single chance to apply the filter. You cannot iterate through different values in a single dev mode "session".
Feel free to give feedback on the issue: https://github.com/OpenLiberty/ci.maven/issues/587
Also I will note we are considering enhancing filter support for general resources and web resources here.
ONE MORE THOUGHT
If all you need is a dynamic way to select, at build time, one set of Liberty config values vs. another you don't necessarily need to use filtering.
You could instead use the support which maps Maven properties to Liberty config.
E.g. for this example you could have one profile which defines
<properties>
<liberty.var.tidal.url>URL1</liberty.var.tidal.url>
</properties>
and another profile defining the same property with a different value.
This would parameterize my sample:
<jndiEntry jndiName="url/tidal-api" value="${tidal.url}" id="TidalJNDI" />
just fine.
The problem though is if you wanted to use the same sets of properties in other contexts with other plugins that did fully support filtering. Then, you want standard Maven filtering.

${surefire.forkNumber} always resolving as null

I am using ${surefire.forkNumber} in system property in my pom. According to maven documentation, it should be resolved to the number of fork that is currently running. But it is resolving as null.
Below is snippet of my pom file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<systemPropertyVariables>
<database.name>My_Test_Schema_${surefire.forkNumber}</database.name>
</systemPropertyVariables>
</configuration>
</plugin>
Am I missing anything?
Please, anybody throw some light...
It might be that ${surefire.forkNumber} is substituted twice: first by maven-core, and then by surefire. Since maven-core doesn't know about this property, it substitutes null there.
Solution: protect from first substitution by quoting $:
<systemPropertyVariables>
<database.name>My_Test_Schema_$${surefire.forkNumber}</database.name>
</systemPropertyVariables>
Source: http://maven.40175.n5.nabble.com/SureFire-2-16-doesn-t-respect-forkCount-td5771850.html#a5771855
This one worked for me --- I had the same problem. It's a pity this isn't documented.
Pass setting via VM -D within argLine:
<argLine>-Ddatabase.name=My_Test_Schema_${surefire.forkNumber}</argLine>
I found systemPropertyVariables to be quite fragile. See SureFire 2.16 doesn't respect forkCount (which didn't work for me one way or the other using surefire 2.17).
You can use the place holder ${surefire.forkNumber} within argLine, or within the system properties
You should pass the value to place holder either these three ways..
1. command line argument like mvn test -Dsurefire.forkNumber=8
2. set by systemPropertyVariables System.setProperty("surefire.forkNumber",8);
3. set by pom properties tag like
<properties>
<surefire.forkNumber>8</surefire.forkNumber>
</properties>

Configure maven-license-plugin to use excludedGroups correctly

When this plugin is attached to the test or package phase, it causes a multi module build to break since it forces dependency resolution before the module dependencies are in the local repository (first build upon updating to a new snapshot version). I'm trying to get the plugin to ignore the offending com.cons3rt group dependencies which are not required for license output. Tried several variations of:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>aggregate-add-third-party</id>
<configuration>
<excludedGroups>com.cons3rt</excludedGroups>
</configuration>
<phase>package</phase>
<goals>
<goal>aggregate-add-third-party</goal>
</goals>
</execution>
</executions>
Nothing seems to work - looking at the output of mvn -X, it seems like the plugin is not honoring the configuration setting for excludedGroups. Anyone have any luck using this configuration approach?
In your configuration use a pipe to separate multiple groupIds and set the .* to refer to all sub packages:
<excludedGroups>com.group1.*|com.group2.*</excludedGroups>
A workaround for this problem is to pass the parameter through the command line using the
-Dlicense.excludedGroups
parameter.
e.g. mvn package -Dlicense.excludedGroups=com.jhla.*
Simply Change
<excludedGroups>com.cons3rt</excludedGroups>
to
<excludedGroups>^com\.cons3rt</excludedGroups>
as the given string needs to be a regular expression.
For further information, see documentation at:
http://www.mojohaus.org/license-maven-plugin/aggregate-add-third-party-mojo.html

Varying plugin configuration for each child module

I have a multi-module build which contains modules which can target either Java 5 or Java 6. I want to allow modules to opt-in to Java 6, and leaving the default to 5.
To set Java 5 as a target I need to configure the following:
maven-compiler-plugin: source and target set to 1.5
maven-bundle-plugin: configure the Bundle-RuntimeExecutionEnvironment to J2SE-1.5
To set Java 6 as a target I need to configure the following:
maven-compiler-plugin: source and target set to 1.6
maven-bundle-plugin: configure the Bundle-RuntimeExecutionEnvironment to JavaSE-1.6
I considered having two properties: java.compiler.source and osgi.bree which can be defined by each module, but this leaves place for error.
How can I override the configuration of these two plugins per module with a single switch?
I would personally structure your project so that Java 5 modules descend from one parent POM and Java 6 modules from another parent POM.
Global Parent (majority of global settings)
Java5 parent (just define source/bundle)
module A
module B
Java 6 parent (just define source/bundle)
module C
How about allowing child modules to set a my.java.version property (or whatever you want it named) and embedding a Groovy script that sets version properties for the compiler and bundle plugins? Something like this in the parent pom:
<project ...>
...
<properties>
<my.java.version>1.5</my.java.version> <!-- default Java version -->
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<!-- set up properties in an early lifecycle phase -->
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<!-- this can be as simple or complex as you need it to be -->
<source>
if (project.properties['my.java.version'] == '1.6') {
project.properties['my.compiler.version'] = '1.6'
project.properties['my.execution.environment.version'] = 'JavaSE-1.6'
}
else {
project.properties['my.compiler.version'] = '1.5'
project.properties['my.execution.environment.version'] = 'J2SE-1.5'
}
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!-- now use the properties from above in the plugin configurations -->
<!-- assume that both of these plugins will execute in a phase later than 'initialize' -->
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${my.compiler.version}</source>
<target>${my.compiler.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<!-- sorry if this part isn't correct; never used this plugin before -->
<instructions>
<Bundle-RuntimeExecutionEnvironment>${my.execution.environment.version}</Bundle-RuntimeExecutionEnvironment>
</instructions>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
I don't think there is an elegant Maven way to solve this complex scenario, neither yours or Duncan's proposed solution are easy maintainable IMO, when number of sub module becomes tremendous.
For maximum maintainability, I would write shell script (and/or batch file on Windows) in case Maven can't do the job very well, for example, a set-version.sh (and set-version.bat) that loop all sub module and reset the default java.compiler.source and osgi.bree properties based on a version-feed.txt, the version-feed.txt gives you a single central place for manipulating your version varying. As you can see, the cons is this is really not a Maven solution, it requires running set-version.sh before mvn ... every time version customization is required.
In addition, For build/release standardization, I would use maven-enforcer-plugin to play/pause the build process based on a property version.set(which is flagged by set-version.sh) and prompt some warning/error message if developer is not follow the correct procedure when doing build. The version.set also gives the flexibility if you prefer to use the default values defined in every sub module, instead of running set-version.sh, just directly set it to true in the parent pom.xml or from command-line parameter.
Sample directory structure:
parent/
module-a/
module-b/
module-c/
... ...
pom.xml
set-version.sh
set-version.bat
version-feed.txt
Hope this make sense.

mvn release:perform automatically specify scm tag that includes release version

I would like to setup my maven release to run in batch mode, but I'm not a fan of the default scm tag ${artifactId}-${releaseVersion}. Instead, I'd like to simply tag it with ${releaseVersion}; however, I'm unclear if such a property exists (ie. without the -SNAPSHOT suffix).
I'd like the configuration to resemble the code below. Is such a default tagging possible with the maven-release-plugin?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.0</version>
<configuration>
<tag>${releaseVersion}</tag>
</configuration>
</plugin>
I just got this to work when using Hudson to do my release. I noted that Hudson (with the Maven Release Plugin) is initiating the command with a property like -Dproject.rel.com.example:my-artifact-id=1.0.1. Using the following plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<tag>REL-${project.rel.com.example:my-artifact-id}</tag>
</configuration>
</plugin>
Resulted in the tag being REL-1.0.1
I'm new to the release plugin but I would assume something similar would work from the command line.
You can pass in the properties for:
releaseVersion -- What version you want it to be released as (1.0)
developmentVersion -- The next version (2.0-SNAPSHOT)
tag -- The name of the tag
a 1.0-SNAPSHOT implies a 1.0 release version, but doesn't set it. You can set that property in your POM file as a regular property.
try this:
<configuration>
<tag>${project.version}</tag>
</configuration>

Resources