I am trying to keep my java project compatible with java 17 but actually compile and ships the jars with Java 21 compatibility level.
The rationale being that I am releasing a new major version and I would like to have Java 21 for baseline, but it might be a problem for some users. So the idea is to ship in Java 21 but keep the sources compatible with 17 in order to be able to bring back Java 17 build in a minor release if a user cannot upgrade with a valid reason. If all the users can migrate to Java 21 without issue, I will be able to use Java 21 only features without having to wait for a new major version of my software.
I am puzzled when configuring maven-compiler-plugin
.
To ensure compatibility, the plan is:
maven-compiler-plugin
:<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source> 17 </source>
<target> 21 </target>
<release> 17 </release>
</configuration>
</plugin>
However, after reading What is the --release flag in the Java 9 compiler?, I am wondering if there will be a conflict between the release
flag and the others.
<profile>
<id>test-nightly</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source> 17 </source>
<target> 17 </target>
<release> 17 </release>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Am I configuring the maven-compiler-plugin
correctly ?
Thanks in advance
After some investigation, it is not possible to do via the java build flags.
The javac
documentation says:
Note: This can only be used when compiling for releases prior to JDK 9.
As applicable, see the descriptions in [--release](https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#option-release), [-source](https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#option-source), or [-target](https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#option-target) for details.
--release release
Compiles source code according to the rules of the Java programming language for the specified Java SE release, generating class files which target that release. Source code is compiled against the combined Java SE and JDK API for the specified release.
The supported values of release are the current Java SE release and a limited number of previous releases, detailed in the command-line help.
For the current release, the Java SE API consists of the java.*, javax.*, and org.* packages that are exported by the Java SE modules in the release; the JDK API consists of the com.* and jdk.* packages that are exported by the JDK modules in the release, plus the javax.* packages that are exported by standard, but non-Java SE, modules in the release.
For previous releases, the Java SE API and the JDK API are as defined in that release.
Note: When using --release, you cannot also use the [--source](https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#option-source)/-source or [--target](https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#option-target)/-target options.
Note: When using --release to specify a release that supports the Java Platform Module System, the --add-exports option cannot be used to enlarge the set of packages exported by the Java SE, JDK, and standard modules in the specified release
And especially the line Note: When using --release, you cannot also use the --source/-source or --target/-target options.
The solution I went for is based on:
mvn versions:set-property -Dproperty=maven.compiler.release -DnewVersion=21