Summary
After commit cd5feb8 ("Only consider the default-compile execution when update JDT settings"), projects that disable the default-compile execution and use custom execution IDs for maven-compiler-plugin have their JDT source/target level silently forced to 1.8, regardless of the actual compiler configuration in the POM.
Affected Component
org.eclipse.m2e.jdt - AbstractJavaProjectConfigurator.addJavaProjectOptions()
Regression Introduced By
Environment
Root Cause Analysis
In addJavaProjectOptions(), the code iterates over MojoExecution objects returned by getCompilerMojoExecutions() and checks:
if(!"default-compile".equals(id)) {
//Maven can have many but JDT only supports one config!
continue;
}
If no execution has id "default-compile", the loop completes without extracting any source/target configuration. The method then falls through to:
} else {
if(source == null) {
source = getDefaultSourceLevel();
log.warn("Could not determine source level, using default " + source);
}
where getDefaultSourceLevel() returns the hardcoded value "1.8".
This value gets propagated to getExecutionEnvironmentId(), which maps "1.8" -> "JavaSE-1.8" via the ENVIRONMENTS map, and ultimately writes JavaSE-1.8 into the project's .classpath file.
Reproduction
POM Configuration (Parent POM pattern)
Some Maven configurations use parent POMs that disable the default-compile execution and replace it with custom executions:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<!-- Disable default-compile -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Custom compile execution -->
<execution>
<id>my-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
Steps to Reproduce
- Create a Maven project whose POM (or parent POM) disables
default-compile by setting <phase>none</phase> and defines a custom execution (e.g., my-compile) for the compile goal.
- Set
<source>17</source> and <target>17</target> (or <release>17</release>) in the compiler plugin configuration.
- Import the project in an IDE that uses m2e (VS Code with Language Support for Java(TM) by Red Hat, or Eclipse).
- Observe the resulting
.classpath file and JDT project settings (if in VS Code, this can be observed by hovering over { } Java or by clicking Java: Ready > Open Project Settings in the status bar).
Expected Behavior
The JDT project should be configured with JavaSE-17 (matching the POM's compiler source/target).
Actual Behavior
The JDT project is configured with JavaSE-1.8 because addJavaProjectOptions() only examines executions with executionId == "default-compile", misses the actual compiler configuration in the custom execution, and falls back to the hardcoded "1.8" default.
Impact
- Projects silently get the wrong JRE System Library (
JavaSE-1.8 instead of JavaSE-17).
- Compiler compliance level is set incorrectly in
.settings/org.eclipse.jdt.core.prefs.
- Red squiggles appear on valid Java 17+ syntax (records, sealed classes, text blocks, etc.).
- The only workaround is to manually override the JDK Runtime and source/target via the IDE's Project Settings UI (If using VS Code,
Java: Ready > Open Project Settings in the status bar).
- This pattern of disabling
deafult-compile and using custom execution IDs is a valid Maven configuration that worked correctly prior to this commit.
Related Issues
See also #2156 for a related but distinct issue - it reports the same symptom (fallback to JaveSE-1.8) but caused by Maven property indirection resolution, not by execution ID filtering.
Suggested Fix
The filtering logic in addJavaProjectOptions() should not exclusively match "default-compile". When default-compile has been disabled (e.g., <phase>none</phase>), the method should also consider other compile-goal executions, or fall back to reading the plugin-level <configuration> block (which applies to all executions), or fall back to the maven.compiler.source / maven.compiler.target / maven.compiler.release Maven properties.
Possible approaches:
- Check all compile executions, not just
default-compile - use the first one that has source/target configuration, or the one with the highest source level.
- Read plugin-level configuration as a fallback when
default-compile is not found or is disabled.
- Read Maven properties (
maven.compiler.source, maven.compiler.target, maven.compiler.release) as a final fallback before returning the hardcoded "1.8".
Regression Confirmed by Downgrade
Downgrading the Language Support for Java(TM) by Red Hat extension in VS Code from v1.54.0 to v1.50.0 (which does not include commit cd5feb8) and performing a clean workspace import correctly resolves the project as JavaSE-17. Upgrading back to v1.51.0 or later reproduces the JaveSE-1.8 fallback.
Summary
After commit
cd5feb8("Only consider the default-compile execution when update JDT settings"), projects that disable thedefault-compileexecution and use custom execution IDs formaven-compiler-pluginhave their JDT source/target level silently forced to 1.8, regardless of the actual compiler configuration in the POM.Affected Component
org.eclipse.m2e.jdt-AbstractJavaProjectConfigurator.addJavaProjectOptions()Regression Introduced By
cd5feb8ff9b077630aa6d3a66291954c99306098Environment
Root Cause Analysis
In
addJavaProjectOptions(), the code iterates overMojoExecutionobjects returned bygetCompilerMojoExecutions()and checks:If no execution has id
"default-compile", the loop completes without extracting any source/target configuration. The method then falls through to:where
getDefaultSourceLevel()returns the hardcoded value"1.8".This value gets propagated to
getExecutionEnvironmentId(), which maps"1.8"->"JavaSE-1.8"via theENVIRONMENTSmap, and ultimately writesJavaSE-1.8into the project's.classpathfile.Reproduction
POM Configuration (Parent POM pattern)
Some Maven configurations use parent POMs that disable the
default-compileexecution and replace it with custom executions:Steps to Reproduce
default-compileby setting<phase>none</phase>and defines a custom execution (e.g.,my-compile) for thecompilegoal.<source>17</source>and<target>17</target>(or<release>17</release>) in the compiler plugin configuration..classpathfile and JDT project settings (if in VS Code, this can be observed by hovering over{ } Javaor by clickingJava: Ready > Open Project Settingsin the status bar).Expected Behavior
The JDT project should be configured with
JavaSE-17(matching the POM's compiler source/target).Actual Behavior
The JDT project is configured with
JavaSE-1.8becauseaddJavaProjectOptions()only examines executions withexecutionId == "default-compile", misses the actual compiler configuration in the custom execution, and falls back to the hardcoded"1.8"default.Impact
JavaSE-1.8instead ofJavaSE-17)..settings/org.eclipse.jdt.core.prefs.Java: Ready > Open Project Settingsin the status bar).deafult-compileand using custom execution IDs is a valid Maven configuration that worked correctly prior to this commit.Related Issues
See also #2156 for a related but distinct issue - it reports the same symptom (fallback to JaveSE-1.8) but caused by Maven property indirection resolution, not by execution ID filtering.
Suggested Fix
The filtering logic in
addJavaProjectOptions()should not exclusively match"default-compile". Whendefault-compilehas been disabled (e.g.,<phase>none</phase>), the method should also consider other compile-goal executions, or fall back to reading the plugin-level<configuration>block (which applies to all executions), or fall back to themaven.compiler.source/maven.compiler.target/maven.compiler.releaseMaven properties.Possible approaches:
default-compile- use the first one that has source/target configuration, or the one with the highest source level.default-compileis not found or is disabled.maven.compiler.source,maven.compiler.target,maven.compiler.release) as a final fallback before returning the hardcoded"1.8".Regression Confirmed by Downgrade
Downgrading the Language Support for Java(TM) by Red Hat extension in VS Code from v1.54.0 to v1.50.0 (which does not include commit
cd5feb8) and performing a clean workspace import correctly resolves the project asJavaSE-17. Upgrading back to v1.51.0 or later reproduces theJaveSE-1.8fallback.