Maven and Java multi-version modules

Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Wouldn’t that be just awesome?

Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, or Play Framework.

So, enjoy spending your time on the things you love rather than fixing performance issues in your production system on a Saturday night!

Introduction

In this article, you are going to learn how to configure Maven to choose a specific Java version when the OS has multiple Java versions installed.

For instance, FlexyPool uses Java 8 for all modules, except for the flexy-pool-core-java9 module that needs to be built using Java 9.

Using Maven Toolchains to define multiple Java versions

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>Java17</id>
      <version>17</version>
    </provides>
    <configuration>
      <jdkHome>${env.JAVA_HOME_17}</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_17, 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 parent pom.xml Maven configuration defining a default Java version

The parent pom.xml Maven configuration file 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 child Maven module pom.xml using a non-default 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.

Conclusion

Using multiple Java versions is a common requirement when developing open-source frameworks that target a wide range of project environments. Thanks to the Maven Toolchains plugin, this task is very easy to address.

Transactions and Concurrency Control eBook

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.