简体   繁体   中英

How to build two different EAR in maven for with same java files in JAVA 6 and JAVA 11 with different jars for both java version?

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:

  • transitive dependencies/ good style to write poms
  • maven-enforcer-plugin to have reproducible builds
  • usage of WAR- and EAR-Maven-plugins since they differ dramatically between versions for JDK-6 and -11 on how to setup the classpath
  • using toolchains so all developers have a common platform, may spread to build nodes
  • recommendations regarding jdeps which is partly broken because of the Maven plugin and partly because of treatment for multi-release jARs (that will show up with JDK 11 dependencies)
  • Maven profiles that allow command line switches to alter build behavior
  • releasing through Maven introducing funny quirks based on JDK, Maven and your SCM.
  • static code analysis, PMD is one of the most flexible that will run in this setup even having the same ruleset for both JDKs while others might not or at least not easily (Coverity, Sonarqube, CAST, …)
  • security checks, org.owasp:dependency-check-maven will trigger a lot of warnings in JDK 6 branch, some libraries don't evolve anymore for this target JDK

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM