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

Build failure if Guava 32.1.x is applied to the Checkstyle classpath using the Spring Dependency Management plugin #27035

Closed
mjustin opened this issue Nov 13, 2023 · 4 comments
Assignees
Labels
a:bug closed:not-fixed Indicates the issue was not fixed and is not planned to be has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround in:checkstyle-plugin

Comments

@mjustin
Copy link

mjustin commented Nov 13, 2023

Current Behavior

I have an existing project that uses the Gradle Checkstyle plugin (Checkstyle 10.12.1), and uses the Spring Dependency Management Plugin to manage dependency versions including the Guava version (32.0.1-jre). When I upgrade both of these to the latest versions (Checkstyle 10.12.4 and Guava 32.1.3-jre), I get a build failure. If I only upgrade one but not the other, the build continues to pass.

Failure:

Execution failed for task ':checkstyleMain'.
> Could not resolve all files for configuration ':checkstyle'.
   > Could not resolve com.google.guava:guava:32.0.1-jre.
     Required by:
         project : > com.puppycrawl.tools:checkstyle:10.12.4
      > Module 'com.google.guava:guava' has been rejected:
           Cannot select module with conflict on capability 'com.google.collections:google-collections:32.1.3-jre' also provided by [com.google.collections:google-collections:1.0(runtime)]
   > Could not resolve com.google.collections:google-collections:1.0.
     Required by:
         project : > com.puppycrawl.tools:checkstyle:10.12.4 > org.apache.maven.doxia:doxia-core:1.12.0 > org.codehaus.plexus:plexus-container-default:2.1.0
      > Module 'com.google.collections:google-collections' has been rejected:
           Cannot select module with conflict on capability 'com.google.collections:google-collections:1.0' also provided by [com.google.guava:guava:32.1.3-jre(jreRuntimeElements)]

build.gradle:

plugins {
    id 'java'
    id 'checkstyle'
    id 'io.spring.dependency-management' version '1.1.4'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencyManagement {
    dependencies {
        dependency 'com.google.guava:guava:32.1.3-jre'
    }
}

checkstyle {
    toolVersion = '10.12.4'
}

Expected Behavior

The build should not fail with a file resolution error.

If everything in the build is good, including all Checkstyle checks, the build should succeed. If any Checkstyle checks fail, the build should fail with the Checkstyle failures.

Context (optional)

I use the Spring Dependency Management plugin to ensure all dependencies in a large multi-module project are consistent. I use this for both Spring Boot-managed dependencies in org.springframework.boot:spring-boot-dependencies:3.1.5, and non-Boot dependencies (such as Gradle).

I am attempting to use the latest Gradle version and latest Checkstyle version.

The crux of the issue is that the Checkstyle plugin transitively depends on the very old google-collections library that was superseded by Guava over a decade ago:

com.puppycrawl.tools:checkstyle:10.12.4 > org.apache.maven.doxia:doxia-core:1.12.0 > org.codehaus.plexus:plexus-container-default:2.1.0 > com.google.collections:google-collections:1.0

One workaround is to explicitly tell Gradle that Google collections has been replaced by Guava:

dependencies {
    modules {
        module("com.google.collections:google-collections") {
            replacedBy("com.google.guava:guava", "Google Collections is part of Guava")
        }
    }
}

A different workaround is to use org.codehaus.plexus:plexus-container-default:2.1.1 instead of 2.1.0, as that does not have the Google Collections dependency:

dependencyManagement {
    dependencies {
        dependency 'com.google.guava:guava:32.1.3-jre'
        dependency 'org.codehaus.plexus:plexus-container-default:2.1.1'
    }
}

Since doxia-core 2.0 is still in a milestone version, I wonder if the easiest fix for the Checkstyle plugin at this point would be to explicitly use plexus-container-default:2.1.1 or to exclude google-collections from its plugin dependencies.

Steps to Reproduce

On a Unix-like system (e.g. macOS):

git clone https://github.com/mjustin/gradle-checkstyle-guava-issue
cd gradle-checkstyle-guava-issue
./gradlew checkstyleMain

Gradle version

8.4

Build scan URL (optional)

No response

Your Environment (optional)

No response

@jjohannes
Copy link
Contributor

As well analyzed by @mjustin in the description, this is not directly a bug in Gradle, but the metadata of com.puppycrawl.tools:checkstyle (or its transitive dependencies) is not "ideal". You end up with both "Google Collections" and "Guava" on the checkstyle classpath, which contain overlapping packages and classes.

The failure is actually an improvement in the metadata of Guava. Gradle is now able to detect that Guava and Google Collections are in conflict and should not be used together. And now we know that the "checkstyle classpath" is not clean.

I agree that Gradle's checkstyle plugin could/should add a rule to resolve this conflict automatically. The right/best way to do that is to add a strategy for the capability the conflict is about:

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

See also Guava release notes: https://github.com/google/guava/releases/tag/v32.1.0

@ljacomet
Copy link
Member

ljacomet commented Nov 16, 2023

Thanks @jjohannes for the explanation. I figured that out as well but I am trying to understand why the Gradle error message ends up mentioning version 32.0.1-jre of guava - which does not have Gradle Module Metadata - instead of version 32.1.3-jre. As this makes reading the error harder than it should be.

And I figured it out: this is caused by the way the Spring dependency management plugin ends up forcing the Guava version.

In short, as explained by Jendrik, the behavior is expected and is not Gradle resolution bug. I agree however that the core Checkstyle plugin should account for this and be configured to resolve that conflict automatically.

@mjustin Thank you for providing a valid report.

The issue is in the backlog of the relevant team, but the existence of a workaround makes it non-critical, so it might take a while before a fix is made.

@ljacomet ljacomet added in:checkstyle-plugin has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround and removed to-triage labels Nov 16, 2023
@mjustin
Copy link
Author

mjustin commented Nov 16, 2023

@jjohannes

The right/best way to do that is to add a strategy for the capability the conflict is about:

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

See also Guava release notes: https://github.com/google/guava/releases/tag/v32.1.0

Despite having looked through those release notes myself, I missed that workaround; I think I skimmed too fast. I can confirm that's also a successful workaround in my submitted example.

makmn1 added a commit to GroupHQ/group-service that referenced this issue Dec 7, 2023
makmn1 added a commit to GroupHQ/group-sync that referenced this issue Dec 7, 2023
sir-gon pushed a commit to sir-gon/algorithm-exercises-java that referenced this issue Dec 10, 2023
sir-gon pushed a commit to sir-gon/algorithm-exercises-java that referenced this issue Dec 10, 2023
gjvoosten added a commit to NCI-Agency/anet that referenced this issue Dec 14, 2023
murdos added a commit to murdos/jhipster-lite that referenced this issue Jan 5, 2024
AB-xdev added a commit to xdev-software/intellij-plugin-template that referenced this issue Apr 10, 2024
AB-xdev added a commit to xdev-software/intellij-plugin-template that referenced this issue Apr 10, 2024
@big-guy
Copy link
Member

big-guy commented May 13, 2024

@ljacomet I think instead of putting this capability conflict resolution in the Checkstyle plugin itself, we should have a way for a module to publish/replace old coordinates itself via GMM. In that case, the metadata would be interpreted in a way that automatically resolves the capability conflict. The reason being is that it's not just one place where this capability conflict needs to be resolved. It would need to be fixed everywhere.

Given there's a workaround and we know what's happening here, I think we should close this and add the missing feature to GMM.

@big-guy big-guy closed this as not planned Won't fix, can't repro, duplicate, stale May 13, 2024
@ov7a ov7a added closed:not-fixed Indicates the issue was not fixed and is not planned to be and removed to-triage labels May 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:bug closed:not-fixed Indicates the issue was not fixed and is not planned to be has:reproducer Indicates the issue has a confirmed reproducer has:workaround Indicates that the issue has a workaround in:checkstyle-plugin
Projects
None yet
Development

No branches or pull requests

5 participants