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 aa282d272353..78f43c6eed20 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 @@ -1423,7 +1423,14 @@ private Model readEffectiveModel() throws ModelBuilderException { // Mixins for (Mixin mixin : model.getMixins()) { Model parent = resolveParent(model, mixin, profileActivationContext, parentChain); + // Merge mixin into model model = inheritanceAssembler.assembleModelInheritance(model, parent, request, this); + // Ensure mixin properties override any previously inherited properties + // This is necessary because normal inheritance gives child precedence, but for mixins + // we want the mixin to take precedence over inherited parent properties + Map mergedProperties = new java.util.HashMap<>(model.getProperties()); + mergedProperties.putAll(parent.getProperties()); + model = model.withProperties(mergedProperties); } // model normalization @@ -1901,7 +1908,12 @@ protected void mergeModel_Subprojects( Model parent = defaultInheritanceAssembler.assembleModelInheritance(raw, parentData, request, this); for (Mixin mixin : parent.getMixins()) { Model parentModel = resolveParent(parent, mixin, childProfileActivationContext, parentChain); + // Merge mixin into parent parent = defaultInheritanceAssembler.assembleModelInheritance(parent, parentModel, request, this); + // Ensure mixin properties override any previously inherited properties + Map mergedProperties = new java.util.HashMap<>(parent.getProperties()); + mergedProperties.putAll(parentModel.getProperties()); + parent = parent.withProperties(mergedProperties); } // Profile injection SHOULD be performed on parent models to ensure diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng11133MixinsPrecedenceTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng11133MixinsPrecedenceTest.java new file mode 100644 index 000000000000..f8b61348381a --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng11133MixinsPrecedenceTest.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.it; + +import java.io.File; +import java.nio.file.Files; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * MNG-11133: Mixins should override properties inherited from parent. + */ +public class MavenITmng11133MixinsPrecedenceTest extends AbstractMavenIntegrationTestCase { + + @Test + public void testMixinOverridesParentProperty() throws Exception { + File testDir = extractResources("/mng-11133-mixins/project"); + + Verifier verifier = newVerifier(testDir.getAbsolutePath()); + verifier.setAutoclean(false); + verifier.deleteDirectory("target"); + verifier.addCliArgument("help:effective-pom"); + verifier.addCliArgument("-Doutput=target/effective-pom.xml"); + verifier.execute(); + verifier.verifyErrorFreeLog(); + + verifier.verifyFilePresent("target/effective-pom.xml"); + String effectivePom = Files.readString(new File(testDir, "target/effective-pom.xml").toPath()); + assertTrue(effectivePom.contains("21")); + } +} diff --git a/its/core-it-suite/src/test/resources/mng-11133-mixins/mixins/mixin.xml b/its/core-it-suite/src/test/resources/mng-11133-mixins/mixins/mixin.xml new file mode 100644 index 000000000000..8c0cf4fc3e1f --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-11133-mixins/mixins/mixin.xml @@ -0,0 +1,32 @@ + + + + 4.2.0 + + org.apache.maven.its.mng11133 + mixin-jdk-21 + 1.0.0 + pom + + + 21 + + + diff --git a/its/core-it-suite/src/test/resources/mng-11133-mixins/parent/pom.xml b/its/core-it-suite/src/test/resources/mng-11133-mixins/parent/pom.xml new file mode 100644 index 000000000000..c7211cc84c9a --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-11133-mixins/parent/pom.xml @@ -0,0 +1,31 @@ + + + + 4.2.0 + + org.apache.maven.its.mng11133 + parent + 1.0 + pom + + + 11 + + diff --git a/its/core-it-suite/src/test/resources/mng-11133-mixins/project/pom.xml b/its/core-it-suite/src/test/resources/mng-11133-mixins/project/pom.xml new file mode 100644 index 000000000000..6fe6d575506e --- /dev/null +++ b/its/core-it-suite/src/test/resources/mng-11133-mixins/project/pom.xml @@ -0,0 +1,39 @@ + + + + 4.2.0 + + + org.apache.maven.its.mng11133 + parent + 1.0 + ../parent/pom.xml + + + org.apache.maven.its.mng11133 + project + 1.0 + + + + ../mixins/mixin.xml + + +