Skip to content

Commit 5f5217d

Browse files
committed
Align Eclipse import with Gradle build
Update `JavaConventions` and `EclipseConventions` to align the Eclipse import with the regular Gradle Build. Imported projects now use Java 25 for the JRE but have compatibility set to Java 17 and a project configuration that uses the `--release` flag. This update also removes the calls to `setSourceCompatibility` and `setTargetCompatibility` on the `JavaPluginExtension` in favor of just using `compile.options.release`. We now also enforce that Java 25 or above is being used to build the project. Since buildship doesn't offer a way to set the `--release` JDT project setting, a custom task is used. Projects may need to be reimported or cleaned to actually have the setting apply correctly. Closes gh-48929
1 parent efac1bf commit 5f5217d

File tree

3 files changed

+129
-19
lines changed

3 files changed

+129
-19
lines changed

buildSrc/src/main/java/org/springframework/boot/build/EclipseConventions.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@
1616

1717
package org.springframework.boot.build;
1818

19+
import org.gradle.api.DomainObjectCollection;
20+
import org.gradle.api.JavaVersion;
1921
import org.gradle.api.Project;
2022
import org.gradle.api.plugins.JavaBasePlugin;
23+
import org.gradle.api.tasks.TaskProvider;
2124
import org.gradle.plugins.ide.api.XmlFileContentMerger;
2225
import org.gradle.plugins.ide.eclipse.EclipsePlugin;
2326
import org.gradle.plugins.ide.eclipse.model.Classpath;
2427
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry;
2528
import org.gradle.plugins.ide.eclipse.model.EclipseClasspath;
29+
import org.gradle.plugins.ide.eclipse.model.EclipseJdt;
2630
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
2731
import org.gradle.plugins.ide.eclipse.model.Library;
2832

@@ -35,12 +39,35 @@
3539
class EclipseConventions {
3640

3741
void apply(Project project) {
38-
project.getPlugins()
39-
.withType(EclipsePlugin.class,
40-
(eclipse) -> project.getPlugins().withType(JavaBasePlugin.class, (javaBase) -> {
41-
EclipseModel eclipseModel = project.getExtensions().getByType(EclipseModel.class);
42-
eclipseModel.classpath(this::configureClasspath);
43-
}));
42+
project.getPlugins().withType(EclipsePlugin.class, (eclipse) -> configure(project, eclipse));
43+
}
44+
45+
private DomainObjectCollection<JavaBasePlugin> configure(Project project, EclipsePlugin eclipsePlugin) {
46+
TaskProvider<EclipseSynchronizeJdtSettings> eclipseSynchronizeJdtSettings = registerEclipseSynchronizeJdtSettingsTask(
47+
project);
48+
return project.getPlugins().withType(JavaBasePlugin.class, (javaBase) -> {
49+
EclipseModel model = project.getExtensions().getByType(EclipseModel.class);
50+
model.synchronizationTasks(eclipseSynchronizeJdtSettings);
51+
model.jdt(this::configureJdt);
52+
model.classpath(this::configureClasspath);
53+
});
54+
}
55+
56+
private TaskProvider<EclipseSynchronizeJdtSettings> registerEclipseSynchronizeJdtSettingsTask(Project project) {
57+
TaskProvider<EclipseSynchronizeJdtSettings> taskProvider = project.getTasks()
58+
.register("eclipseSynchronizateJdt", EclipseSynchronizeJdtSettings.class);
59+
taskProvider.configure((task) -> {
60+
task.setDescription("Synchronizate the Eclipse JDT settings file from Buildship.");
61+
task.setOutputFile(project.file(".settings/org.eclipse.jdt.core.prefs"));
62+
task.setInputFile(project.file(".settings/org.eclipse.jdt.core.prefs"));
63+
});
64+
return taskProvider;
65+
}
66+
67+
private void configureJdt(EclipseJdt jdt) {
68+
jdt.setSourceCompatibility(JavaVersion.toVersion(JavaConventions.RUNTIME_JAVA_VERSION));
69+
jdt.setTargetCompatibility(JavaVersion.toVersion(JavaConventions.RUNTIME_JAVA_VERSION));
70+
jdt.setJavaRuntimeName("JavaSE-" + JavaConventions.BUILD_JAVA_VERSION);
4471
}
4572

4673
private void configureClasspath(EclipseClasspath classpath) {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.build;
18+
19+
import java.util.Properties;
20+
21+
import org.gradle.api.Task;
22+
import org.gradle.api.internal.PropertiesTransformer;
23+
import org.gradle.plugins.ide.api.PropertiesGeneratorTask;
24+
import org.gradle.plugins.ide.internal.generator.PropertiesPersistableConfigurationObject;
25+
26+
import org.springframework.boot.build.EclipseSynchronizeJdtSettings.Configuration;
27+
28+
/**
29+
* {@link Task} to do something.
30+
*
31+
* @author Phillip Webb
32+
*/
33+
public abstract class EclipseSynchronizeJdtSettings extends PropertiesGeneratorTask<Configuration> {
34+
35+
@Override
36+
protected Configuration create() {
37+
return new Configuration(getTransformer());
38+
}
39+
40+
@Override
41+
protected void configure(Configuration configuration) {
42+
}
43+
44+
static class Configuration extends PropertiesPersistableConfigurationObject {
45+
46+
Configuration(PropertiesTransformer transformer) {
47+
super(transformer);
48+
}
49+
50+
@Override
51+
protected String getDefaultResourceName() {
52+
return null;
53+
}
54+
55+
@Override
56+
protected void load(Properties properties) {
57+
}
58+
59+
@Override
60+
protected void store(Properties properties) {
61+
properties.put("org.eclipse.jdt.core.compiler.release", "true");
62+
}
63+
64+
}
65+
66+
}

buildSrc/src/main/java/org/springframework/boot/build/JavaConventions.java

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
package org.springframework.boot.build;
1818

19+
import java.util.ArrayList;
1920
import java.util.Arrays;
2021
import java.util.Collections;
22+
import java.util.LinkedHashSet;
2123
import java.util.List;
2224
import java.util.Map;
2325
import java.util.Set;
@@ -32,6 +34,7 @@
3234
import io.spring.javaformat.gradle.SpringJavaFormatPlugin;
3335
import io.spring.javaformat.gradle.tasks.CheckFormat;
3436
import io.spring.javaformat.gradle.tasks.Format;
37+
import org.gradle.api.GradleException;
3538
import org.gradle.api.JavaVersion;
3639
import org.gradle.api.Project;
3740
import org.gradle.api.Task;
@@ -53,6 +56,9 @@
5356
import org.gradle.api.tasks.javadoc.Javadoc;
5457
import org.gradle.api.tasks.testing.Test;
5558
import org.gradle.external.javadoc.CoreJavadocOptions;
59+
import org.gradle.jvm.toolchain.JavaCompiler;
60+
import org.gradle.jvm.toolchain.JavaInstallationMetadata;
61+
import org.gradle.jvm.toolchain.JavaLanguageVersion;
5662

5763
import org.springframework.boot.build.architecture.ArchitecturePlugin;
5864
import org.springframework.boot.build.classpath.CheckClasspathForProhibitedDependencies;
@@ -127,7 +133,9 @@
127133
*/
128134
class JavaConventions {
129135

130-
private static final String SOURCE_AND_TARGET_COMPATIBILITY = "17";
136+
public static final int BUILD_JAVA_VERSION = 25;
137+
138+
public static final int RUNTIME_JAVA_VERSION = 17;
131139

132140
void apply(Project project) {
133141
project.getPlugins().withType(JavaBasePlugin.class, (java) -> {
@@ -165,7 +173,8 @@ private void configureJarManifestConventions(Project project) {
165173
jar.manifest((manifest) -> {
166174
Map<String, Object> attributes = new TreeMap<>();
167175
attributes.put("Automatic-Module-Name", project.getName().replace("-", "."));
168-
attributes.put("Build-Jdk-Spec", SOURCE_AND_TARGET_COMPATIBILITY);
176+
// Build-Jdk-Spec is used by buildpacks to pick the JRE to install
177+
attributes.put("Build-Jdk-Spec", RUNTIME_JAVA_VERSION);
169178
attributes.put("Built-By", "Spring");
170179
attributes.put("Implementation-Title",
171180
determineImplementationTitle(project, sourceJarTaskNames, javadocJarTaskNames, jar));
@@ -243,23 +252,31 @@ private void addValuelessOption(CoreJavadocOptions options, String option) {
243252
}
244253

245254
private void configureJavaConventions(Project project) {
246-
if (!project.hasProperty("toolchainVersion")) {
247-
JavaPluginExtension javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class);
248-
javaPluginExtension.setSourceCompatibility(JavaVersion.toVersion(SOURCE_AND_TARGET_COMPATIBILITY));
249-
javaPluginExtension.setTargetCompatibility(JavaVersion.toVersion(SOURCE_AND_TARGET_COMPATIBILITY));
250-
}
251255
project.getTasks().withType(JavaCompile.class, (compile) -> {
256+
compile.doFirst((task) -> assertCompatible(compile));
252257
compile.getOptions().setEncoding("UTF-8");
253-
compile.getOptions().getRelease().set(17);
254-
List<String> args = compile.getOptions().getCompilerArgs();
255-
if (!args.contains("-parameters")) {
256-
args.add("-parameters");
257-
}
258-
args.addAll(Arrays.asList("-Werror", "-Xlint:unchecked", "-Xlint:deprecation", "-Xlint:rawtypes",
258+
compile.getOptions().getRelease().set(RUNTIME_JAVA_VERSION);
259+
Set<String> args = new LinkedHashSet<>(compile.getOptions().getCompilerArgs());
260+
args.addAll(List.of("-parameters", "-Werror", "-Xlint:unchecked", "-Xlint:deprecation", "-Xlint:rawtypes",
259261
"-Xlint:varargs"));
262+
compile.getOptions().setCompilerArgs(new ArrayList<>(args));
260263
});
261264
}
262265

266+
private void assertCompatible(JavaCompile compile) {
267+
JavaVersion requiredVersion = JavaVersion.toVersion(BUILD_JAVA_VERSION);
268+
JavaVersion actualVersion = compile.getJavaCompiler()
269+
.map(JavaCompiler::getMetadata)
270+
.map(JavaInstallationMetadata::getLanguageVersion)
271+
.map(JavaLanguageVersion::asInt)
272+
.map(JavaVersion::toVersion)
273+
.orElse(JavaVersion.current())
274+
.get();
275+
if (!actualVersion.isCompatibleWith(requiredVersion)) {
276+
throw new GradleException("This project should be built with Java %s or above".formatted(requiredVersion));
277+
}
278+
}
279+
263280
private void configureSpringJavaFormat(Project project) {
264281
project.getPlugins().apply(SpringJavaFormatPlugin.class);
265282
project.getTasks().withType(Format.class, (Format) -> Format.setEncoding("UTF-8"));

0 commit comments

Comments
 (0)