Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile Maven Module with Different Java Version

Tags:

maven

My maven project has a few modules: server, web, etc.

I would like to build all but my server module on Java 6. For the server module, I'd like to compile it with Java 7.

Here's my pom.xml below, but I think that if I modify it to 1.7, then all of my modules will be compiled with Java 7. Also, does maven use the JAVA_HOME environment variable to determine which Java version to use?

    <plugin>         <groupId>org.apache.maven.plugins</groupId>         <artifactId>maven-compiler-plugin</artifactId>                         <version>2.3.2</version>         <configuration>             <source>1.6</source>             <target>1.6</target>             <memmax>2048m</memmax>         </configuration>     </plugin> 

EDIT Also, does the below output of

maven --version

indicate that maven is compiling my java code with 1.7?

vagrant@dev:~/bin/apache-tomcat-7.0.29/bin$ mvn --version Apache Maven 3.0.4 (r1232337; 2012-01-17 08:44:56+0000) Maven home: /home/vagrant/bin/apache-maven-3.0.4 Java version: 1.7.0_07, vendor: Oracle Corporation Java home: /home/vagrant/bin/jdk1.7.0_07/jre Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "3.2.0-23-generic", arch: "amd64", family: "unix" 

Thanks, Kevin

like image 324
Kevin Meredith Avatar asked Sep 13 '12 20:09

Kevin Meredith


People also ask

Does Maven support Java 11?

Maven ConfigurationThe Maven tool uses JDK version 11.0. 10. The default JDK is set to 13.0. 2.

Does Maven work with Java 17?

In case of Maven, we specify the compiler plugin to use Maven with Java 17. The next step is to basically upgrade the dependencies of our application.

Which plugin is useful for an Organisation where many projects are using different versions of Java?

Compiler plugin. The Compiler Plugin is used to compile the sources of your project. Sometimes when you may need to compile a certain project to a different version than what you are currently using. The javac can accept such command using -source and -target .

What Java version is Maven using?

Before moving on, we can check the default JDK version of Maven. Running the mvn -v command will show the Java version in which Maven runs.


2 Answers

There are a number of hacks out there for compiling source code with a different version of the JDK than you are using to run Maven, for example you can use something like

<project>   [...]   <build>     [...]     <plugins>       <plugin>         <groupId>org.apache.maven.plugins</groupId>         <artifactId>maven-compiler-plugin</artifactId>         <version>2.5.1</version>         <configuration>           <executable><!-- path-to-javac --></executable>         </configuration>       </plugin>     </plugins>     [...]   </build>   [...]  </project> 

The issue with this approach is that you now have hard-coded the path to the JDK into your POM. Everything will work just fine on your machine but when you have to rebuild your machine because the HDD failed, or when you want to build on a different machine, you will be stuck as the path will most likely not match up.

The correct best practice way to handle this is via Toolchains. This will see you creating a ~/.m2/toolchains.xml file that describes where each of the different toolchains in your system are. Then the version of the JDK can be applied by the Maven Toolchains Plugin, e.g.

<plugins>  ...   <plugin>     <groupId>org.apache.maven.plugins</groupId>     <artifactId>maven-toolchains-plugin</artifactId>     <version>1.0</version>     <executions>        <execution>         <phase>validate</phase>         <goals>           <goal>toolchain</goal>         </goals>       </execution>     </executions>     <configuration>       <toolchains>         <jdk>           <version>1.6</version>         </jdk>       </toolchains>     </configuration>   </plugin>   ... </plugins> 

The next thing is that you don't need this as often as you would think. For example by using the source and target values you can generate the correct bytecode for the JRE that you are targeting... the only issue that you will then hit is the use of methods that are new in JRE 1.7... which is where Mojo's Animal Sniffer Plugin comes in. Animal Sniffer can be used to ensure that you only use the methods of the JRE that you are targeting. The general community consensus is that the use of source and target configuration options in the Maven Compiler Plugin configuration coupled with the use of Mojo's Animal Sniffer virtually eliminates the need for toolchains on the Compiler end of things.... on the Surefire end of things there is still need for toolchains... and I have a few edge cases that I need to update the compiler plugin and the toolchains plugins for to handle but, realistically you will not hit those edge cases ;-)

Just to be sure that your original question is completely answered (since the above answers the question you wanted to ask - as opposed to the one you asked)

At present you are compiling with JDK 1.7 however depending on the version of the Maven Compiler Plugin you are using, you may be compiling with either <source>1.4</source><target>1.4</target> or <source>1.5</source><target>1.5</target> unless you have changed the configuration of the Maven Compiler Plugin in your pom.xml. That will dictate which language features are available to you, but not which classes... so you would be generating code that will work on JRE 1.7 and provided you have not used any new classes/methods introduced since 1.4/1.5 (Such as String.isEmpty()) should also work on JRE 1.4/1.5... the only way to be sure if it works on such an old JVM is to either: run it on the old JVM OR use Animal Sniffer.

like image 155
Stephen Connolly Avatar answered Oct 07 '22 09:10

Stephen Connolly


Maven Toolchains

To use multiple Java versions, you need to use Maven Toolchains, which require you to create a toolchains.xml file in your ~/.m2 Maven folder, containing all Java versions installed on your machine:

<toolchains>   <toolchain>     <type>jdk</type>     <provides>       <id>Java13</id>       <version>13</version>     </provides>     <configuration>       <jdkHome>${env.JAVA_HOME_13}</jdkHome>     </configuration>   </toolchain>   <toolchain>     <type>jdk</type>     <provides>       <id>Java9</id>       <version>9</version>     </provides>     <configuration>       <jdkHome>${env.JAVA_HOME_9}</jdkHome>     </configuration>   </toolchain>   <toolchain>     <type>jdk</type>     <provides>       <id>Java8</id>       <version>8</version>     </provides>     <configuration>       <jdkHome>${env.JAVA_HOME_8}</jdkHome>     </configuration>   </toolchain>   <toolchain>     <type>jdk</type>     <provides>       <id>Java7</id>       <version>7</version>     </provides>     <configuration>       <jdkHome>${env.JAVA_HOME_7}</jdkHome>     </configuration>   </toolchain>   <toolchain>     <type>jdk</type>     <provides>       <id>Java6</id>       <version>6</version>     </provides>     <configuration>       <jdkHome>${env.JAVA_HOME_6}</jdkHome>     </configuration>   </toolchain> </toolchains> 

The JAVA_HOME_13, JAVA_HOME_9, JAVA_HOME_8, JAVA_HOME_7, JAVA_HOME_6 environment variables are configured so that they reference the path where the associated Java version is installed.

The FlexyPool parent pom.xml configuration file

The parent pom.xml Maven configuration file of the FlexyPool project defines the global Java version settings

<properties>     <jdk.version>8</jdk.version>     ... </properties> 

Now, we need to instruct both the compiler and the test plugins to use the configured java version.

<build>     <plugins>         <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-toolchains-plugin</artifactId>             <version>1.1</version>             <executions>                 <execution>                     <goals>                         <goal>toolchain</goal>                     </goals>                 </execution>             </executions>             <configuration>                 <toolchains>                     <jdk>                         <version>${jdk.version}</version>                     </jdk>                 </toolchains>             </configuration>         </plugin>                  <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-compiler-plugin</artifactId>             <version>${maven-compiler-plugin.version}</version>             <configuration>                 <source>${jdk.version}</source>                 <target>${jdk.version}</target>                 <showDeprecation>true</showDeprecation>                 <showWarnings>true</showWarnings>             </configuration>         </plugin>                  <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-surefire-plugin</artifactId>             <version>${maven-surefire-plugin.version}</version>         </plugin>     </plugins> </build> 

The FlexyPool child Maven module pom.xml using a different Java version

The flexy-pool-core-java9 child Maven module that requires a different Java version only needs to override the default jdk.version Maven property:

<properties>     <jdk.version>9</jdk.version> </properties> 

And that's it, we can now build each module using its own minimum viable Java version.

like image 32
Vlad Mihalcea Avatar answered Oct 07 '22 08:10

Vlad Mihalcea