apache / apache/maven

[MNG-7852] Use all the versions for dependency resolution rather than "nearest first" or "declared first"

Open
#9,070 17 comments 3 reactions 0 assignees View on GitHub
enhancement priority:major
Dominant language
Java
Stars
5.3k
Forks
3.1k
Avg merge
20h 42m
Merged PRs (30d)
297

Description

**[Vladimir Sitnikov](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=vladimirsitnikov)** opened **[MNG-7852](https://issues.apache.org/jira/browse/MNG-7852?redirect=false)** and commented

Currently, Maven uses "nearest first", "declared first" rules for conflict resolution: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

I suggest those rules are removed since they produce hard to reason resolutions for transitive dependencies.
Below I list reasons why both "nearest wins" and "declared first" yield hard-to-predict behaviours, and they are likely to produce dependency downgrades and the associated runtime errors.

Here are some examples:
1) "Nearest first". Even though the rule sounds easy, it is not something the users can control. For instance, if the project does not use Guava library, some of the transitive dependencies could add a dependency on Guava. The user has no control which dependency would be "the nearest" to declare Guava, so user has literally no way to tell which Guava version will be used.
The only workaround I see for the users is to declare Guava dependency explicitly even though the project does not need it directly. It sounds like Maven requires users to re-declare all the possible dependencies, including the runtime-only ones.

2) "declared first". Of course, dependency order matters for classpath order, however, it is not predictable in practice, and it might result in downgrading dependencies. Imagine the project does not use Guice. However, transitive dependencies might use Guice. At the same time, they might start using Guice and stop using Guice, so the user can never tell which will be the first project that uses Guice. Unfortunately, in Maven, the first project that declares dependency wins, so it might easily be the case that the first mention of Guice will reference outdated version that would be incompatible with the newer one required in another dependency.

3) Here's a real-life case: Maven downgrades protobuf-java dependency causing something like NoSuchMethodError at the runtime. The step to reproduce is to add dependency on dev.sigstore:sigstore-java:0.4.0. See [Hervé Boutemy](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=hboutemy) analysis in https://github.com/hboutemy/sigstore-maven-plugin/blob/import/analysis.md
Long story short, sigstore-java does not depend on protobuf-java directly, however, sigstore-java depends on several third-party libraries that eventually depend on protobuf-java. Maven's "the first wins" behaviour results in incoherent set of protobuf dependencies on the classpath.

4) see "unexpected" in MNG-5988

To my best understanding, when it comes to transitive dependencies, both "nearest first" and "declared first" are random variables which user can't control unless they re-declare all the dependencies in their local pom. I suggest Maven should not use random variables like "dependency depth" or "dependency order" to drive conflict resolution.

---

**Issue Links:**
- [MNG-2672](https://issues.apache.org/jira/browse/MNG-2672) Wrong dependency handling when having dependencies to artifacts in different versions
(_**"fixes"**_)
- [MNG-3072](https://issues.apache.org/jira/browse/MNG-3072) Dependency with lower version number is chosen
(_**"fixes"**_)
- [MNG-5980](https://issues.apache.org/jira/browse/MNG-5980) DependencyGraphBuilder gives different results depending on the order of dependencies in the pom
(_**"incorporates"**_)
- [MNG-4175](https://issues.apache.org/jira/browse/MNG-4175) Dependency mediation - allow for different strategies
(_**"incorporates"**_)
- [MNG-6058](https://issues.apache.org/jira/browse/MNG-6058) Test dependencies should override application dependencies only during testing

- [MNG-6224](https://issues.apache.org/jira/browse/MNG-6224) Dependency version from test scope leaks into compile scope

- [MNG-5739](https://issues.apache.org/jira/browse/MNG-5739) Adding a test dependency can move dependencies from the compile scope to the test scope

- [MNG-5988](https://issues.apache.org/jira/browse/MNG-5988) Dependency mediation should prioritize transitive dependencies based on scope.

- [MNG-5971](https://issues.apache.org/jira/browse/MNG-5971) Imported dependencies should be available to inheritance processing

- [MNG-5057](https://issues.apache.org/jira/browse/MNG-5057) The order in which you declare dependencies in pom.xml affect resulting WAR file

- [MNG-4692](https://issues.apache.org/jira/browse/MNG-4692) Maven choose the wrong transitive dependency

- [MNG-6357](https://issues.apache.org/jira/browse/MNG-6357) Dependency order should be nearest first
(_**"supercedes"**_)

1 votes, 5 watchers

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.