My project is currently in ant and we want to migrate to maven. We have to support both java 6 and java 11 build for different servers (Our codebase is compatible with java 6 and above). Java 6 is using old jar files while Java 11 has new jar files. We want to compile project with both java 6 and 11 with their own set of jars. (Final build as two different EAR) Is it possible to achieve this in maven, if yes then how?
Edit: To make myself clear, I do not have code which needs java 7 and above to compile. My codebase if fully compatible with java 6 and above. I just need to compile it with java 11 with newer dependencies to run it on newer version of server while supporting java 6 for old server, Thus one EAR with java 6 and another with java 11. We will be eventually moving to only support java 11 when all of our customer moves to new server.
I would go for a multi-module project that contains two modules for the two EARs, and additionally modules for the JARs you want to build.
Then you can set the Java version to 6 in one EAR and to 11 in the other one.
First of all you will need different compilers. There is a limitation in backwards compatibility. As far as I remember Oracle JDK supports current minus two major release. Thus JDK 11 javac can compile JDK 8 incl. The first snippet thus – I assume – is something like:
<properties>
<java.version>11</java.version>
</properties>
This setting can only occur once per (simple) pom.xml as it will affect maven-compiler-plugin
to set source and target. Again I assume you have a source directory with JDK 6 code and another source directory with JDK 11 code. And your goal is to have all the JDK 6 sources in a compatible way bound to one EAR. At the same time your JDK 11 sources end up in a different EAR and must resemble JDK 11 bytecode.
It is something totally different to have JDK 11 source compiled for a JDK 8 target – still incompatible with a JDK 6 VM. I also assume it is not wanted and also not easy to turn your JDK 11 sources into JDK 6 bytecode through compiler only.
Next I assume you have at least one shared element in classpath for both EARs. It can be your own API JAR or an an external library. Such a dependency would end up in dependencyManagement
of the so called parent pom. This is the same pom that contains all module definitions.
Third you'll need to define a groupId and various artifactIds. I strongly urge you to express the JDK affinity at least in the artifactId. Then you can express dependencies based on JDK affinity. A skeleton (parent) pom.xml might look like this:
<project>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release</artifactId>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>sample-cross-release-api</module>
<module>sample-cross-release-source6</module>
<module>sample-cross-release-source11</module>
<module>sample-cross-release-war6</module>
<module>sample-cross-release-war11</module>
<module>sample-cross-release-ear6</module>
<module>sample-cross-release-ear11</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency><!-- necessary for 6 and 11 source/ WAR/ EAR -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-api</artifactId>
<version>${project.version}</version>
<dependency>
<dependency><!-- only 6 is shown, 11 looks the similar -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-sources6</artifactId>
<version>${project.version}</version>
<dependency>
<dependency><!-- only 6 is shown, 11 looks the similar -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-war6</artifactId>
<version>${project.version}</version>
<dependency>
</dependencies>
</dependencyManagement>
</project>
I omit the source and WAR-part. But it has a dependency
on sample-cross-release-sources6
and the -api, too. The EAR's pom.xml would look like this:
<project>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-ear11</artifactId>
<version>1.0.0-SNAPSHOT</version>
<parent>
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency><!-- does not need version, determined by parent -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-api</artifactId>
<dependency>
<dependency><!-- does not need version, determined by parent -->
<groupId>com.stackoverflow</groupId>
<artifactId>sample-cross-release-war6</artifactId>
<dependency>
<!-- other dependencies, like logging, persistence... -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compile.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
And the project structure will look like this in the file system:
|
+-- pom.xml (parent)
+-- sample-cross-release-api
| +-- pom.xml
| +-- src/main/java
| +-- src/main/resources
| ...
...
+-- sample-cross-release-ear11
+-- pom.xml
...
Finally I urge you to have totally separate JDK 6 and JDK 11 code bases/ projects/ pom.xml-s. Do not merge them with a parent pom. You will end up in dependency hell as soon as you try to setup (Maven-) profiles supporting release plugins for different JDKs/ toolchains. It might work for simple cases. It will break as soon as you bring in static code analysis, surefire/ failsafe and presumably WAR- and EAR-creation. (I assume a JDK 6 EAR is built with a matching JEE dependency which differs from the JEE for JDK 11. This in turn forces the use of compatible Maven plugins – different per JDK.)
And you never know: there will be an application server running on JDK 11 that prohibits reflective access in a third party library that somehow ended up in your 11's EAR classpath. Play safe from the start, tear the different JDKs apart and check twice carefully.
What I omitted for brevity:
And normally a parent pom is contains a lot of dependencyManagement
and pluginManagement
so all module poms can omit versions and detailed configuration. Your approach goes against this, forcing a JDK 6 branch and a JDK 11 branch through the same parent. It is always forced from parent onto modules and the latter cannot alter or cherry pick.
If there isn't a real trade-off to switch from Ant to Maven, don't do it. Maven requires a lot by contract, esp. when it comes to file system layout vs. artifact content – to build a WAR/ an EAR you either need to follow the rules or have a lot of plugin-configuration.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.