Duplicate results in the classpath when using spring aot plugin
Steps to Reproduce
- git clone https://github.com/scratches/gradle-aot
- run
./gradlew clean buildin the project root folder - Open the project in VS Code or eclipse
- Run the test case
ConfigTest, you can see the errors.
Expected Behavior
The test should succeed.
Current Behavior
The test fails due to the duplicate results in the classpath.

Context
It looks like the issue exists in the interaction between spring aot plugin and buildship/Gradle eclipse plugin. The aot plugin will add each source set's output to the runtime classpath. See : https://github.com/spring-projects/spring-boot/blob/5d49889bfde45ec0cf1d73b96ae61096add9dae7/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java#L78 and https://github.com/spring-projects/spring-boot/blob/5d49889bfde45ec0cf1d73b96ae61096add9dae7/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java#L92
Looks like this might be related: https://github.com/gradle/gradle/issues/23032 (according to comments in https://github.com/redhat-developer/vscode-java/issues/2344). Might even be fixed upstream already, but still broken for me in "pre-release" version of vscode extensions (redhat.java v1.18.2023041704)?
@dsyer I guess you should use Gradle 8.1 first (the version is mentioned in the PR's milestone) and configure like the following snippet:
eclipse {
classpath {
baseSourceOutputDir = file('build')
}
}
Unfortunately, it doesn't help. The generated files are under build folder but the classpath entries are still duplicated.
@CsCherrYY @dsyer You can try the following patch:
diff --git a/build.gradle b/build.gradle
index 5dd773c..c1053ce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,7 @@ plugins {
id 'org.springframework.boot' version '3.0.5'
id 'io.spring.dependency-management' version '1.1.0'
id 'org.graalvm.buildtools.native' version '0.9.20'
+ id 'eclipse'
}
group = 'com.example'
@@ -20,4 +21,19 @@ dependencies {
tasks.named('test') {
useJUnitPlatform()
-}
\ No newline at end of file
+}
+
+eclipse {
+ classpath {
+ defaultOutputDir = file('build-default')
+ file {
+ whenMerged {
+ cp -> cp.getEntries().forEach{
+ cpEntry -> if(cpEntry.path=='src/main/resources') {
+ cpEntry.output = 'build/resources/main'
+ }
+ }
+ }
+ }
+ }
+}
Why does Buildship want to use bin/main as a default build location? I imagine there is a reason for it, and this patch changes the build location, and therefore probably breaks something else?
@dsyer you may want to take a look at https://github.com/eclipse/buildship/issues/1131#issuecomment-1014559863
From that it seems like changing the default is a bad idea - gradle clean would break the IDE? Also the patch is ugly, and I wouldn't want everyone who uses Spring AOT to have to use it. So I'm not sure what to do next.
This is the same problem that was described in #1238. In this case, the org.graalvm.buildtools.native contributes the classes directory to the Eclipse classpath. Currently we can only work around the problem (see the previous comment). The correct solution requires a deeper change on how the Gradle classpath is mapped into Eclipse.
Besides the "strange url" (classpath*:*), I could not reproduce!
Nor via:
- tests run
- gradlew (terminal)
- gradle (menu)
Vs Code: v1.78.0
>.\gradlew.bat --version
------------------------------------------------------------
Gradle 8.1.1
------------------------------------------------------------
Build time: 2023-04-21 12:31:26 UTC
Revision: 1cf537a851c635c364a4214885f8b9798051175b
Kotlin: 1.8.10
Groovy: 3.0.15
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.7 (Oracle Corporation 17.0.7+8-LTS-224)
OS: Windows 10 10.0 amd64
>.\gradlew.bat clean build
...
BUILD SUCCESSFUL in 18s
15 actionable tasks: 15 executed
Is this OS-specific? Or rather (recently/unlcky timing) fixed by https://github.com/gradle/gradle/issues/23032 -> https://github.com/redhat-developer/vscode-java/issues/634 -> https://github.com/eclipse/eclipse.jdt.ls/pull/1108 ?
It's not OS-specific. Did you run the tests in the IDE? I just checked in Codespaces and it's still broken with 1.78.1 and the latest Java extensions v0.25.1 (although I'm not sure if that includes the fixes you mentioned).
Did you run the tests in the IDE?
Confirmative, @dsyer.
I am on "release channel" (yesterday was a (code) update between the tests, but tests passed before&after..)
Furthermore: I cannot see the symptom: file.txt is unique (in bin and build folders)
I have all the same versions of extensions and it is still broken for me: test fails and
$ find . -name file.txt
./bin/main/file.txt
./src/main/resources/file.txt
./build/resources/main/file.txt
I also tried with pre-release versions.
ok, now confirm: found the 2nd file(.txt) :see_no_evil:
but still: test passes! :flushed:
let's try in a "uniform" devcontainer!? (OS!?/side effects"!??) :thinking:
Please send a PR for your suggested change at https://github.com/scratches/gradle-aot and/or open an issue there.
I can reproduce on a (linux) dev container, but still not on (minimal, win) profile
changing (source code) to classpath:/*.txt (behaves uniformly on platforms, but)
- fails in gradle
- passes in "vscode test run"
The Spring Boot Gradle plugin introduces additional source sets (aot / aotTest) and corresponding configurations (aotCompileClasspath, aotRuntimeClasspath, ...).
As long as the build (./gradlew build) has not been invoked these sources are not created and no duplicate entries (e.g. file.txt) are added to the classpath. After executing the build (and executing Refresh Gradle Project) these classpath entries are created and lead to the unwanted duplicates.
When the functionality from the Spring AOT plugin is not needed during development in Eclipse you can remove the source sets and configurations in build.gradle:
eclipse {
classpath {
plusConfigurations -= [
configurations.aotCompileClasspath,
configurations.aotRuntimeClasspath,
configurations.aotTestCompileClasspath,
configurations.aotTestRuntimeClasspath
]
sourceSets -= [ sourceSets.aot, sourceSets.aotTest ]
}
}
Now, after invoking Refresh Gradle Project the ConfigTest should complete successfully.
The behavior of the Spring AOT plugin is not OS dependent. I can also reproduce this issue on Windows.