You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/09/01 15:08:15 UTC
(maven) branch master updated: [MNG-8450] Report BOM import warnings only at declaration sites (#12959)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push:
new 625d69d92a [MNG-8450] Report BOM import warnings only at declaration sites (#12959)
625d69d92a is described below
commit 625d69d92aa45ce12d7055d840c66b9616f7bf82
Author: Goutam Adwant <86...@users.noreply.github.com>
AuthorDate: Tue Sep 1 08:08:09 2026 -0700
[MNG-8450] Report BOM import warnings only at declaration sites (#12959)
* [MNG-8450] Report BOM import warnings only at declaration sites
Signed-off-by: goutamadwant <wo...@gmail.com>
* [MNG-8450] Handle import warnings without source locations
Signed-off-by: goutamadwant <wo...@gmail.com>
* [MNG-8450] Address review feedback: polish deduplication code
- Import java.util.stream.Collectors instead of using fully-qualified references
- Add Javadoc on ImportWarningKey record explaining its deduplication role
- Document dual-key rationale in registerReactorProblemCollector
- Extract anonymous ModelProblemCollector to named DeduplicatingImportProblemCollector inner class
Signed-off-by: Guillaume Nodet <gn...@gmail.com>
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---------
Signed-off-by: goutamadwant <wo...@gmail.com>
Signed-off-by: Guillaume Nodet <gn...@gmail.com>
Co-authored-by: Guillaume Nodet <gn...@gmail.com>
Co-authored-by: Claude Opus 4.6 <no...@anthropic.com>
---
.../model/DefaultDependencyManagementImporter.java | 3 +-
.../maven/impl/model/DefaultModelBuilder.java | 146 ++++++++++++++++++++-
.../maven/impl/model/DefaultModelBuilderTest.java | 98 ++++++++++++++
.../mng-8450-profile-context/bom-one/pom.xml | 17 +++
.../mng-8450-profile-context/bom-two/pom.xml | 17 +++
.../factory/mng-8450-profile-context/child/pom.xml | 11 ++
.../mng-8450-profile-context/parent/pom.xml | 34 +++++
.../poms/factory/mng-8450-profile-context/pom.xml | 14 ++
.../poms/factory/mng-8450-standalone/child/pom.xml | 11 ++
.../factory/mng-8450-standalone/parent/pom.xml | 26 ++++
.../1.0.0/standalone-bom-one-1.0.0.pom | 17 +++
.../1.0.0/standalone-bom-two-1.0.0.pom | 17 +++
.../poms/factory/mng-8450/bom-one/pom.xml | 17 +++
.../poms/factory/mng-8450/bom-two/pom.xml | 17 +++
.../poms/factory/mng-8450/child-one/pom.xml | 10 ++
.../poms/factory/mng-8450/child-two/pom.xml | 10 ++
.../poms/factory/mng-8450/independent/pom.xml | 26 ++++
.../test/resources/poms/factory/mng-8450/pom.xml | 41 ++++++
18 files changed, 528 insertions(+), 4 deletions(-)
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java
index 05b4190388..73c706f1f3 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultDependencyManagementImporter.java
@@ -81,7 +81,8 @@ public Model importManagement(
Version.V40,
"Ignored POM import for: " + toString(dependency) + " as already imported "
+ toString(present) + ". Add the conflicting managed dependency directly "
- + "to the dependencyManagement section of the POM.");
+ + "to the dependencyManagement section of the POM.",
+ source.getImportedFrom());
}
if (present != null
&& directDependencies.contains(key)
diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java
index 118e098d9c..988e2956bb 100644
--- a/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java
+++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/model/DefaultModelBuilder.java
@@ -234,7 +234,7 @@ public ModelBuilderResult build(ModelBuilderRequest request) throws ModelBuilder
mainSession = new ModelBuilderSessionState(request);
session = mainSession;
} else {
- session = mainSession.derive(
+ session = mainSession.deriveTopLevel(
request,
new DefaultModelBuilderResult(request, ProblemCollector.create(mainSession.session)));
}
@@ -269,6 +269,8 @@ protected class ModelBuilderSessionState implements ModelProblemCollector {
final DefaultModelBuilderResult result;
final Graph dag;
final Map<GAKey, Set<ModelSource>> mappedSources;
+ final Set<ImportWarningKey> reportedImportWarnings;
+ final Map<String, ProblemCollector<ModelProblem>> reactorProblemCollectors;
String source;
Model sourceModel;
@@ -297,6 +299,8 @@ List<RemoteRepository> getExternalRepositories() {
new DefaultModelBuilderResult(request, ProblemCollector.create(request.getSession())),
new Graph(),
new ConcurrentHashMap<>(64),
+ ConcurrentHashMap.newKeySet(),
+ new ConcurrentHashMap<>(),
List.of(),
repos(request),
repos(request),
@@ -373,6 +377,8 @@ private ModelBuilderSessionState(
DefaultModelBuilderResult result,
Graph dag,
Map<GAKey, Set<ModelSource>> mappedSources,
+ Set<ImportWarningKey> reportedImportWarnings,
+ Map<String, ProblemCollector<ModelProblem>> reactorProblemCollectors,
List<RemoteRepository> pomRepositories,
List<RemoteRepository> externalRepositories,
List<RemoteRepository> repositories,
@@ -382,6 +388,8 @@ private ModelBuilderSessionState(
this.result = result;
this.dag = dag;
this.mappedSources = mappedSources;
+ this.reportedImportWarnings = reportedImportWarnings;
+ this.reactorProblemCollectors = reactorProblemCollectors;
this.pomRepositories = pomRepositories;
this.externalRepositories = externalRepositories;
this.repositories = repositories;
@@ -405,6 +413,18 @@ ModelBuilderSessionState derive(ModelBuilderRequest request) {
}
ModelBuilderSessionState derive(ModelBuilderRequest request, DefaultModelBuilderResult result) {
+ return derive(request, result, reportedImportWarnings, reactorProblemCollectors);
+ }
+
+ ModelBuilderSessionState deriveTopLevel(ModelBuilderRequest request, DefaultModelBuilderResult result) {
+ return derive(request, result, ConcurrentHashMap.newKeySet(), new ConcurrentHashMap<>());
+ }
+
+ private ModelBuilderSessionState derive(
+ ModelBuilderRequest request,
+ DefaultModelBuilderResult result,
+ Set<ImportWarningKey> reportedImportWarnings,
+ Map<String, ProblemCollector<ModelProblem>> reactorProblemCollectors) {
if (session != request.getSession()) {
throw new IllegalArgumentException("Session mismatch");
}
@@ -433,6 +453,8 @@ ModelBuilderSessionState derive(ModelBuilderRequest request, DefaultModelBuilder
result,
dag,
mappedSources,
+ reportedImportWarnings,
+ reactorProblemCollectors,
pomRepositories,
derivedExtRepos,
derivedRepos,
@@ -986,6 +1008,8 @@ private void loadFromRoot(Path root, Path top) {
top,
root);
mappedSources.clear();
+ reportedImportWarnings.clear();
+ reactorProblemCollectors.clear();
loadFromRoot(top, top);
}
}
@@ -998,6 +1022,7 @@ private void loadFilePom(
Model model = derive(src, r).readFileModel();
// keep all loaded file models in memory, those will be needed
// during the raw to build transformation
+ registerReactorProblemCollector(src, r.getProblemCollector());
putSource(getGroupId(model), model.getArtifactId(), src);
Model activated = activateFileModel(model);
for (String subproject : getSubprojects(activated)) {
@@ -2178,7 +2203,112 @@ private Model importDependencyManagement(Model model, Collection<String> importI
model = model.withDependencyManagement(
model.getDependencyManagement().withDependencies(deps));
- return dependencyManagementImporter.importManagement(model, importMgmts, request, this);
+ return dependencyManagementImporter.importManagement(
+ model, importMgmts, request, deduplicatingImportProblemCollector());
+ }
+
+ private ModelProblemCollector deduplicatingImportProblemCollector() {
+ return new DeduplicatingImportProblemCollector();
+ }
+
+ /**
+ * A {@link ModelProblemCollector} wrapper that deduplicates BOM import conflict warnings
+ * within a single top-level build. When a warning originates from a reactor module,
+ * it is routed to that module's own problem collector so the warning appears next to the
+ * declaration rather than being repeated for every inheriting child. Non-warning problems
+ * and warnings without a resolvable source are forwarded to the enclosing
+ * {@link ModelBuilderSessionState} unchanged.
+ */
+ private class DeduplicatingImportProblemCollector implements ModelProblemCollector {
+ @Override
+ public ProblemCollector<ModelProblem> getProblemCollector() {
+ return ModelBuilderSessionState.this.getProblemCollector();
+ }
+
+ @Override
+ public void add(
+ BuilderProblem.Severity severity,
+ ModelProblem.Version version,
+ String message,
+ InputLocation location,
+ Exception exception) {
+ if (severity == Severity.WARNING && location != null && location.getSource() != null) {
+ var source = location.getSource();
+ String sourceLocation = source.getLocation();
+ ImportWarningKey key = new ImportWarningKey(
+ message,
+ sourceLocation,
+ source.getModelId(),
+ location.getLineNumber(),
+ location.getColumnNumber());
+ if (!reportedImportWarnings.add(key)) {
+ return;
+ }
+ ProblemCollector<ModelProblem> collector =
+ sourceLocation != null ? reactorProblemCollectors.get(sourceLocation) : null;
+ if (collector != null) {
+ collector.reportProblem(new DefaultModelProblem(
+ message,
+ severity,
+ version,
+ sourceLocation,
+ location.getLineNumber(),
+ location.getColumnNumber(),
+ source.getModelId(),
+ exception));
+ return;
+ }
+ }
+ ModelBuilderSessionState.this.add(severity, version, message, location, exception);
+ }
+
+ @Override
+ public ModelBuilderException newModelBuilderException() {
+ return ModelBuilderSessionState.this.newModelBuilderException();
+ }
+
+ @Override
+ public void setSource(String location) {
+ ModelBuilderSessionState.this.setSource(location);
+ }
+
+ @Override
+ public void setSource(Model model) {
+ ModelBuilderSessionState.this.setSource(model);
+ }
+
+ @Override
+ public String getSource() {
+ return ModelBuilderSessionState.this.getSource();
+ }
+
+ @Override
+ public void setRootModel(Model model) {
+ ModelBuilderSessionState.this.setRootModel(model);
+ }
+
+ @Override
+ public Model getRootModel() {
+ return ModelBuilderSessionState.this.getRootModel();
+ }
+ }
+
+ /**
+ * Registers the problem collector under both the location string (path form) and
+ * the URI form of the source. Import warnings produced by
+ * {@link DefaultDependencyManagementImporter} carry whichever form the resolver
+ * happened to record, so both keys are registered as a safety net to ensure a
+ * lookup in {@link DeduplicatingImportProblemCollector#add} always finds the
+ * declaring model's collector.
+ */
+ private void registerReactorProblemCollector(
+ ModelSource source, ProblemCollector<ModelProblem> problemCollector) {
+ if (source.getLocation() != null) {
+ reactorProblemCollectors.put(source.getLocation(), problemCollector);
+ }
+ if (source.getPath() != null) {
+ reactorProblemCollectors.put(source.getPath().toUri().toString(), problemCollector);
+ }
}
private DependencyManagement loadDependencyManagement(Dependency dependency, Collection<String> importIds) {
@@ -2251,7 +2381,9 @@ private DependencyManagement loadDependencyManagement(Dependency dependency, Col
importMgmt = importMgmt.withDependencies(dependencies);
}
- return importMgmt;
+ return DependencyManagement.newBuilder(importMgmt, true)
+ .importedFrom(dependency.getLocation(""))
+ .build();
}
@SuppressWarnings("checkstyle:parameternumber")
@@ -2570,6 +2702,14 @@ private boolean containsCoordinates(String message, String groupId, String artif
record GAKey(String groupId, String artifactId) {}
+ /**
+ * Composite key used to deduplicate BOM import conflict warnings within a single top-level build.
+ * Two warnings are considered duplicates when they share the same message text and originate
+ * from the same source location (file, model ID, line, and column).
+ */
+ private record ImportWarningKey(
+ String message, String sourceLocation, String sourceModelId, int lineNumber, int columnNumber) {}
+
public record RgavCacheKey(
Session session,
RequestTrace trace,
diff --git a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
index f865beec06..e88cb09ca5 100644
--- a/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
+++ b/impl/maven-impl/src/test/java/org/apache/maven/impl/model/DefaultModelBuilderTest.java
@@ -36,6 +36,8 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.apache.maven.api.Constants;
import org.apache.maven.api.RemoteRepository;
@@ -50,6 +52,7 @@
import org.apache.maven.api.services.ModelBuilder;
import org.apache.maven.api.services.ModelBuilderRequest;
import org.apache.maven.api.services.ModelBuilderResult;
+import org.apache.maven.api.services.ModelProblem;
import org.apache.maven.api.services.ModelSource;
import org.apache.maven.api.services.Sources;
import org.apache.maven.impl.DefaultRemoteRepository;
@@ -967,6 +970,101 @@ public void testBomTypeImpliesImportWithoutScope() {
assertEquals("0.1", managed.getVersion());
}
+ @Test
+ void testBomImportWarningsReportedWhereImportsAreDeclared() {
+ Path pom = Paths.get("src/test/resources/poms/factory/mng-8450/pom.xml").toAbsolutePath();
+ for (String parallelism : List.of("1", "4")) {
+ ModelBuilderResult result = builder.newSession()
+ .build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .recursive(true)
+ .userProperties(
+ Map.of(Constants.MAVEN_MODEL_BUILDER_PARALLELISM, parallelism, "revision", "1.0.0"))
+ .source(Sources.buildSource(pom))
+ .build());
+
+ List<ModelProblem> warnings = bomImportWarnings(result);
+
+ assertEquals(2, warnings.size(), warnings.toString());
+ assertEquals(
+ Set.of(
+ "org.apache.maven.test:mng-8450-parent:${revision}",
+ "org.apache.maven.test:independent:1.0.0"),
+ warnings.stream().map(ModelProblem::getModelId).collect(Collectors.toSet()));
+ assertEquals(
+ Map.of("mng-8450-parent", 1L, "independent", 1L),
+ results(result)
+ .filter(r -> directBomImportWarningCount(r) > 0)
+ .collect(Collectors.toMap(
+ r -> r.getEffectiveModel().getArtifactId(), this::directBomImportWarningCount)));
+ }
+ }
+
+ @Test
+ void testBomImportWarningFromNonReactorParentIsPreserved() {
+ Path basedir = Paths.get(System.getProperty("basedir", ""));
+ Path fixture = basedir.resolve("src/test/resources/poms/factory/mng-8450-standalone");
+ Session standaloneSession = ApiRunner.createSession(
+ injector -> injector.bindInstance(DefaultModelBuilderTest.class, this),
+ basedir.resolve("target/local-repo-mng-8450"));
+ standaloneSession = standaloneSession.withRemoteRepositories(List.of(standaloneSession.createRemoteRepository(
+ RemoteRepository.CENTRAL_ID, fixture.resolve("repo").toUri().toString())));
+
+ var modelBuilderSession =
+ standaloneSession.getService(ModelBuilder.class).newSession();
+ ModelBuilderRequest request = ModelBuilderRequest.builder()
+ .session(standaloneSession)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .source(Sources.buildSource(fixture.resolve("child/pom.xml")))
+ .build();
+
+ for (int build = 0; build < 2; build++) {
+ ModelBuilderResult result = modelBuilderSession.build(request);
+ List<ModelProblem> warnings = bomImportWarnings(result);
+ assertEquals(1, warnings.size(), warnings.toString());
+ assertEquals(
+ "org.apache.maven.test:standalone-parent:1.0.0",
+ warnings.get(0).getModelId());
+ }
+ }
+
+ @Test
+ void testBomImportWarningFromParentProfileActivatedForChild() {
+ Path pom = Paths.get("src/test/resources/poms/factory/mng-8450-profile-context/pom.xml")
+ .toAbsolutePath();
+ ModelBuilderResult result = builder.newSession()
+ .build(ModelBuilderRequest.builder()
+ .session(session)
+ .requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
+ .recursive(true)
+ .source(Sources.buildSource(pom))
+ .build());
+
+ List<ModelProblem> warnings = bomImportWarnings(result);
+ assertEquals(1, warnings.size(), warnings.toString());
+ assertEquals(
+ "org.apache.maven.test:profile-parent:1.0.0", warnings.get(0).getModelId());
+ }
+
+ private List<ModelProblem> bomImportWarnings(ModelBuilderResult result) {
+ return results(result)
+ .flatMap(r -> r.getProblemCollector().problems())
+ .filter(p -> p.getMessage().startsWith("Ignored POM import for:"))
+ .toList();
+ }
+
+ private long directBomImportWarningCount(ModelBuilderResult result) {
+ return result.getProblemCollector()
+ .problems()
+ .filter(p -> p.getMessage().startsWith("Ignored POM import for:"))
+ .count();
+ }
+
+ private Stream<ModelBuilderResult> results(ModelBuilderResult result) {
+ return Stream.concat(Stream.of(result), result.getChildren().stream().flatMap(this::results));
+ }
+
private static DefaultProfileActivationContext.Record recordActiveProfile(
List<String> activeIds, String profileId) {
DefaultProfileActivationContext recording =
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-one/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-one/pom.xml
new file mode 100644
index 0000000000..5354e87b6f
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-one/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-bom-one</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-two/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-two/pom.xml
new file mode 100644
index 0000000000..5a8180c289
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/bom-two/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-bom-two</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/child/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/child/pom.xml
new file mode 100644
index 0000000000..24639da423
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/child/pom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-parent</artifactId>
+ <version>1.0.0</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+ <artifactId>profile-child</artifactId>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/parent/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/parent/pom.xml
new file mode 100644
index 0000000000..c347942410
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/parent/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.1.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-parent</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <profiles>
+ <profile>
+ <id>child-imports</id>
+ <activation>
+ <packaging>jar</packaging>
+ </activation>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-bom-one</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>profile-bom-two</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ </profile>
+ </profiles>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/pom.xml
new file mode 100644
index 0000000000..8dd4c5f862
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-profile-context/pom.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>mng-8450-profile-context</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <modules>
+ <module>bom-one</module>
+ <module>bom-two</module>
+ <module>parent</module>
+ <module>child</module>
+ </modules>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/child/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/child/pom.xml
new file mode 100644
index 0000000000..c0e2b8b3b2
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/child/pom.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-parent</artifactId>
+ <version>1.0.0</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+ <artifactId>standalone-child</artifactId>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/parent/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/parent/pom.xml
new file mode 100644
index 0000000000..6927dfeb04
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/parent/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-parent</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-bom-one</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-bom-two</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-one/1.0.0/standalone-bom-one-1.0.0.pom b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-one/1.0.0/standalone-bom-one-1.0.0.pom
new file mode 100644
index 0000000000..d128096222
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-one/1.0.0/standalone-bom-one-1.0.0.pom
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-bom-one</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-two/1.0.0/standalone-bom-two-1.0.0.pom b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-two/1.0.0/standalone-bom-two-1.0.0.pom
new file mode 100644
index 0000000000..c76d10c1bf
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450-standalone/repo/org/apache/maven/test/standalone-bom-two/1.0.0/standalone-bom-two-1.0.0.pom
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>standalone-bom-two</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-one/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-one/pom.xml
new file mode 100644
index 0000000000..c34ea0f6af
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-one/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-one</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-two/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-two/pom.xml
new file mode 100644
index 0000000000..d6820616c5
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/bom-two/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-two</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>managed</artifactId>
+ <version>2.0.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-one/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-one/pom.xml
new file mode 100644
index 0000000000..573bd3250b
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-one/pom.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>mng-8450-parent</artifactId>
+ <version>${revision}</version>
+ </parent>
+ <artifactId>child-one</artifactId>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-two/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-two/pom.xml
new file mode 100644
index 0000000000..049ab51a14
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/child-two/pom.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>mng-8450-parent</artifactId>
+ <version>${revision}</version>
+ </parent>
+ <artifactId>child-two</artifactId>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/independent/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/independent/pom.xml
new file mode 100644
index 0000000000..744fc45402
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/independent/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>independent</artifactId>
+ <version>1.0.0</version>
+ <packaging>pom</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-one</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-two</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/impl/maven-impl/src/test/resources/poms/factory/mng-8450/pom.xml b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/pom.xml
new file mode 100644
index 0000000000..63068ab547
--- /dev/null
+++ b/impl/maven-impl/src/test/resources/poms/factory/mng-8450/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>mng-8450-parent</artifactId>
+ <version>${revision}</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <revision>1.0.0</revision>
+ </properties>
+
+ <modules>
+ <module>bom-one</module>
+ <module>bom-two</module>
+ <module>child-one</module>
+ <module>child-two</module>
+ <module>independent</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-one</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.test</groupId>
+ <artifactId>bom-two</artifactId>
+ <version>1.0.0</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>