Keywords: Spring Boot | Java Version Configuration | pom.xml | Maven Compiler Plugin | javac Arguments
Abstract: This article provides a comprehensive exploration of how to correctly configure Java versions in the pom.xml file of Spring Boot projects, particularly for Java 11 and later releases. By examining the source code of spring-boot-starter-parent and the workings of the Maven compiler plugin, it explains how the <java.version> property maps to the -source and -target arguments of javac. The discussion covers the evolution of version number formats (e.g., from 1.8 to 8) and offers practical configuration examples and best practices to help developers avoid common pitfalls.
Core Mechanism of Java Version Configuration
In Spring Boot projects, Java version configuration is primarily achieved through the <java.version> property in the pom.xml file. This property is not unique to Spring Boot but is closely linked to Java compiler (javac) arguments via Maven's build mechanism. Understanding this configuration requires analysis at three levels: the parent POM definition in Spring Boot, parameter transmission in the Maven compiler plugin, and version compatibility rules of the Java compiler.
Configuration Inheritance from spring-boot-starter-parent
Spring Boot projects typically inherit from spring-boot-starter-parent, which defines default Java version configurations in the properties section. For instance, in Spring Boot 2.x versions, the parent POM source code shows the following configuration:
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>The key here is that the value of <java.version> is assigned to both maven.compiler.source and maven.compiler.target, two Maven properties. This design allows developers to update source and target bytecode version requirements simultaneously by modifying a single property.
Parameter Mapping in the Maven Compiler Plugin
The Maven compiler plugin (maven-compiler-plugin) is responsible for converting Maven properties into actual javac command-line arguments. According to Maven official documentation, maven.compiler.source and maven.compiler.target are "user properties" for the <source> and <target> configuration parameters. This means that setting these properties in the project POM is equivalent to explicitly specifying corresponding values in the plugin configuration.
For example, when <java.version> is set to 11, the actual configuration of the Maven compiler plugin is as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>This implicit configuration simplifies developers' work but can also cause confusion, as the effective parameters are those of the compiler plugin, not the <java.version> property itself.
Evolution of Java Version Number Formats
The representation of Java version numbers has changed historically. In Java 8 and earlier versions, the "1.x" format (e.g., 1.8) was commonly used. However, starting from Java 9, Oracle and the OpenJDK community shifted to simplified integer formats (e.g., 9, 10, 11). This change is also reflected in the -source and -target arguments of javac.
According to Java official documentation, javac accepts the following version values:
- 1.6 or 6 (Java SE 6)
- 1.7 or 7 (Java SE 7)
- 1.8 or 8 (Java SE 8)
- 9 (Java SE 9)
- 10 (Java SE 10)
- 11 (Java SE 11)
- 12 (Java SE 12)
Therefore, for Java 11, the correct configuration value is 11, not 1.11. The latter is invalid and may cause the compiler to use a default version or generate warnings.
Practical Configuration Examples and Verification
In the pom.xml of a Spring Boot project, the correct way to configure Java 11 is as follows:
<properties>
<java.version>11</java.version>
</properties>To verify that the configuration is effective, you can run Maven commands and check the compiler output. For example, after using the mvn compile command, look for messages like "javac 11.0.2 was used to compile java sources" in the logs. Additionally, you can use Maven's help plugin to view the actual effective property values:
mvn help:effective-pomThis command displays the complete POM after merging all parent POM and plugin configurations, where you can confirm whether maven.compiler.source and maven.compiler.target are correctly set to 11.
Common Misconceptions and Debugging Techniques
Some developers may encounter situations where the configuration seems ineffective, such as the project compiling normally even when <java.version> is set to an arbitrary value (e.g., 100). This is often because Maven or the IDE uses default compiler settings, or there are other overriding configurations in the project. To troubleshoot these issues, the following steps can be taken:
- Check if the project indeed inherits from spring-boot-starter-parent. If not, you need to manually configure maven.compiler.source and maven.compiler.target.
- Ensure that <source> and <target> values are not explicitly overridden in plugin configurations. For example, if maven-compiler-plugin is directly configured in pom.xml, it might ignore the <java.version> setting.
- Use Maven's debug mode (mvn -X compile) to view detailed parameter transmission processes, ensuring the compiler plugin receives the correct version arguments.
Comparison with the release Parameter
Starting from Maven compiler plugin version 3.6.0, the <release> parameter was introduced as an alternative to <source> and <target>. The <release> parameter not only sets the language version but also ensures the correct platform API is used. For example:
<configuration>
<release>11</release>
</configuration>In Spring Boot, if both <java.version> and <release> are set, the latter typically takes higher precedence. Therefore, it is recommended that developers choose one approach based on project needs to avoid configuration conflicts.
Summary and Best Practices
Correctly configuring the Java version is fundamental to ensuring the compatibility and stability of Spring Boot projects. For Java 11 and later versions, integer formats (e.g., 11) should be used as the value for <java.version>. Developers should understand the underlying mechanism of this configuration, where properties are transmitted through Maven to compiler arguments and ultimately affect javac's behavior. When debugging configuration issues, combining Maven commands and log analysis can quickly identify causes. As Java versions evolve rapidly, maintaining accurate and consistent configurations will facilitate long-term project maintenance.