Site icon Automation Dojos

Configuring Maven Compiler Plugin (Java)

Table of Contents

1. What is Maven Compiler Plugin

The ‘Maven Compiler Plugin’ or more commonly known as ‘Maven Java Compiler’ is used to compile the source code of your project/application.

Internally this plugin uses the standard ‘javac’ compiler (JDK) and as of version 3.0 of this plugin the default compiler is javax.tools.JavaCompiler

Unlike other Maven plugins, the ‘maven compiler plugin’ is ‘in-built’ and ‘implicit’ in nature. This plugin has two goals, which are already bound to specific phases of the default lifecycle:

  • compile: compile main source files
  • testCompile: compile test source files

As mentioned earlier, the maven compiler plugin is called implicitly and automatically by the maven lifecycle in the appropriate phase. Hence you don´t necessarily need to define it inside ‘pom.xml’ it shall be downloaded and executed automatically by maven as and when required. However, we can certainly define and configure custom behavior and attributes for this plugin by specifying it in the ‘pom.xml’.

2. Default Configuration

As per the default behavior, the ‘maven compiler plugin’ compiles source code compatible with Java 5 (also written as Java 1.5), irrespective of the JDK installed on your machine. However, with custom configuration in your ‘pom.xml’ you can override this behavior and specify your own version of compiler and compatibility version.

Note: The java version used to launch Maven itself (Maven runtime) can be set to a different version than the version used for compiling your source code or project. This can be done using custom configuration in your pom.xml as explained in below examples.

You can find out java version for ‘Maven runtime’ by typing the command ‘mvn -v’ or ‘mvn -version’

3. Common Compilation Error

While starting with Maven projects, it is very common to encounter the below error associated with this plugin. This is nothing but the default behavior as mentioned in the above paragraph and can be rectified by using one of the below mentioned custom configurations for your maven java compiler.

[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] Source option 5 is no longer supported. Use 6 or later.
[ERROR] Target option 1.5 is no longer supported. Use 1.6 or later.
[INFO] 2 errors
[INFO] -------------------------------------------------------------

4. Custom Configuration Java 8 or Earlier

If you are using Java 8 or earlier, you can set the Maven Java Compiler version in your POM file using one of the following three methods:

  • Using POM Properties
  • Using -source and -target values in compiler configuration
  • Using compilerVersion in compiler configuration

Let us start with a standard bare-bone ‘pom.xml’ file and insert our custom configuration for ‘Maven Compiler Plugin’ eventually by three different methods.

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
</project>

4.1. Configure using POM Properties

In this method rather than tweaking the ‘maven compiler’ configuration or ‘build’ configuration’ directly, you can use the POM properties to set the compiler (JDK) versions.

This is the most simple but probably least reliable way. However, which option works best for you depends on the setup of your project and specific requirements i.e. depend on a case by case basis.

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
    <properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>
</project>

Using the above configuration should give you output classes both compiled and compatible with the specified java (compiler) version which is Java 8 in this case.

4.2. Configure using -source & -target

Another, preferred way for forcing a specific compiler version is by modifying the default parameter values of ‘-source’ and ‘target’ directly in the plugin settings as below.

Here we are setting the JDK/JRE version for both source and target to 1.8

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>
NOTE: In some cases, problem with this method is that it does not ‘guarantee’ that the maven compiler would be able to strictly adhere to above settings due to unintended usage of APIs that only exist in JREs which would make your code fail at runtime with a linkage error. For further reference on this read https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html

4.3. Configure using ‘compilerVersion’

You can use this method to compile your code with a ‘very specific’ JDK version, even if it is different than the one used to launch Maven itself. This is probably the most precise of all methods.

Here ‘compilerVersion’ parameter can be used as part of ‘build configuration’ to specify the version of the compiler that the plugin will use. However, you also need to set fork to true for this to work

Using the below ‘POM’ configuration, it is still possible to tell the ‘Maven Compiler Plugin’ the specific JDK to use during compilation. But such configuration will be specific to this plugin, and will not affect others.

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
  
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <executable><!-- path-to-javac --></executable>
          <compilerVersion>1.3</compilerVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
 
</project>
NOTE: Please note that you need to set the ‘fork’ value to ‘true’ for this method to work. This allows running the compiler in a separate process. If false it uses the built-in compiler, while if true it will use the explicitly mentioned executable. Default value is: false.

4.3.1. Improvise – Use variable for Path

In the above ‘pom.xml’ snippet, rather than hardcoding the path to java compiler, you can replace it with a variable. We can do so by using the following property: <executable>${JAVA_1_4_HOME}/bin/javac</executable>

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
  
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <executable>${JAVA_1_8_HOME}/bin/javac</executable>
          <compilerVersion>1.8</compilerVersion>
        </configuration>
      </plugin>
    </plugins>
  </build>
  
</project>

The best part of using the above property is that different users can specify their own values for this property in their ‘settings.xml’ file, keeping your project portable for different users and machine configurations.

<settings>
  [...]
  <profiles>
    [...]
    <profile>
      <id>compiler</id>
        <properties>
          <JAVA_1_4_HOME>C:\Program Files\Java\j2sdk1.4.2_09</JAVA_1_4_HOME>
        </properties>
    </profile>
  </profiles>
  [...]
  <activeProfiles>
    <activeProfile>compiler</activeProfile>
  </activeProfiles>
</settings>

4.3.2. Improvise – Pass args to compiler

If you wish to pass some arguments to the maven java compiler, you can do so in two ways.

Method 1: Using <configuration> element

You can pass the compiler arguments inside the ‘configuration’ part of the compiler plugin itself. A very common example is to pass min and max memory values as below.

Here we are passing the following arguments related to max and min memory to the compiler:

           <meminitial>128m</meminitial>
           <maxmem>512m</maxmem>

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
  
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <executable>${JAVA_1_8_HOME}/bin/javac</executable>
          <compilerVersion>1.3</compilerVersion>
           <meminitial>128m</meminitial>
           <maxmem>512m</maxmem>
        </configuration>
      </plugin>
    </plugins>
  </build>
  
</project>
NOTE: The fork value needs to be set to true in order for these memory settings to work. Without fork value being true these memory parameters set for compiler will not work.
Method 2: Using explicit <compilerArgs>

You should use ‘<compilerArgs>’ element to pass specific compiler arguments that are not handled by the Compiler Plugin itself but are supported by the compilerId selected. For such arguments, use the Compiler Plugin’s <compilerArgs> parameter.

The following example passes compiler arguments to the javac compiler:

<project 
	xmlns="http://maven.apache.org/POM/4.0.0" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
  
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <verbose>true</verbose>
          <fork>true</fork>
          <executable>${JAVA_1_8_HOME}/bin/javac</executable>
          <compilerVersion>1.3</compilerVersion>
           <meminitial>128m</meminitial>
           <maxmem>512m</maxmem>
          <compilerArgs>
            <arg>-verbose</arg>
            <arg>-Xlint:all,-options,-path</arg>
           <arg>-Xmaxerrs</arg>
           <arg>1000</arg>
         <arg>-J-Duser.language=en_us</arg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
  </build>
  
</project>
NOTE: Please note that you need to set the ‘fork’ value to ‘true’ for this method to work. Without fork value being set to true the parameters will not be picked up. Default value is: false.

5. Custom Configuration Java 9 and Beyond

Starting from JDK 9, we can use a new command-line option i.e. ‘-release’ which is accepted by the javac executable and can be used to specify against which Java SE release you want to build the project.

This new argument replaces the traditional ‘source’ and ‘target’ properties used for Java 8 or earlier and will automatically configure the compiler to produce class files compatible with the given platform version which should be Java 9 or above. You can implement this ‘-release’ value in the following two ways :

5.1. Configure using POM Properties

In this method, you can specify the Java compiler version using the ‘maven.compiler.release’ element inside the POM Properties. Here is how the Maven Java compiler release element look inside pom properties:

<project 
   xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
      http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
    <properties>
    <maven.compiler.release>11</maven.compiler.release>
  </properties>
</project>

5.2. Configure using plugin <configuration>

In this method, instead of the source and target properties (as mentioned in section 4.2 above), you need to use the ‘-release‘ property inside the Maven Java compiler plugin’s ‘<configuration>’ element. Given below is the snippet for such implementation:

<project 
   xmlns="http://maven.apache.org/POM/4.0.0" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
      http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.testoxide</groupId>
  <artifactId>maven-quick-start</artifactId>
  <version>1.0</version>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <release>11</release>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
NOTE:

The value in the ‘-release’ parameter follows the new version naming scheme adopted since Java 9. As such, the release number does not start with 1.x anymore.

Also note that ‘-release’ parameter is available for maven-compiler-plugin starting 3.6 version

Exit mobile version