openrewrite / openrewrite/rewrite
Support classifiers on BOMs imported into `<dependencyManagement>` (Maven 4)
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3.7k
- Forks
- 570
- Avg merge
- 13h 12m
- Merged PRs (30d)
- 261
Description
Problem
Maven 4 permits a <classifier> on a BOM imported into <dependencyManagement>, and the Maven team actively recommends that project BOMs be published as classified artifacts (via the bom-builder3 plugin's <bomClassifier>) so that a BOM is a separate artifact from the project's own POM:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0</version>
<classifier>bom</classifier>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
rewrite-maven silently ignores the classifier. The import resolves example-1.0.0.pom instead of example-1.0.0-bom.pom, so the wrong managed versions are contributed — or, when the project publishes no main POM worth importing, none are, and every dependency that relied on the BOM fails to resolve with an error that never mentions the BOM.
Current behavior
<classifier> on an imported BOM is dropped at parse time and never reaches the downloader.
Root cause
The classifier has nowhere to live and no way to be requested:
ManagedDependency.Importedholds only aGroupArtifactVersion— there is noclassifierfield, unlikeManagedDependency.Defined.RawPom.mapDependencyManagement(~line 560) andUpdateMavenModel(~line 111) both constructnew ManagedDependency.Imported(gav), discardingd.getClassifier().ResolvedPom.mergeDependencyManagement(~line 936) callsdownloader.download(groupArtifactVersion, null, ...).MavenPomDownloaderbuilds the POM URI as<artifactId>-<version>.pom(~line 594, and<artifactId>-<version>.pomagain for maven-local at ~line 1298). There is no classifier slot in either path.
Maven's own validation confirms this is version-gated behavior rather than something that was always allowed — DefaultModelValidator.validate20RawDependencies reports "must be empty, imported POM cannot have a classifier." only below model 4.1.0:
} else if (!is41OrBeyond
&& dependency.getClassifier() != null
&& !dependency.getClassifier().isEmpty()) {
addViolation(problems, errOn30, Version.V20, prefix + prefix2 + "classifier", ...
"must be empty, imported POM cannot have a classifier.", dependency);
}
Desired behavior
A classifier on an imported BOM is preserved through parsing and used when downloading the BOM POM, so <classifier>bom</classifier> resolves example-1.0.0-bom.pom. Unclassified imports must keep working unchanged.
This touches the LST model (ManagedDependency.Imported), so it needs care around serialization compatibility.
Secondary: diagnose non-importing <dependencyManagement> entries
When a <dependencyManagement> entry looks like a BOM import but is not one, the failure surfaces as a MavenDownloadingException pointing at an unrelated downstream artifact:
No version provided for direct dependency org.junit.jupiter:junit-jupiter-api
Maven instead reports the cause directly, at the offending element (DefaultModelValidator, ~line 1176):
[WARNING] 'dependencyManagement.dependencies.dependency.type' for groupId='com.example',
artifactId='example', type='bom' must be 'pom' to import the managed dependencies. @ line 5, column 98
Mirroring that — a warning when a managed dependency carries <scope>import</scope> with a non-pom type, or a bom type that will not be imported — would make this class of failure diagnosable from a build log.
Not a bug: <type>bom</type> is not an import
This issue originally asked for <type>bom</type> in <dependencyManagement> to be treated as an import. That is not Maven 4 behavior, and rewrite-maven's current handling is correct.
DefaultModelBuilder.importDependencyManagement, identical on master, maven-4.0.x, and tag maven-4.0.0-rc-5:
if (!("pom".equals(dependency.getType()) && "import".equals(dependency.getScope()))
|| "bom".equals(dependency.getType())) {
continue;
}
The || "bom".equals(...) clause is dead code — when the type is bom the first clause has already forced the continue. The condition is exactly Maven 3's. It arrived as a drive-by in c6380108b1 ([MNG-7877], a consumer-POM commit) with no test and no IT, and there is not a single <type>bom</type> anywhere in apache/maven's sources, ITs, or test resources; every BOM IT uses <type>pom</type><scope>import</scope>. Pairing <type>bom</type> with <scope>import</scope> produces the "must be 'pom' to import the managed dependencies" warning quoted above.
Verified by running Maven 4.0.0-rc-5: a pom declaring a BOM with <type>bom</type> fails with 'dependencies.dependency.version' for ... is missing, whether the model version is 4.0.0 or 4.1.0. Implementing the original request would make rewrite resolve POMs that Maven itself cannot build.
bom in Maven 4 is two other things, neither of which is a consumer-side import mechanism:
<packaging>bom</packaging>on the producing project — a build-POM-only packaging whose lifecycle bindsinstall/deployonly, and whose published consumer POM is rewritten to<packaging>pom</packaging>(apache/maven#11427) so Maven 3 can still import it. It produces no artifact other than POMs.- A registered artifact type whose extension is
.pom(DefaultTypeProvider:new DefaultType(Type.BOM, Language.NONE, "pom", null, false)). In a plain<dependencies>block it resolves the.pomand contributes nothing to the classpath and no managed versions.
Related
- #6869 — Maven 4 versionless parent references
- Maven 4 BOM packaging (describes the packaging, not a
<type>bom</type>import) - MNG-7879 — add a new BOM packaging
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with ManagedDependency.Imported, then trace classifier handling through RawPom.mapDependencyManagement, UpdateMavenModel, ResolvedPom.mergeDependencyManagement, and both MavenPomDownloader URI paths identified in the issue. Check serialization compatibility while preserving unclassified imports. Done means classified BOM imports request the classified POM, unclassified imports remain unchanged, and the non-importing dependency-management case is diagnosable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100