Conflict Resolvers
Synopsis
A dependency version conflict occurs when building a Maven project whose dependency graph pulls in two different versions of the same dependency. Maven must decide which version of the conflicting dependency to use before proceeding with the build. The behaviour thus far has always been to select the version in the dependency graph that is 'nearest' to the project being built, where the distance is defined to be the number of transitive steps between two nodes in the graph. This aim of this proposal is to allow alternative conflict resolution techniques to be used when building projects with Maven.
Design
The existing but unused ConflictResolver interface will become the basis for the conflict resolver API. The following method will be added to handle conflict resolutions:
The following ConflictResolver implementations will be provided:
Name |
Strategy |
|---|---|
nearest |
Resolves conflicting artifacts by always selecting the |
farthest |
Resolves conflicting artifacts by always selecting the |
newest |
Resolves conflicting artifacts by always selecting the |
oldest |
Resolves conflicting artifacts by always selecting the |
ArtifactCollector will have an additional method added to accept a list of ConflictResolvers:
Correspondingly, DefaultArtifactCollector will be updated to process the chain of ConflictResolvers to resolve dependency version conflicts. The chain will be processed until one ConflictResolver can resolve the conflict. In the event that no ConflictResolvers can resolve the conflict, an ArtifactResolutionException will be thrown to fail the build.
ArtifactResolver will also have a corresponding new method in order to delegate to the new ArtifactCollector method:
To ensure that the conflict resolution strategy is consistent throughout the build, all usages of ArtifactCollector and ArtifactResolver within Maven will be updated to use these new overloaded versions. The list of ConflictResolvers to use will be obtained from the MavenProject being built. In order to preserve the 2.0.x POM schema, a POM property will initially be used to configure the ConflictResolver chain. The POM property will be named mavenConflictResolvers and its value will be defined as a comma-separated list of conflict resolver names. For example:
For 2.1.x, it is likely that the POM schema will be modified to introduce a more appropriate syntax for configuring conflict resolvers. For example:
For backwards compatibility, if a project does not declare any conflict resolvers then the 'nearest' conflict resolver will be used by default.
5 Comments
Hide/Show CommentsOct 31, 2007
Reto Bachmann-Gmür
I'd suggest to add also a conflict-resolution method 'fail' which causes a build to fail id two different versions of an artifact are referenced. Generally this would enforce updating the project basing on an older version.
Ideally, I should be able to set the 'fail' mode only for dependencies of a set of projects, e.g. those with group-id matching org.example.*.
Feb 16, 2008
mihhon
why do not allow the user to specify explicitly the compatibility of artifact versions so maven could decide to choose the latest version if it is backward-compatible ? and to fail the build process in the case of non-compatibility with a readable error message
May 22, 2008
Paul Gier
It would be helpful to also have a way to load a custom conflict resolvers as an extension. Maybe the custom resolver could have it's name defined internally, and then you could choose to use it by doing something like:
<dependencies> <conflictResolvers> <conflictResolver>newest</conflictResolver> <conflictResolver>myCustomResolver</conflictResolver> <conflictResolver>nearest</conflictResolver> </conflictResolvers> </dependencies>Jun 03, 2008
Paul Gier
Mark, do you have an example of when you would want to use more than one conflict resolver? It seems like only one would ever be needed for a single build.
Jun 10, 2008
Ian Robertson
How would ConflictResolvers interact with VersionRanges? The current behavior of maven when a one or more VersionRanges is introduced is to select the highest numbered version available in the repository which lives in the intersection of all VersionRanges. Would a ConflictResolver override this behavior, or be overridden by it?