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!

6 comments:

Bhakti Mehta said...

Very helpful blog Just a small correction the id's in groupid and artifactid should be groupId and artifactId

Dave Moten said...

useful stuff but yeah mixed case has been lost everywhere,

Adrian Cole said...

note that you need to set your compiler plugin to fork = true

Anonymous said...

Thanks -- this did the trick.

Some other camelbackies needed to be fixed too though:

groupid -> groupId
artifactid -> artifactId
artifactitem -> artifactItem
artifactitems -> artifactItems
outputdirectory -> outputDirectory
argline -> argLine

(the latter was the trickiest as Maven was silent about it)

Thanks again
/Kalle

Anonymous said...

Very useful when using RI (com.sun.xml.ws) above the version supported in 1.6 too. Thanks for the post. Saved me some time. I actually changed it to copy-dependencies goal and then used includeGroupIds to get what I wanted.

Peter Faller said...

Very helpful for using JAX-WS 2.2 generated code with JDK 1.6. Thanks!