Maven exec plugin with toolchain can not enable preview features
Asked Answered
C

2

1

I want to taste the newest Java 19 feature, also do not change the default Java Home( Java 17).

So I create a toolchains.xml in the ~/.m2, and define a jdk type toolchain like this.

<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
  <!-- JDK toolchains -->
  <toolchain>
    <type>jdk</type>
    <provides>
      <version>1.8</version>
      <vendor>oracle</vendor>
    </provides>
    <configuration>
      <jdkHome>D:/jdks/jdk8</jdkHome>
    </configuration>
  </toolchain>
  <toolchain>
    <type>jdk</type>
    <provides>
      <version>11</version>
      <vendor>oracle</vendor>
    </provides>
    <configuration>
      <jdkHome>D:/jdks/jdk11</jdkHome>
    </configuration>
  </toolchain>
   <toolchain>
    <type>jdk</type>
    <provides>
      <version>17</version>
      <vendor>oracle</vendor>
    </provides>
    <configuration>
      <jdkHome>D:/jdks/jdk17</jdkHome>
    </configuration>
  </toolchain>
    <toolchain>
    <type>jdk</type>
    <provides>
      <version>19</version>
      <vendor>oracle</vendor>
    </provides>
    <configuration>
      <jdkHome>D:/jdks/jdk-19</jdkHome>
    </configuration>
  </toolchain>
  <!-- other toolchains -->
  <toolchain>
    <type>netbeans</type>
    <provides>
      <version>15</version>
    </provides>
    <configuration>
      <installDir>D:/devtools/netbeans</installDir>
    </configuration>
  </toolchain>
</toolchains>

Then I added the following plugins in my project POM.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.10.1</version>
    <configuration>
        <compilerArgs>
            <arg>--enable-preview</arg>             
        </compilerArgs>
        <encoding>${project.build.sourceEncoding}</encoding>
    </configuration>
</plugin>
<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>19</version>
                <vendor>oracle</vendor>
            </jdk>
        </toolchains>
    </configuration>
</plugin>
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <mainClass>com.example.demo.RecordPatternExample</mainClass>
        <commandlineArgs>--enable-preview</commandlineArgs>
        <arguments>
            <argument>--enable-preview</argument>
        </arguments>
    </configuration>
</plugin>

As suggested in this question, I also added --enable-preview to the .mvn/jvm.config.

But when running the project in command line.

mvn clean package exec:java

I still got the exception like this.

[INFO] --- maven-compiler-plugin:3.10.1:compile (default-compile) @ record-pattern ---
[INFO] Toolchain in maven-compiler-plugin: JDK[D:/jdks/jdk-19]
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\hantsylabs\java-sandbox\record-pattern\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ record-pattern ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\hantsylabs\java-sandbox\record-pattern\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.10.1:testCompile (default-testCompile) @ record-pattern ---
[INFO] Toolchain in maven-compiler-plugin: JDK[D:/jdks/jdk-19]
[INFO] Changes detected - recompiling the module!
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ record-pattern ---
[INFO] Toolchain in surefire-plugin: JDK[D:/jdks/jdk-19]
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ record-pattern ---
[INFO] Building jar: D:\hantsylabs\java-sandbox\record-pattern\target\record-pattern-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- exec-maven-plugin:3.1.0:java (default-cli) @ record-pattern ---
[WARNING]
java.lang.UnsupportedClassVersionError: com/example/demo/RecordPatternExample has been compiled by a more recent version of the Java Runtime (class file version 63.65535), this version of the Java Runtime only recognizes class file versions up to 61.0

Obviously the --enable-preview option was not applied with exec:java and toolchain configured JDK, but it worked well with maven-compiler-plugin.

The sample project is shared on my Github.

Catercorner answered 23/9, 2022 at 16:20 Comment(9)
toolchain.xml or toolchains.xml? should be the latter, but you wrote the former. did the compiler plugin pick up your toolchain configuration?Crimpy
Yes, it is toolchains.xml. The compiler plugin is working well and picked up the --enable-preview arguments. But there is no way to make exec plugin working as expected.Catercorner
the error message does not seem to be about not having --enable-preview, but not using toolchain configuration altogether. However, if compiler plugin picked up the new toolchain, so should exec:java.Crimpy
is your toolchains.xml somewhere in its entirety? don't see it in the github repoCrimpy
can you also please try running mvn toolchains:toolchain exec:java and see if that worksCrimpy
Did not work. I have run the mvn clean package exec:java again, and updated the whole log of compile, testCompile and test, and exec:java, it seems exec does not run against the toolchain configured JDK.Catercorner
From the exec plugin doc, jdk type toolchain should be enabled by default.Catercorner
did you add your full toolchains.xml somewhere so we can see it?Crimpy
@Crimpy Updated and pasted my complete toolchains.xml.Catercorner
C
1

Investigated this, and to me it seems this cannot be done: exec:java doesn't seem to have toolchains support. If you look at ExecJavaMojo source code which is used for exec:java, you see it has no references to toolchain, so it can't work. Compare that with ExecMojo source code that has them.

If you change your configuration to use exec:exec instead, setup should work:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>3.1.0</version>
    <configuration>
        <executable>java</executable>
        <arguments>
            <argument>--enable-preview</argument>
            <argument>-classpath</argument>
            <classpath/>
            <argument>com.example.demo.RecordPatternExample</argument>
        </arguments>
    </configuration>
</plugin>

Test run using mvn exec:exec with toolchains configured:

[INFO] --- exec-maven-plugin:3.1.0:exec (default-cli) @ record-pattern ---
[INFO] Toolchain in exec-maven-plugin: JDK[C:/Program Files/Java/jdk-19+36]
Hantsy Bai
Circle with r:1.2, area:4.5216
Square with x:1.2, area:1.44
Rectangle with x: 1.0 and y:2.0, area:2.0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.350 s
[INFO] Finished at: 2022-10-12T13:25:56+03:00
[INFO] Final Memory: 10M/25M
[INFO] ------------------------------------------------------------------------
Crimpy answered 12/10, 2022 at 10:33 Comment(4)
It seems like a bug.Catercorner
@Catercorner toolchain support might not be possible to implement with exec:java. The point of that goal is to execute in the same VM as maven run, and it might not be possible to use some other toolchain within the same VM.Crimpy
As the documentation doesn't claim exec:java supports toolchains, I'm thinking rather a missing feature than a bug.Crimpy
I hope it is enabled by default when running application(align with compiler and surefire plugins), and use a configuration option to select use toolchain or not. Like we use NetBeans IDE(eg. use Java 19 to start) to build a Java 11 project(select a different JDK for project), when build and run the project in IDE, we never use the IDE scoped Java 19.Catercorner
I
0

The exec-maven-plugin documentation doesn't make it very clear, but there are two requirements to get the plugin to use the toolchain:

  1. you have to use exec:exec. As someone else pointed out, exec:java is for running java classes within the same VM that maven is running in.

  2. you have to specify the as simply "java".

Then the plugin properly uses jdk toolchain configurations.

Isopleth answered 15/10 at 21:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.