Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capability conflict not detected for a certain dependency ordering #22326

Open
jjohannes opened this issue Oct 6, 2022 · 6 comments
Open

Capability conflict not detected for a certain dependency ordering #22326

jjohannes opened this issue Oct 6, 2022 · 6 comments
Labels
a:bug in:dependency-resolution engine metadata @support Issues owned by GBT support team

Comments

@jjohannes
Copy link
Contributor

If I have dependencies defined in a specific order (see reproducer) a capability conflict is not detected.

Expected Behavior

The capability conflict is detected and resolved as defined in the corresponding capabilities resolution strategy.

Current Behavior

The capability conflict is not detected. (Workaround: Change the order of dependencies.)

Context

This issue suddenly appeared when we added a dependency (Hibernate in this case) again in another place to make it visible there at compile time. Without the detection of the conflict, we got multiple Jars with the same classes on the classpath.

Steps to Reproduce

  • Checkout reproducer project: https://github.com/jjohannes/gradle-demos/tree/main/capability-conflict-detection-issue
  • Run $ ./gradlew :extension:dependencies --configuration=runtimeClasspath --scan and inspect the result
  • The conflict between javax.transaction:javax.transaction-api:1.3 and org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.1.1.Final is not detected although both have the javax.transaction:javax.transaction-api capability
  • Change the order of dependencies in app/build.gradle.kts - the conflict is now detected

Your Environment

Build scan URL - with issue: https://scans.gradle.com/s/sljcle3av5nae/dependencies?dependencies=transaction&expandAll&focusedDependency=WzAsMCwxMixbMCwwLFswXV1d
Build scan URL - issue disappeared after changing order: https://scans.gradle.com/s/zydyc3jau2jho/dependencies?dependencies=transaction&expandAll&focusedDependency=WzAsMCwyLFswLDAsWzBdXV0

jjohannes added a commit to jjohannes/gradle-demos that referenced this issue Oct 6, 2022
@jjohannes jjohannes changed the title Capability conflict not detected if for certain dependency ordering Capability conflict not detected for a certain dependency ordering Oct 6, 2022
@jbartok jbartok added in:dependency-resolution engine metadata @support Issues owned by GBT support team and removed to-triage labels Oct 13, 2022
@jjohannes
Copy link
Contributor Author

jjohannes commented Apr 17, 2023

We were hitting this again today. Maybe there is also a relationship to (some cases of) #14220.

@jjohannes
Copy link
Contributor Author

Another reproducer. Without using any additional plugins, just a dependency to Guava which now publishes Gradle Metadata with capabilities: google/guava#6618 (comment)

@jjohannes
Copy link
Contributor Author

Any chance fixing this may get some priority?

This is a quite severe issue for projects that aim for a clean dependency graph by utilizing capabilities to detect and resolve conflicts. If this mechanism is not reliable, it is very hard to use and might break suddenly when you add a new dependency.
If you are not super familiar with the inner working of things, you just keep wondering why suddenly a capability is no longer respected. And there is no clear workaround except for adding artificial dependencies to change the order of things in the graph and hope that that will keep things stable.

@jjohannes
Copy link
Contributor Author

#14220 (comment)

@jjohannes
Copy link
Contributor Author

This issue is still present in 8.11-rc-2 despite the changes of #30363.

jjohannes added a commit to gradlex-org/jvm-dependency-conflict-resolution that referenced this issue Nov 12, 2024
@jjohannes
Copy link
Contributor Author

jjohannes commented Nov 12, 2024

With Gradle 8.11 you can also reproduce an issue like this as follows.

Working Example

Consider this working example with capability conflict on com.google.collections:google-collections

plugins {
    id("java-library")
}

dependencies {
    implementation("com.google.collections:google-collections:1.0")
    implementation("com.google.guava:guava:33.3.1-jre")
}

repositories { mavenCentral() }
configurations.all {
    resolutionStrategy.capabilitiesResolution.withCapability("com.google.collections:google-collections") { select("com.google.guava:guava:0" }
}

The capability conflict is detected and resolved:

+--- com.google.collections:google-collections:1.0 -> com.google.guava:guava:33.3.1-jre
|    +--- com.google.guava:failureaccess:1.0.2
|    +--- com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava
|    +--- com.google.code.findbugs:jsr305:3.0.2
|    +--- org.checkerframework:checker-qual:3.43.0
|    +--- com.google.errorprone:error_prone_annotations:2.28.0
|    \--- com.google.j2objc:j2objc-annotations:3.0.0
\--- com.google.guava:guava:33.3.1-jre (*)

Scan: https://scans.gradle.com/s/h4u7al2b6bles/dependencies?toggled=W1swXSxbMCwxXV0

Broken Example

When we modify the sample and add the org.gradlex.jvm-dependency-conflict-detection plugin

plugins {
    id("java-library")
    id("org.gradlex.jvm-dependency-conflict-detection") version "2.1.2"
}

dependencies {
    implementation("com.google.collections:google-collections:1.0")
    implementation("com.google.guava:guava:33.3.1-jre")
}
...

The capability conflict is NOT detected and resolved:

compileClasspath
+--- com.google.collections:google-collections:1.0
\--- com.google.guava:guava:33.3.1-jre
     +--- com.google.guava:failureaccess:1.0.2
     +--- com.google.code.findbugs:jsr305:3.0.2
     +--- org.checkerframework:checker-qual:3.43.0
     +--- com.google.errorprone:error_prone_annotations:2.28.0
     \--- com.google.j2objc:j2objc-annotations:3.0.0

What the plugin is doing is adding additional the additional capability com.google.guava:listenablefuture to com.google.guava:guava:33.3.1-jre. This is also causing a conflict with a child of guava which is resolved. Maybe the fact that Guava is participating in two conflicts and one of the conflicts is with its own child is causing this behavior.

Scan: https://scans.gradle.com/s/o6cjvfmpaekg2/dependencies?toggled=W1swXSxbMCwxXV0

Fix by changing order

Changing the order of dependencies, fixes the issue.

plugins {
    id("java-library")
    id("org.gradlex.jvm-dependency-conflict-detection") version "2.1.2"
}

dependencies {
    implementation("com.google.guava:guava:33.3.1-jre")
    implementation("com.google.collections:google-collections:1.0")
}
...
+--- com.google.guava:guava:33.3.1-jre
|    +--- com.google.guava:failureaccess:1.0.2
|    +--- com.google.code.findbugs:jsr305:3.0.2
|    +--- org.checkerframework:checker-qual:3.43.0
|    +--- com.google.errorprone:error_prone_annotations:2.28.0
|    \--- com.google.j2objc:j2objc-annotations:3.0.0
\--- com.google.collections:google-collections:1.0 -> com.google.guava:guava:33.3.1-jre (*)

Scan: https://scans.gradle.com/s/dt72ui4du55x4/dependencies?toggled=W1swXSxbMCwxXV0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:bug in:dependency-resolution engine metadata @support Issues owned by GBT support team
Projects
None yet
Development

No branches or pull requests

2 participants