Skip to content

Configurable Dependency Version Resolution Strategy #11391

@gnodet

Description

@gnodet

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):

  1. Maven Configuration: maven.resolver.directDependencyStrategy property

    <properties>
      <maven.resolver.directDependencyStrategy>flexible</maven.resolver.directDependencyStrategy>
    </properties>
  2. Project Level: <project directDependencyStrategy="..."> in POM

  3. Dependency Level: <directDependencyStrategy> within individual <dependency> block

Consumer Behavior

When a direct dependency with non-default strategy is consumed as a transitive dependency:

  • The directDependencyStrategy attribute 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 flexible strategy
  • 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 ConfigurableVersionSelector to check strategy configuration before applying fixed direct dependency preference
  • Requires POM model updates to support directDependencyStrategy attribute
  • Consumer POM transformations should strip directDependencyStrategy attributes during publishing
  • Strategy resolution follows hierarchy: dependency-level > project-level > Maven property > hardcoded default

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions