MNG-8099: Add explicit 'api' scope for dependencies and make 'compile' non-transitive for Maven 4 - #12745
MNG-8099: Add explicit 'api' scope for dependencies and make 'compile' non-transitive for Maven 4#12745Hiteshsai007 wants to merge 1 commit into
Conversation
…' non-transitive for Maven 4
gnodet
left a comment
There was a problem hiding this comment.
Thanks for working on MNG-8099, @Hiteshsai007! The api/compile scope split concept is well-motivated (mirroring Gradle's api/implementation distinction). A few issues need to be addressed:
🔴 Critical: Consumer POM regression — compile-scoped dependencies silently stripped
DefaultConsumerPomBuilder.hasDependencyScope() uses !scope.isTransitive() to decide which dependencies to remove from consumer POMs. With COMPILE changing from transitive=true to transitive=false, all compile-scoped dependencies — and dependencies with no explicit scope (the most common case, which defaults to COMPILE) — will be stripped from consumer POMs.
This breaks downstream dependency resolution for essentially every Maven 4 project. The method is not gated on model version, so even modelVersion=4.0.0 projects are affected. The PR's backward compatibility claim ("Maven 3 / modelVersion 4.0.0: No change") is incorrect for this code path.
This is the same regression identified in our review of PR #12723. The fix requires hasDependencyScope() to use a different criterion than isTransitive() — e.g., checking whether the scope should appear in consumer POMs (compile, api, runtime) directly.
🔴 Critical: Resolver treats compile as non-transitive
Both Maven4ScopeManagerConfiguration files pass DependencyScope.COMPILE.isTransitive() to createDependencyScope(). After this change, the resolver will treat compile as non-transitive in Maven 4, meaning transitive dependencies of compile-scoped libraries won't be resolved — a massive behavioral change with no migration path.
🔴 Accidental files committed
Two files are included in the diff that shouldn't be:
issue_comment.md— a binary (UTF-16) file containing a GitHub issue comment about PR #12744plexus-sec-dispatcher— a git submodule reference (160000mode) pointing to commita3b5741
Both must be removed before merging.
🔴 No tests provided
The PR checklist marks "Write unit tests" as complete, but zero test files are modified or added. A change of this magnitude to Maven's dependency scope system needs comprehensive test coverage for:
- Consumer POM generation with compile vs api-scoped dependencies
- Transitive resolution behavior for both scopes
- Model validation of api scope in 4.0.0 vs 4.1.0 POMs
- Backward compatibility with Maven 3
🟡 MavenModelVersion does not detect api scope
The auto-generated MavenModelVersion class does not check for api-scoped dependencies. Since API.isTransitive()=true, api-scoped deps survive hasDependencyScope() filtering, but the consumer POM could be written with modelVersion=4.0.0 — creating an inconsistency where a 4.0.0 POM contains a scope only valid in 4.1.0+.
Recommendations:
- Update
hasDependencyScope()to not rely onisTransitive()for determining consumer POM inclusion - Gate the compile→non-transitive behavior on model version (as MNG-8099 description states: "only with the new modelVersion to opt into")
- Remove the accidental files
- Add comprehensive tests
- Address MavenModelVersion detection of the api scope
The direction is right — the implementation just needs more work to handle the cross-cutting impacts. Happy to re-review once updated!
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of gnodet
|
I question the idea that only API dependencies should be transitive and not the dependencies with the Or maybe you mean In other words, keep a separation of tasks: Maven controls what to put on the module-path, and |
Resolves #10786 (MNG-8099)
Summary
This PR introduces a new transitive
apidependency scope for Maven 4 and makes the existingcompilescope non-transitive. This aligns Maven's dependency model with modern build tools like Gradle, which distinguish between API (publicly exposed) and implementation (internal) dependencies.Problem
Currently in Maven, the
compilescope is transitive — meaning if library A depends on library B withcompilescope, any project depending on A will also see B on its compile classpath. This leads to "leaky" dependency graphs where implementation details are exposed to consumers, causing:Solution
1. New
apiScope (DependencyScope.java)API("api", true)— a transitive scope for dependencies that form part of the public APICOMPILE("compile", false)from transitive to non-transitive — for implementation-only dependencies2. Scope Manager Configuration (
Maven4ScopeManagerConfiguration.java)apidependency scope in both:impl/maven-impl/.../Maven4ScopeManagerConfiguration.javacompat/maven-resolver-provider/.../Maven4ScopeManagerConfiguration.javaapiscope is configured withall()build paths (compile + runtime), matchingcompile's path visibility3. Path Scope Updates (
PathScope.java)DependencyScope.APIto all four standard path scopes:MAIN_COMPILE— api dependencies appear on the compile classpathMAIN_RUNTIME— api dependencies appear on the runtime classpathTEST_COMPILE— api dependencies appear on the test compile classpathTEST_RUNTIME— api dependencies appear on the test runtime classpath4. Model Validation (
DefaultModelValidator.java)DependencyScope.APIto the list of Maven 4-only scopes that are rejected when used withmodelVersion4.0.0 (legacy POMs)apiscope is only valid for Maven 4.1.0+ model versionsUsage (Maven 4)
Backward Compatibility
compilescope continues to behave as before (transitive) throughMaven3ScopeManagerConfiguration, and theapiscope is rejected by validation.apifor dependencies they want to expose transitively.Following this checklist to help us incorporate your contribution quickly and easily:
Checklist
mvn verifyto make sure basic checks pass.To make clear that you license your contribution under the Apache License Version 2.0, January 2004, you have to acknowledge this by using the following checkbox.