-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Summary
Currently, Maven's resolver treats direct dependencies (declared in a POM) as absolute version requirements that always override transitive dependencies, even when transitive deps require higher versions. This requires extensive use of <dependencyManagement> blocks to control resolution. This RFE proposes a configurable mechanism to allow more flexible version resolution while maintaining user control.
Motivation
- Current Pain Point: Developers must explicitly manage many transitive dependencies through
<dependencyManagement>to avoid version conflicts - Flexibility Need: Different projects have different requirements—some need strict version control, others prefer automatic upgrades to satisfy transitive requirements
- Control Concern: Any change to default resolution behavior risks breaking builds unexpectedly (e.g., in reactor builds where in-development versions could be downgraded)
Proposed Solution
Introduce an optional directDependencyStrategy attribute at both project and dependency levels to control how direct dependencies participate in version conflict resolution:
<project directDependencyStrategy="flexible">
<dependencies>
<!-- Strategy "flexible" applies: allows transitive deps to override this version -->
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-a</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>Or at the individual dependency level:
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-b</artifactId>
<version>2.0</version>
<directDependencyStrategy>fixed</directDependencyStrategy> <!-- This version always wins -->
</dependency>Strategy Options
fixed(default): Direct dependency version is absolute; always wins version conflicts (current behavior)flexible: Allow the configured version resolver to apply its normal conflict resolution rules (e.g., highest version, nearest) even for direct dependencies, permitting transitive dependencies to override this direct dependency
Configuration
Strategy default can be controlled at multiple levels (lowest precedence to highest):
-
Maven Configuration:
maven.resolver.directDependencyStrategyproperty<properties> <maven.resolver.directDependencyStrategy>flexible</maven.resolver.directDependencyStrategy> </properties>
-
Project Level:
<project directDependencyStrategy="...">in POM -
Dependency Level:
<directDependencyStrategy>within individual<dependency>block
Consumer Behavior
When a direct dependency with non-default strategy is consumed as a transitive dependency:
- The
directDependencyStrategyattribute should be removed/not applied - Resolution follows normal transitive dependency rules using the active conflict resolver
- Consumer POM controls conflict resolution via their own direct dependency strategies
Safeguards
- Build Validation: Maven warns if unexpected downgrades occur during resolution when using
flexiblestrategy - Reactor Awareness: In-development versions in reactor builds always take precedence over deployed versions
- Explicit Override: Individual dependencies can override project-level strategy setting
Benefits
- Less Configuration: Developers need fewer
<dependencyManagement>entries - Explicit Intent: Clear declaration of whether a version is fixed or flexible
- Gradual Adoption: Backward compatible; defaults preserve current behavior
- Flexibility: Works with any conflict resolver implementation (highest, nearest, etc.)
- Platform Compatibility: Works alongside platform/BOM-based dependency management
Implementation Notes
- Extends
ConfigurableVersionSelectorto check strategy configuration before applying fixed direct dependency preference - Requires POM model updates to support
directDependencyStrategyattribute - Consumer POM transformations should strip
directDependencyStrategyattributes during publishing - Strategy resolution follows hierarchy: dependency-level > project-level > Maven property > hardcoded default