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>