Class ConflictResolver
java.lang.Object
org.eclipse.aether.util.graph.transformer.ConflictResolver
- All Implemented Interfaces:
org.eclipse.aether.collection.DependencyGraphTransformer
- Direct Known Subclasses:
ClassicConflictResolver,PathConflictResolver
public class ConflictResolver
extends Object
implements org.eclipse.aether.collection.DependencyGraphTransformer
Abstract base class for dependency graph transformers that resolve version and scope conflicts among dependencies.
For a given set of conflicting nodes, one node will be chosen as the winner. How losing nodes are handled depends
on the configured verbosity level: they may be removed entirely, have their children removed, or be left in place
with conflict information. The exact rules by which a winning node and its effective scope are determined are
controlled by user-supplied implementations of
ConflictResolver.VersionSelector, ConflictResolver.ScopeSelector,
ConflictResolver.OptionalitySelector and ConflictResolver.ScopeDeriver.
Available Implementations:
PathConflictResolver- Recommended high-performance implementation with O(N) complexityClassicConflictResolver- Legacy implementation for backward compatibility (O(N²) worst-case)
Implementation Selection Guide:
- New Projects: Use
PathConflictResolverfor optimal performance - Large Multi-Module Projects: Use
PathConflictResolverto avoid performance bottlenecks - Maven 4+ Environments: Use
PathConflictResolverfor best build performance - Legacy Compatibility: Use
ClassicConflictResolveronly when exact Maven 3.x behavior is required
Usage Example:
// Recommended: High-performance path-based resolver
DependencyGraphTransformer transformer = new ChainedDependencyGraphTransformer(
new PathConflictResolver(
new NearestVersionSelector(),
new JavaScopeSelector(),
new SimpleOptionalitySelector(),
new JavaScopeDeriver()),
// other transformers...
);
// Legacy: Classic resolver for backward compatibility
DependencyGraphTransformer legacyTransformer = new ChainedDependencyGraphTransformer(
new ClassicConflictResolver(
new NearestVersionSelector(),
new JavaScopeSelector(),
new SimpleOptionalitySelector(),
new JavaScopeDeriver()),
// other transformers...
);
Verbosity Levels and Conflict Handling:
- NONE (default): Creates a clean dependency tree without duplicate artifacts. Losing nodes are completely removed from the graph, so are cycles as well.
- STANDARD: Retains losing nodes for analysis but removes their children to prevent
duplicate dependencies. Special handling for version ranges: redundant nodes may still be removed
if multiple versions of the same artifact exist. Losing nodes link back to the winner via
NODE_DATA_WINNERand preserve original scope/optionality information. This mode removes cycles only, while conflict nodes/duplicates are left in place. Graphs in this verbosity level cannot be resolved, their purpose is for analysis only. - FULL: Preserves the complete original graph structure including all conflicts and cycles. All nodes remain with their children, but conflict information is recorded for analysis. Graphs in this verbosity level cannot be resolved, their purpose is for analysis only.
CONFIG_PROP_VERBOSE configuration property.
Conflict Metadata: In STANDARD and FULL modes, the keys NODE_DATA_ORIGINAL_SCOPE
and NODE_DATA_ORIGINAL_OPTIONALITY are used to store the original scope and optionality of each node.
Obviously, dependency trees with verbosity STANDARD or FULL are not suitable for artifact resolution unless
a filter is employed to exclude the duplicate dependencies.
Conflict ID Processing Pipeline:
ConflictMarker: Assigns conflict IDs based on GACE (groupId:artifactId:classifier:extension) coordinates, grouping artifacts that differ only in version (partitions the graph, assigning same conflict IDs to nodes belonging to same conflict group).ConflictIdSorter: Creates topological ordering of conflict IDs and detects cycles- ConflictResolver implementation: Uses the sorted conflict IDs to resolve conflicts in dependency order
TransformationContextKeys.CONFLICT_IDS,
TransformationContextKeys.SORTED_CONFLICT_IDS, TransformationContextKeys.CYCLIC_CONFLICT_IDS for
existing information about conflict ids. In absence of this information, it will automatically invoke the
ConflictIdSorter to calculate it.- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classA context used to hold information that is relevant for resolving version and scope conflicts.static classA conflicting dependency.static classAn extension point ofConflictResolverthat determines the effective optional flag of a dependency from a potentially conflicting set of derived optionalities.static classA context used to hold information that is relevant for deriving the scope of a child dependency.static classAn extension point ofConflictResolverthat determines the scope of a dependency in relation to the scope of its parent.static classAn extension point ofConflictResolverthat determines the effective scope of a dependency from a potentially conflicting set ofderived scopes.static enumThe enum representing verbosity levels of conflict resolver.static classAn extension point ofConflictResolverthat determines the winner among conflicting dependencies. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final Stringstatic final StringThe name of the conflict resolver implementation to use: "path" (default) or "classic" (same as Maven 3).static final StringThe key in the repository session'sconfiguration propertiesused to store aBooleanflag controlling the transformer's verbose mode.static final Stringstatic final StringThe key in the dependency node'scustom dataunder which the optional flag of the dependency before derivation and conflict resolution is stored.static final StringThe key in the dependency node'scustom dataunder which the scope of the dependency before scope derivation and conflict resolution is stored.static final StringThe key in the dependency node'scustom dataunder which a reference to theDependencyNodewhich has won the conflict is stored.static final String -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedNo arg ctor for subclasses and default cases.ConflictResolver(ConflictResolver.VersionSelector versionSelector, ConflictResolver.ScopeSelector scopeSelector, ConflictResolver.OptionalitySelector optionalitySelector, ConflictResolver.ScopeDeriver scopeDeriver) Creates a new conflict resolver instance with the specified hooks that delegates to configured conflict resolver dynamically. -
Method Summary
Modifier and TypeMethodDescriptionstatic ConflictResolver.VerbositygetVerbosity(org.eclipse.aether.RepositorySystemSession session) Helper method that usesRepositorySystemSessionandCONFIG_PROP_VERBOSEkey to figure out currentConflictResolver.Verbosity: ifBooleanorStringfound, returnsConflictResolver.Verbosity.STANDARDorConflictResolver.Verbosity.NONE, depending on value (string is parsed withBoolean.parseBoolean(String)fortrueorfalsecorrespondingly.org.eclipse.aether.graph.DependencyNodetransformGraph(org.eclipse.aether.graph.DependencyNode node, org.eclipse.aether.collection.DependencyGraphTransformationContext context)
-
Field Details
-
CONFIG_PROP_VERBOSE
The key in the repository session'sconfiguration propertiesused to store aBooleanflag controlling the transformer's verbose mode. Accepted values are Boolean types, String type (where "true" would be interpreted astrue) or Verbosity enum instances.- See Also:
- Sourced from:
RepositorySystemSession.getConfigProperties()- Value type:
Object- Default value:
- "NONE"
-
CONFIG_PROP_CONFLICT_RESOLVER_IMPL
The name of the conflict resolver implementation to use: "path" (default) or "classic" (same as Maven 3).- Since:
- 2.0.11
- See Also:
- Sourced from:
RepositorySystemSession.getConfigProperties()- Value type:
String- Default value:
DEFAULT_CONFLICT_RESOLVER_IMPL
-
CLASSIC_CONFLICT_RESOLVER
- See Also:
-
PATH_CONFLICT_RESOLVER
- See Also:
-
DEFAULT_CONFLICT_RESOLVER_IMPL
- See Also:
-
NODE_DATA_WINNER
The key in the dependency node'scustom dataunder which a reference to theDependencyNodewhich has won the conflict is stored.- See Also:
-
NODE_DATA_ORIGINAL_SCOPE
The key in the dependency node'scustom dataunder which the scope of the dependency before scope derivation and conflict resolution is stored.- See Also:
-
NODE_DATA_ORIGINAL_OPTIONALITY
The key in the dependency node'scustom dataunder which the optional flag of the dependency before derivation and conflict resolution is stored.- See Also:
-
-
Constructor Details
-
ConflictResolver
protected ConflictResolver()No arg ctor for subclasses and default cases. -
ConflictResolver
public ConflictResolver(ConflictResolver.VersionSelector versionSelector, ConflictResolver.ScopeSelector scopeSelector, ConflictResolver.OptionalitySelector optionalitySelector, ConflictResolver.ScopeDeriver scopeDeriver) Creates a new conflict resolver instance with the specified hooks that delegates to configured conflict resolver dynamically.- Parameters:
versionSelector- the version selector to use, must not benullscopeSelector- the scope selector to use, must not benulloptionalitySelector- the optionality selector ot use, must not benullscopeDeriver- the scope deriver to use, must not benull
-
-
Method Details
-
getVerbosity
public static ConflictResolver.Verbosity getVerbosity(org.eclipse.aether.RepositorySystemSession session) Helper method that usesRepositorySystemSessionandCONFIG_PROP_VERBOSEkey to figure out currentConflictResolver.Verbosity: ifBooleanorStringfound, returnsConflictResolver.Verbosity.STANDARDorConflictResolver.Verbosity.NONE, depending on value (string is parsed withBoolean.parseBoolean(String)fortrueorfalsecorrespondingly. This is to retain "existing" behavior, where the config key accepted only these values. Since 1.9.8 release, this key may containConflictResolver.Verbosityenum instance as well, in which case that instance is returned. This method never returnsnull. -
transformGraph
public org.eclipse.aether.graph.DependencyNode transformGraph(org.eclipse.aether.graph.DependencyNode node, org.eclipse.aether.collection.DependencyGraphTransformationContext context) throws org.eclipse.aether.RepositoryException - Specified by:
transformGraphin interfaceorg.eclipse.aether.collection.DependencyGraphTransformer- Throws:
org.eclipse.aether.RepositoryException
-