[ACCEPTED]-Different maven compiler versions for test and main-maven-3

Accepted answer
Score: 32

If you want to set compliance to the relevant 15 Java version, you can configure the compiler 14 plugin for each execution. Assuming Maven 13 is using a JDK at least as current as the 12 highest version you specify. By using properties 11 you can override that configuration on the 10 commandline or in a child if needed:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>${compileSource}</source>
    <target>${compileSource}</target>
  </configuration>
  <executions>
    <execution>
      <id>test-compile</id>
      <phase>process-test-sources</phase>
      <goals>
        <goal>testCompile</goal>
      </goals>
      <configuration>
        <source>${testCompileSource}</source>
        <target>${testCompileSource}</target>
      </configuration>
    </execution>
  </executions>
</plugin>
...
<properties>
  <compileSource>1.4</compileSource>
  <testCompileSource>1.5</testCompileSource>
</properties>

If you 9 mean using different compilers, that's a bit more 8 involved. as you need to specify the path 7 to the JDK and what compiler version you're 6 using. Again these can be defined in properties. Though 5 you may want to define them in your settings.xml

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <source>${compileSource}</source>
    <target>${compileSource}</target>
    <executable>${compileJdkPath}/bin/javac</executable>
    <compilerVersion>${compileSource}</compilerVersion>
  </configuration>
  <executions>
    <execution>
      <id>test-compile</id>
      <phase>process-test-sources</phase>
      <goals>
        <goal>testCompile</goal>
      </goals>
      <configuration>
        <source>${testCompileSource}</source>
        <target>${testCompileSource}</target>
        <executable>${testCompileJdkPath}/bin/javac</executable>
        <compilerVersion>${testCompileSource}</compilerVersion>
      </configuration>
    </execution>
  </executions>
</plugin>
...
<properties>
  <compileSource>1.4</compileSource>
  <testCompileSource>1.5</testCompileSource>
  <compileJdkPath>path/to/jdk</compileJdkPath>
  <testCompileJdkPath>path/to/test/jdk<testCompileJdkPath>
</properties>

Note 4 it might make sense to define the compiler 3 configurations in profiles, one for each 2 JDK you support, so that your normal builds 1 don't rely on properties being set.

Also, in Maven 3.x, you need to include the fork parameter when specifying the executable, e.g.:

  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
      <execution>
        <id>default-testCompile</id>
        <phase>test-compile</phase>
        <goals>
          <goal>testCompile</goal>
        </goals>
        <configuration>
          <fork>true</fork>
          <executable>${testCompileJdkPath}/bin/javac</executable>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>            
      </execution>
    </executions>
  </plugin>
Score: 18

I had no luck with the accepted answer compiling 7 java 7 source and java 8 test sources using 6 the maven-compiler-plugin, version 3.5.1. Because the compile 5 plugin used the source / target parameter 4 for both, main and test sources.

But I found 3 out, there are separate configuration parameters 2 for the test source and target.

So for me 1 the solution that worked was

 <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <testSource>1.8</testSource>
                <testTarget>1.8</testTarget>
            </configuration>
        </plugin>
    </plugins>
</build>
Score: 0

I found a solution at least for my case.

I 22 am writing a library that needs to be Java 21 1.7 compatible but relies on the nashorn engine 20 in JDK 8 to test some of its features, which 19 is a perfect reason for using different 18 compiler/jdk version for main and test.

When talking 17 about using different compiler/JRE version 16 for main and test, say version A for main and 15 version B for test and A is strictly smaller than 14 B, we really want to achieve the following:

  1. Make the IDE (in my case, the Eclipse) use the JDK version B during development for not introducing compilation error (red cross on your project icon).
  2. Make JUnit tests runnable from within your IDE.
  3. Make JUnit tests runnable from command line through mvn clean test which is required for releasing.
  4. Compile sources in main using JRE A, which enables automatic detection of using new features from JDK B.
  5. Free use of new features / new APIs from JDK B in test cases codes.

And 13 the following pom declaration works (for 12 example let A = 1.7 and B = 1.8):

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <fork>true</fork>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
                <executions>
                   <execution>
                      <id>default-compile</id>
                      <configuration>
                         <compilerArguments>
                            <source>1.7</source>
                            <target>1.7</target>
                         </compilerArguments>
                      </configuration>
                   </execution>
                   <execution>
                      <id>default-testCompile</id>
                      <configuration>
                         <compilerArguments>
                            <source>1.8</source>
                            <target>1.8</target>
                         </compilerArguments>
                      </configuration>
                   </execution>
                </executions>
            </plugin>

Firstly, <source>1.8</source> <target>1.8</target> is a must to 11 make Eclipse happy and using 1.8 for the 10 project itself, as others pointed out that 9 Eclipse has a still pending bug and does 8 not support different JDK version in a single 7 project natively.

Secondly, use <execution> to override 6 the source and target arguments during source compilation 5 and test source compilation. default-compile and default-testCompile are special 4 names for compiler plugin.

Thirdly, be sure 3 to use compilerArguments but not compilerArgs. As far as I know, only 2 compilerArguments can be used to override argument settings 1 during runtime.

More Related questions