Sunday, September 21, 2008

Compile and test with different JDK with a Maven project

If you ever have the need to compile and run tests of your Maven project with different JDK, here are some tips:

1. The cheapest way



Maven by default use your JAVA_HOME to compile the project and then run the tests.
So if want to run your tests with different jdk, just set your JAVA_HOME to the jdk of your desire. Here's a neat treat in Bash to set an env variable locally to the current process.

Assume you have environment variables JAVA_HOME_15 and JAVA_HOME_16 pointing to their respective jdk1.5 and jdk1.6, you can then do this:


%> JAVA_HOME=$JAVA_HOME_15 mvn install # run with 1.5
%> JAVA_HOME=$JAVA_HOME_16 mvn install # run with 1.6


2. The Maven way

(hairy verbose and messy pom.xml profiles)

This only works with Maven-2.1.0-M1. Failed with 2.0.9 for me

You have to specify which JDK you want for 2 of these plugins: maven-compiler-plugin and maven-surefire-plugin.


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable>${jdk}/bin/javac</executable>
<compilerVersion>1.5</compilerVersion>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<jvm>${jdk}/bin/java</jvm>
<forkMode>once</forkMode>
</configuration>
</plugin>
</plugins>
</build>


So you see I use the property ${jdk} Now we just need to define a profile for each of the JDK we want and set the ${jdk} appropriately.


<profiles>
<profile>
<id>default_jdk</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jdk>${env.JAVA_HOME}</jdk>
</properties>
</profile>
<profile>
<id>jdk15</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdk>${env.JAVA_HOME_15}</jdk>
</properties>
</profile>
<profile>
<id>jdk16</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<jdk>${env.JAVA_HOME_16}</jdk>
</properties>
</profile>
</profiles>


Above I defined 3 profiles. The first one is the default one. It's a trick to set ${jdk} to $JAVA_HOME so that Maven knows what to use if you don't specify any profile to run.

Here how you would activate each profile:


%> mvn install # no profile so by default run tests with JAVA_HOME
%> mvn install -Pjdk15 # run with jdk1.5
%> mvn install -Pjdk16 # run with jdk1.6


Note that in the profile I use env variables JAVA_HOME_15 and JAVA_HOME_16 also. You can of course fill in an absolute path to your JDK.

So there you have it. Took me awhile to figure out.

6 comments:

Alex Miller said...

And people say Maven is complicated.... :)

Jean-Francois Poilpret said...

Hi, seems interesting but do you have an idea why it doesn't work with maven 2.0.x? Any idea of a workaround (I don't feel like upgrading to 2.1 yet)?

kukudas said...

Hi nice Post i have one question: Would it not be easier to specifie in the configuration of the maven-compiler-plugin a source and target with lets say ${version} and use your profiles with the diffrence that a property version gets set for jdk 1.5 with 1.5 as example. Maybe i'm missing something would be nice to get feedback on my thought.

Unknown said...

@Jean-Francois

I haven't a clue why it's failing with 2.09

@kukudas

You seem confused about runtime JDK and compile JDK. Setting "source=1.5" doesn't change the fact that it's being compiled with JDK1.6 for example.

Anonymous said...

I've seen numerous articles of how to configure the maven compiler plugin to use an external javac, but what about all these other mojos that spit out class files directly? One example is the Codehaus Weblogic plugin: when run under Java5, it spits out Java5 classes directly. I'm having a hard time to get my build system correctly configured to run under Java5 (Hudson requirement for its Maven integration), but remain 1.4 compatible with all the built artifacts. Luckily I found this Maven plugin: http://animal-sniffer.dev.java.net

merve t said...

thanks, extremely useful.