Setting Maven Properties With Groovy
Goal
While I generally try to configure, rather than script, Maven builds, sometimes the publicly-available plug-ins do not provide enough flexibility to work-around limitations in third-party libraries through configuration alone. Fortunately, GMaven exposes the flexibility of Groovy in a Maven plug-in. This post demonstrates how to use a Groovy script to transform a Maven project property. Such a transformation is sometimes necessary, for example, for transforming a Windows-style path to Unix. For myself, I formalized this solution while trying to install a jar in PostgreSQL automatically during the artifact deployment phase.
Display a Maven Project Property
We can start by creating a simple m2eclipse project, by adding a single property with a default value and by configuring the pom.xml to display this property on the console during a lifecycle event (here, during compilation).
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>timezra.blog.maven.groovy.properties</groupId>
<artifactId>timezra.blog.maven.groovy.properties</artifactId>
<name>timezra.blog.maven.groovy.properties</name>
<version>0.0.1-SNAPSHOT</version>
<description>An example of setting Maven properties using Groovy.</description>
<properties>
<unixy_build_directory>${project.build.directory}</unixy_build_directory>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>show-unixy_build_directory!</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>unixy_build_directory: ${unixy_build_directory}</echo>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
If we run the compile goal, we will see the bound Maven property in the build output.
….
[INFO] [antrun:run {execution: show-unixy_build_directory!}]
[INFO] Executing tasks
[echo] unixy_build_directory: C:\programming\workspaces\blog\timezra.blog.maven.groovy.properties\target
[INFO] Executed tasks
….
Setting up the gmaven-plugin is straightforward, as is re-binding the property with Groovy in the pom.xml.
….
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<executions>
<execution>
<id>set-unixy_build_directory!</id>
<phase>compile</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<classpath>
<element>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</element>
</classpath>
<source>
if (org.apache.commons.lang.SystemUtils.IS_OS_WINDOWS) {
project.properties.unixy_build_directory =
project.build.directory.replace("\\", "/");
}
</source>
</configuration>
</execution>
</executions>
</plugin>
….
</plugins>
</build>
</project>
NB: This example takes a Windows file path and transforms the backslashes to forward slashes. If you are not running Windows, then this example is moot. Please, experiment with the bindings in the pom.xml to demonstrate clearly to yourself that the property has really, really, really been re-bound.
When compiling, we will now see output indicating that the Groovy script has mutated the Maven property.
….
[INFO] [antrun:run {execution: show-unixy_build_directory!}]
[INFO] Executing tasks
[echo] unixy_build_directory: C:/programming/workspaces/blog/timezra.blog.maven.groovy.properties/target
[INFO] Executed tasks
….
Conclusion
With a few lines of configuration and a simple Groovy script, we are able to modify Maven properties as part of a lifecycle event. This tool adds even more power to your Maven builds, but, as stated above, it should be used cautiously and only when absolutely necessary. If there is a solution already in the Maven toolkit, then that is generally better. Not all project requirements fit in the box, however, and this example exposes a simple way to handle the non-ideal.
