redhat-developer / redhat-developer/vscode-java

Gradle multi-project import materializes internal build/libs jars into live JDT classpath

Aperta
#4,399 4 commenti 1 reazione 1 assegnatario Vedi su GitHub

@snjeza ci sta già lavorando.

Dal 21/4/2026.

bug
Lingua principale
TypeScript
Stelle
2.3k
Fork
546
Merge medio
20h 1m
PR unite (30g)
11

Descrizione

Summary

In a Gradle multi-project Java workspace, local subproject dependencies are resolved correctly as project references in the Buildship-saved model, but the live JDT/Eclipse project classpath is later materialized with internal build/libs/*.jar entries instead.

This causes local multi-module dependencies to behave like jar dependencies rather than live project/classfile dependencies, and can trigger stale or missing-library failures when those jars are rebuilt with different names.

Related discussion

I am filing here because the evidence points at the Java tooling / import / classpath materialization stack rather than a Cursor-specific layer.

Environment

  • OS: Windows 11
  • Java tooling: Language Support for Java by Red Hat
  • Build tool: Gradle multi-project build
  • Repo root: C:\Users\<USER>\git\<REPO>
  • Affected example project: admin-tools

Observed Java server startup includes:

  • -Djava.import.generatesMetadataFilesAtProjectRoot=false

Affected dependency shape

The affected project depends on local Gradle subprojects via normal project dependencies, for example:

  • project(":server-common")
  • project(":db-common")
  • project(":runtime-common")

Expected behavior

After import/reload, local Gradle subprojects should remain project references in the live Java project model.

The live classpath should not re-add internal jars from:

  • server-common/build/libs/*.jar
  • db-common/build/libs/*.jar
  • runtime-common/build/libs/*.jar

Actual behavior

After restart / re-import, the live classpath for admin-tools contains internal jars again, for example:

  • C:\Users\<USER>\git\<REPO>\runtime-common\build\libs\runtime-common-20260420175810.jar
  • C:\Users\<USER>\git\<REPO>\db-common\build\libs\db-common-20260420175810.jar
  • C:\Users\<USER>\git\<REPO>\server-common\build\libs\server-common-20260420175810.jar

These entries come back even if removed before restart.

Confirmed findings

1. Buildship-saved model is correct

File:

C:\Users\<USER>\AppData\Roaming\Cursor\User\workspaceStorage\<WORKSPACE_ID>\redhat.java\jdt_ws\.metadata\.plugins\org.eclipse.buildship.core\project-preferences\admin-tools

What was verified:

  • classpath= contains project refs such as /server-common, /db-common, /runtime-common
  • it contains normal external dependencies from .gradle\caches
  • it does not contain internal repo jar paths under <REPO>/*/build/libs

This strongly suggests the Buildship-side saved model is correct.

2. Live JDT/Eclipse classpath is wrong

File:

C:\Users\<USER>\AppData\Roaming\Cursor\User\workspaceStorage\<WORKSPACE_ID>\redhat.java\jdt_ws\.metadata\.plugins\org.eclipse.core.resources\.projects\admin-tools\.classpath

Observed contents include:

<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/runtime-common/build/libs/runtime-common-20260420175810.jar"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/db-common/build/libs/db-common-20260420175810.jar"/>
<classpathentry kind="lib" path="C:/Users/<USER>/git/<REPO>/server-common/build/libs/server-common-20260420175810.jar"/>

So the live Eclipse/JDT classpath is being materialized incorrectly after the Buildship model is already correct.

3. Repo-root .classpath is not the active source

Before restart, these were deleted:

  • repo-level admin-tools/.classpath
  • workspace org.eclipse.core.resources/.../admin-tools/.classpath
  • workspace org.eclipse.buildship.core/project-preferences/admin-tools

After restart:

  • the repo-level admin-tools/.classpath did not get recreated
  • the workspace live .classpath did get recreated
  • the Buildship project-preferences file also got recreated

This suggests the active regeneration is happening from the Java workspace/import pipeline, not from repo-root Eclipse metadata.

4. Gradle eclipse customization produced the correct model-side result

I tested targeted eclipse.classpath.file.whenMerged customization in affected subprojects to:

  • remove internal build/libs/*.jar entries
  • add explicit project refs such as /server-common, /db-common, /runtime-common

I then ran:

  • :admin-tools:eclipseClasspath
  • :db-common:eclipseClasspath
  • :runtime-common:eclipseClasspath

The generated .classpath outputs were correct immediately after generation, with project references present and internal local build/libs/*.jar entries absent.

This suggests the custom merge logic is not being ignored at the model-generation step.

5. Multiple importers were active in logs

Java language server logs showed multiple importers active, including:

  • GradleBuildServerProjectImporter
  • GradleProjectImporter
  • EclipseProjectImporter

That may be relevant if this is an importer precedence / post-processing issue.

6. Wrapper upgrade had no effect

I upgraded the project Gradle wrapper from 8.5 to 8.14.3 and re-tested.

The bad internal jar materialization still occurred, so this does not look like a simple mismatch between system Gradle and wrapper Gradle.

7. Disabling Gradle import was not a usable workaround

I also tested disabling java.import.gradle.enabled.

That severely broke import/build behavior rather than solving the classpath issue, so it does not appear to be a valid workaround.

Reproduction outline

  1. Open a Gradle multi-project Java workspace.
  2. Ensure one project depends on local subprojects via implementation project(...).
  3. Let Java/Gradle import complete.
  4. Inspect the Buildship-saved model under org.eclipse.buildship.core/project-preferences/....
  5. Inspect the live Eclipse/JDT project classpath under org.eclipse.core.resources/.projects/.../.classpath.
  6. Observe that the saved model contains project refs, but the live classpath contains internal build/libs/*.jar entries.

Impact

  • breaks expected live multi-module development workflow
  • makes the editor prefer built jar artifacts over local project/classfile references
  • can reintroduce stale or timestamped jar references on restart
  • can trigger missing-library failures when jar names change

Current hypothesis

The problem appears to happen after Buildship has already produced the correct model, during the step where org.eclipse.buildship.core.gradleclasspathcontainer is materialized into the live JDT/Eclipse project classpath.

If useful, I can provide the relevant anonymized project-preferences content, the resulting live .classpath, and the Java language server log excerpts showing the active importers.

Suggested investigation area

Please inspect how the Gradle/Buildship model is handed off to the live JDT project classpath, especially where org.eclipse.buildship.core.gradleclasspathcontainer is resolved and written into the live .classpath when local Gradle subprojects are already present as project references in the saved model.

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.