Plebejusz Plebejusz - 3 months ago 28
Java Question

Specyfing java version in maven - differences beetwen properties and compiler plugin

I'm not very experienced with maven and while experimenting with multi-module project I started wondering how can I specify java version for all my child modules in parent maven pom. Until today I was using just:

<properties>
<java.version>1.8</java.version>
</properties>


but when researching I found that you can also specify java version in maven compiler plugin, like that:

<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>


And then wrap this into plugin management tag to enable child poms usage of this. So the first question is what are the differences beetwen setting java version in properties and in maven compiler plugin?

I couldn't find clear answer but in process of researching I found that you can also specify java version in this way:

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>


which suggest that compiler plugin is there even if I dont explicit declare it. Running mvn package outputs with

maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---


and some other plugins that I didn't declare. So are those plugins default, hidden part of maven pom? Are there any differences beetwen setting source/target in properties and in maven plugin configuration element?

Some other questions are - which way should be used (and when if they are not equal)? Which one is best for multi-module project and what happens if java version specified in pom is different than version pointed in JAVA_HOME?

Answer

About your question about why the compiler plugin is traced in the output at the execution of the Maven package goal even if you don't specify it in the pom.xml

To compile your code and perform all operations for executing a maven goal, Maven needs tools. So, it uses core Maven plugins (you recognize a core Maven plugin thanks to its groupId : org.apache.maven.plugins) to do the required tasks : compiler plugin for compile classes, test plugin for executing tests, and so for... So, even if you don't declare these plugins, they are bound to the execution of the Maven lifecycle.

At the root dir of your Maven project, you can run the command : mvn help:effective-pom to get the final pom effectively used. You could see among other information, attached plugins by Maven (specified or not in your pom.xml), with the used version, their configuration and the executed goals for each phase of the lifecycle.
You can have more information about it in the introduction of the Maven lifeycle in the Maven documentation.

Nevertheless, you can declare plugins when you want to configure them with other values as default values (for example, you did it when you declared the maven-compiler plugin in your pom.xml to adjust the JDK version to use) or when you want to add some plugin executions not used by default in the Maven lifecycle.


About your question about how to specify the JDK version, here my answer.

1) <java.version> is not referenced in the Maven documentation. I would not use it.

2)

<plugins>
    <plugin>    
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

and

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

are equivalent according to the Maven documentation of the compiler plugin since the <source> and the <target> elements in the compiler configuration use the properties maven.compiler.source and maven.compiler.target if they are defined (else 1.5 by default).

source String 2.0

The -source argument for the Java compiler. Default value is: 1.5. User property is: maven.compiler.source.

target String 2.0

The -target argument for the Java compiler. Default value is: 1.5. User property is: maven.compiler.target.


About your questions about the best way to specify the JDK version and what happens if the version differs between the JDK in JAVA_HOME and which one specified in the pom.xml.

You can use one or the other. It changes nothing in the facts since finally the two solutions rely on the same properties and the same mechanism : the core maven compiler plugin.

About you other question, if the Java versions specified for the maven compiler are different, it is not a problem if the JDK of your JAVA_HOME is compatible with the specified versions in the pom.
To be compatible, I think that the source and the target in the Maven configuration should not be superior to the JDK version in JAVE_HOME. A older version of the JDK cannot compile with a more recent version since it doesn't know its specification (java 8 case):

Valid targets are 1.1, 1.2, 1.3, 1.4, 1.5 (also 5), 1.6 (also 6), 1.7 (also 7), and 1.8 (also 8).

You could have more details in the javac documentation for JDK 1.8

About the case the JDK of your JAVA_HOME is not compatible with the specified versions in the pom.

For example, if your JAVA_HOME refers a JDK 1.7 and you specify a JDK 1.8 as source and target in the compiler configuration of your pom.xml, it will be a problem because as explained, the JDK 1.7 doesn't know how to compile with.
From its point of view, it is an unknown JDK version because too recent.
In this case, you should configure the Maven compiler plugin to specify the JDK in this way :

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerVersion>1.8</compilerVersion>      
        <fork>true</fork>
        <executable>D:\jdk1.8\bin\javac</executable>                
    </configuration>
</plugin>

You could have more details in examples with maven compiler plugin.


It is not your question but case where it may be more complicated is when you specify source but not target. It may use a different version in target according to the source version. Rules are particular :

-target version Generates class files that target a specified release of the virtual machine. Class files will run on the specified target and on later releases, but not on earlier releases of the JVM. Valid targets are 1.1, 1.2, 1.3, 1.4, 1.5 (also 5), 1.6 (also 6), 1.7 (also 7), and 1.8 (also 8).

The default for the -target option depends on the value of the -source option:

If the -source option is not specified, then the value of the -target option is 1.8

If the -source option is 1.2, then the value of the -target option is 1.4

If the -source option is 1.3, then the value of the -target option is 1.4

If the -source option is 1.5, then the value of the -target option is 1.8

If the -source option is 1.6, then the value of the -target is option 1.8

If the -source option is 1.7, then the value of the -target is option 1.8

For all other values of the -source option, the value of the -target option is the value of the -source option.