February 9, 2009

Adding endorsements to Maven's plugins

Since Java 1.6 a number of libraries come piggybacking with the JDK installation. These are namely JAXB and JAX-WS, amongst others. Great in a way, however, if you previously built your project with Maven on Java 1.5, you may get worrying runtime exceptions when executing the build artifacts.

If you, just like me, ran into these obvious class path problems you will have to tell Maven to endorse dependencies on compile (and possibly when executing your unit tests).

Out of the box Maven doesn't seem to support this (I am using the latest 2.0.9), so I started to experiment a little and the solution turned out to be relatively straight forward and easy to implement.

Provided you already have a POM-file, simply add a profile called jdk16-override (or anything you like) and use the maven-dependency-plugin to copy the endorsed files automatically to a folder called endorsed.

Once the plugin has done it's job, you can reconfigure the maven-compiler-plugin and the maven-surefire-plugin to actually use the endorsement directory.

The following snippet of XML serves as a working example for JBossWS, however, it will work for any other library you may need to endorse:

<profiles>
<profile>
<id>jdk16-override</id>
<activation>
<jdk>1.6</jdk>
</activation>
<build>
<plugins>
<plugin>
<artifactid>maven-dependency-plugin</artifactid>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactitems>
<artifactitem>
<groupid>jboss</groupid>
<artifactid>jboss-jaxws</artifactid>
<version>4.3.0.GA</version>
<outputdirectory>${project.build.directory}/endorsed</outputdirectory>
</artifactitem>
<artifactitem>
<groupid>jboss</groupid>
<artifactid>jboss-jaxrpc</artifactid>
<version>4.3.0.GA</version>
<outputdirectory>${project.build.directory}/endorsed</outputdirectory>
</artifactitem>
<artifactitem>
<groupid>jboss</groupid>
<artifactid>jboss-saaj</artifactid>
<version>4.3.0.GA</version>
<outputdirectory>${project.build.directory}/endorsed</outputdirectory>
</artifactitem>
</artifactitems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
<compilerargument>-Djava.endorsed.dirs="${project.build.directory}/endorsed"</compilerargument>
</configuration>
</plugin>
<plugin>
<artifactid>maven-surefire-plugin</artifactid>
<configuration>
<argline>-Djava.endorsed.dirs="${project.build.directory}/endorsed"</argline>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

You may have noticed the profile's activation policy. It simply tells Maven that this profile should be activated automatically if the build is performed on version 1.6 of the JDK.

Finally, I should mention that the JBossWS dependencies provided in the example aren't in Red Hat's repository. They refer to artifacts which I have in my local repository as they belong to the enterprise version of JBoss.

And as usual: Good luck and enjoy!