buildship icon indicating copy to clipboard operation
buildship copied to clipboard

Duplicate results in the classpath when using spring aot plugin

Open CsCherrYY opened this issue 2 years ago • 15 comments

Steps to Reproduce

  1. git clone https://github.com/scratches/gradle-aot
  2. run ./gradlew clean build in the project root folder
  3. Open the project in VS Code or eclipse
  4. 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. image

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

CsCherrYY avatar Apr 17 '23 06:04 CsCherrYY

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 avatar Apr 17 '23 09:04 dsyer

@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 avatar Apr 18 '23 09:04 CsCherrYY

@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'
+                }
+            }
+        }
+    }
+  }
+}

snjeza avatar Apr 24 '23 13:04 snjeza

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 avatar Apr 25 '23 22:04 dsyer

@dsyer you may want to take a look at https://github.com/eclipse/buildship/issues/1131#issuecomment-1014559863

snjeza avatar Apr 26 '23 12:04 snjeza

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.

dsyer avatar Apr 26 '23 12:04 dsyer

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.

donat avatar Apr 27 '23 13:04 donat

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 ?

xerx593 avatar May 09 '23 18:05 xerx593

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).

dsyer avatar May 10 '23 06:05 dsyer

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)

image

xerx593 avatar May 10 '23 10:05 xerx593

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.

dsyer avatar May 10 '23 10:05 dsyer

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:

xerx593 avatar May 10 '23 11:05 xerx593

Please send a PR for your suggested change at https://github.com/scratches/gradle-aot and/or open an issue there.

dsyer avatar May 10 '23 11:05 dsyer

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"

xerx593 avatar May 10 '23 14:05 xerx593

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.

oleosterhagen avatar Jun 30 '24 09:06 oleosterhagen