Description
Maven 4's default TransitiveDependencyManager (enabled when maven3Personality=false) changes dependency mediation behavior compared to Maven 3's ClassicDependencyManager. This causes enforcer rule violations due to managed version application to transitive dependencies.
### 1. Scope derivation excludes transitive compile deps through provided parents
Update: The projects originally reported under this category (hadoop-api-shim, flink-connector-hive) are not affected by scope derivation changes. Both projects fail because their hadoop-project parent POM (versions 3.1.0 and 3.2.0) contains invalid XML (<Xlint:-unchecked/> — the - after the colon is not a valid XML name start character). Maven 3 silently parses this in lenient mode, while Maven 4 correctly rejects it, causing all transitive dependencies from those POMs to be unavailable. This is a project-side issue, not a Maven 4 regression.
2. Managed version application to transitive dependencies
TransitiveDependencyManager applies <dependencyManagement> versions at ALL depths during collection, not just to direct dependencies. This can downgrade transitive dependency versions, triggering RequireUpperBoundDeps and BannedDependencies enforcer rule violations that pass with Maven 3.
Affected projects: guacamole-client, logging-log4j-samples, netbeans-html4j
Example (guacamole-client):
Require upper bound dependencies error for com.google.code.findbugs:jsr305:3.0.1
+-guacamole-auth-header:1.6.1
+-guice:5.1.0
+-guava:32.1.3-jre (managed) <-- guava:30.1-jre
+-jsr305:3.0.1 (managed) <-- jsr305:3.0.2
Note the (managed) annotations — Maven 4 is applying the parent's dependencyManagement to transitive deps, downgrading jsr305 from 3.0.2 to 3.0.1.
Root cause
TransitiveDependencyManager.manageDependency() applies managed versions/scopes at depth ≥ 2 during collection. Maven 3's ClassicDependencyManager did not do this — version management and scope derivation were handled post-collection in the graph transformer.
Key code difference:
|
ClassicDependencyManager |
TransitiveDependencyManager |
deriveUntil |
2 (root depMgmt only) |
Integer.MAX_VALUE (all POMs) |
| Version management sources |
Root <dependencyManagement> only |
Every POM in the graph |
Workaround
-Dmaven.maven3Personality=true reverts to ClassicDependencyManager behavior.
Suggested fix
Apply TransitiveDependencyManager's full-depth collection only for Maven 4 POMs, or only apply collected managed versions when no version has already been established by a higher-priority (nearer-to-root) source.
Reproducers
# Enforcer mediation issue
git clone https://github.com/apache/guacamole-client.git && cd guacamole-client
mvn -B -e clean package -DskipTests
Context
Found during Maven 4 compatibility testing of Apache projects.
Description
Maven 4's default
TransitiveDependencyManager(enabled whenmaven3Personality=false) changes dependency mediation behavior compared to Maven 3'sClassicDependencyManager. This causes enforcer rule violations due to managed version application to transitive dependencies.### 1. Scope derivation excludes transitive compile deps through provided parentsUpdate: The projects originally reported under this category (
hadoop-api-shim,flink-connector-hive) are not affected by scope derivation changes. Both projects fail because theirhadoop-projectparent POM (versions 3.1.0 and 3.2.0) contains invalid XML (<Xlint:-unchecked/>— the-after the colon is not a valid XML name start character). Maven 3 silently parses this in lenient mode, while Maven 4 correctly rejects it, causing all transitive dependencies from those POMs to be unavailable. This is a project-side issue, not a Maven 4 regression.2.Managed version application to transitive dependenciesTransitiveDependencyManagerapplies<dependencyManagement>versions at ALL depths during collection, not just to direct dependencies. This can downgrade transitive dependency versions, triggeringRequireUpperBoundDepsandBannedDependenciesenforcer rule violations that pass with Maven 3.Affected projects:
guacamole-client,logging-log4j-samples,netbeans-html4jExample (guacamole-client):
Note the
(managed)annotations — Maven 4 is applying the parent'sdependencyManagementto transitive deps, downgrading jsr305 from 3.0.2 to 3.0.1.Root cause
TransitiveDependencyManager.manageDependency()applies managed versions/scopes at depth ≥ 2 during collection. Maven 3'sClassicDependencyManagerdid not do this — version management and scope derivation were handled post-collection in the graph transformer.Key code difference:
ClassicDependencyManagerTransitiveDependencyManagerderiveUntil2(root depMgmt only)Integer.MAX_VALUE(all POMs)<dependencyManagement>onlyWorkaround
-Dmaven.maven3Personality=truereverts toClassicDependencyManagerbehavior.Suggested fix
Apply
TransitiveDependencyManager's full-depth collection only for Maven 4 POMs, or only apply collected managed versions when no version has already been established by a higher-priority (nearer-to-root) source.Reproducers
Context
Found during Maven 4 compatibility testing of Apache projects.