java
java copied to clipboard
Transitive dependency on bucket4j
Describe the bug I have a number of services which are built on top of Spring Kubernetes Client, and thus Kubernetes Java Client and the client-java-extended dependency which has a dependency on bucket4j. We also use bucket4j. However, we are using 8.14 of bucket4j which has a different Maven coordinates than either 7.6.0 (the version pulled in by v 19.0 of the client) or 8.10 (which latest is using) and now incorporates a JDK target number in the artifact name. So we end up with 2 conflicting versions of the library on our classpath, which can lead to confusion.
Client Version 19.0.1
Kubernetes Version v1.32.1 (EKS)
Java Version Java 21
To Reproduce Steps to reproduce the behavior:
Expected behavior Ideally, there should not be a conflict between different versions of transitive dependencies, and a consumer's option to update to a newer, backwards compatible version of the dependency should allow existing libraries with a transitive dependency to work with the updated version. In the event of artifact coordinates changing this contract breaks and multiple versions of the dependency end up on the classpath, with classpath ordering becoming the differentiating factor, which can lead to an older version of the dependency shadowing the newer version. In these situations perhaps some form of shadowing could help protect clients from the impact of the coordinate change? Given the direction of bucket4j moving forward it would seem this is more and more likely to be an issue as a JDK version is being used as part of the artifact name.
This seems to me like a Maven/Java dependency problem unrelated to this library.
If there are things that we can do in our pom.xml to make this easier to resolve, please feel free to send PRs.
The Kubernetes project currently lacks enough contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle stale - Close this issue with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle stale
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues.
This bot triages un-triaged issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Mark this issue as fresh with
/remove-lifecycle rotten - Close this issue with
/close - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/lifecycle rotten
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.
This bot triages issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied - After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied - After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closed
You can:
- Reopen this issue with
/reopen - Mark this issue as fresh with
/remove-lifecycle rotten - Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/close not-planned
@k8s-triage-robot: Closing this issue, marking it as "Not Planned".
In response to this:
The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.
This bot triages issues according to the following rules:
- After 90d of inactivity,
lifecycle/staleis applied- After 30d of inactivity since
lifecycle/stalewas applied,lifecycle/rottenis applied- After 30d of inactivity since
lifecycle/rottenwas applied, the issue is closedYou can:
- Reopen this issue with
/reopen- Mark this issue as fresh with
/remove-lifecycle rotten- Offer to help out with Issue Triage
Please send feedback to sig-contributor-experience at kubernetes/community.
/close not-planned
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.
The core issue Transitive dependency: org.springframework.cloud:spring-cloud-starter-kubernetes-client version 19.0.1 depends on a version of the official kubernetes-client-java. Rate limiting: The Kubernetes client uses bucket4j to implement rate limiting for its API calls. Coordinate change: In bucket4j versions 8.11.0 and later, the artifact coordinates changed to include the JDK version (e.g., bucket4j_jdk17-core). The conflict: Your project explicitly depends on bucket4j version 8.14, likely using the new, JDK-specific coordinates. However, the older version used by the Spring Kubernetes client is pulled in transitively with its old coordinates, resulting in two different artifact names on your classpath.
Solution: Resolving the conflict The most robust solution is to use Maven's dependency management features to explicitly control which version of bucket4j is used for your entire application. Exclude the transitive dependency: The first step is to prevent your project from pulling in the older bucket4j version from spring-cloud-starter-kubernetes-client. You can do this with an exclusion rule in your pom.xml.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-client</artifactId>
<version>19.0.1</version>
<exclusions>
<exclusion>
<groupId>com.github.vladimir-bukhtoyarov</groupId>
<artifactId>bucket4j-core</artifactId>
</exclusion>
</exclusions>
</dependency>
Declare your chosen version: Next, declare your preferred version of the bucket4j library explicitly in your <dependencyManagement> section. This forces all dependencies to use this specified version.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j_jdk17-core</artifactId>
<version>8.14.0</version>
</dependency>
<!-- ... other dependencies -->
</dependencies>
</dependencyManagement>
Override in your dependencies: If the transitive dependency was on a different artifact ID (e.g., bucket4j-core), you would need to declare an explicit dependency with the new artifact ID (bucket4j_jdk17-core) to make sure it is included on the classpath.