Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,19 @@ private Model readParentLocally(
}

try {
ModelBuilderSessionState derived = derive(candidateSource);
// When processing BUILD_CONSUMER requests, parent models must be read
// with CONSUMER_PARENT type to enable profile activation. Without this,
// property-activated profiles in parent POMs are skipped (since
// BUILD_CONSUMER disables profile activation), leaving properties
// like BOM import versions unresolved.
ModelBuilderRequest parentRequest =
request.getRequestType() == ModelBuilderRequest.RequestType.BUILD_CONSUMER
? ModelBuilderRequest.builder(request)
.requestType(ModelBuilderRequest.RequestType.CONSUMER_PARENT)
.source(candidateSource)
.build()
: ModelBuilderRequest.build(request, candidateSource);
ModelBuilderSessionState derived = derive(parentRequest);
Model candidateModel = derived.readAsParentModel(profileActivationContext, parentChain);
// Add profiles from parent, preserving model ID tracking
for (Map.Entry<String, List<Profile>> entry :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
Expand Down Expand Up @@ -254,6 +255,67 @@ public void testMissingDependencyGroupIdInference() throws Exception {
}
}

/**
* Verifies that BUILD_CONSUMER resolves properties defined in parent POM profiles
* when the parent is found via reactor model resolution (mappedSources).
*
* This reproduces the bug where readParentLocally() finds a parent via
* resolveReactorModel() during BUILD_CONSUMER processing, but the derived
* session preserves BUILD_CONSUMER type instead of using CONSUMER_PARENT.
* Since isBuildRequestWithActivation() returns false for BUILD_CONSUMER,
* property-activated profiles in parent POMs are skipped, leaving
* properties (like BOM import versions) unresolved.
*/
@Test
public void testBuildConsumerResolvesParentProfileProperties() {
Path parentPom = getPom("consumer-profile-property-parent");
Path childPom = getPom("consumer-profile-property-child");

ModelBuilder.ModelBuilderSession mbs = builder.newSession();

// Build parent with BUILD_PROJECT to populate the reactor (mappedSources).
// This causes the parent to be discoverable via resolveReactorModel().
mbs.build(ModelBuilderRequest.builder()
.session(session)
.requestType(ModelBuilderRequest.RequestType.BUILD_PROJECT)
.source(Sources.buildSource(parentPom))
.build());

// Build child with BUILD_CONSUMER on the same session.
// The parent will be found via resolveReactorModel() in readParentLocally().
// Without the fix, the derived session preserves BUILD_CONSUMER type,
// which disables profile activation, leaving ${managed.version} unresolved.
ModelBuilderResult consumerResult = assertDoesNotThrow(
() -> mbs.build(ModelBuilderRequest.builder()
.session(session)
.requestType(ModelBuilderRequest.RequestType.BUILD_CONSUMER)
.source(Sources.buildSource(childPom))
.build()),
"BUILD_CONSUMER should not fail when parent defines properties in profiles");

assertNotNull(consumerResult);
Model effectiveModel = consumerResult.getEffectiveModel();
assertNotNull(effectiveModel);

// The property from the parent's profile should be resolved
assertEquals(
"1.2.3",
effectiveModel.getProperties().get("managed.version"),
"Property from parent's profile should be resolved in BUILD_CONSUMER effective model");

// The managed dependency version should be interpolated
assertNotNull(effectiveModel.getDependencyManagement());
Dependency managedDep = effectiveModel.getDependencyManagement().getDependencies().stream()
.filter(d -> "managed-lib".equals(d.getArtifactId()))
.findFirst()
.orElse(null);
assertNotNull(managedDep, "Managed dependency from parent should be inherited");
assertEquals(
"1.2.3",
managedDep.getVersion(),
"Managed dependency version should be interpolated, not ${managed.version}");
}

private Path getPom(String name) {
return Paths.get("src/test/resources/poms/factory/" + name + ".xml").toAbsolutePath();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.1.0">
<parent>
<groupId>org.apache.maven.tests</groupId>
<artifactId>consumer-profile-property-parent</artifactId>
<relativePath>consumer-profile-property-parent.xml</relativePath>
</parent>
<artifactId>consumer-profile-property-child</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.1.0">
<groupId>org.apache.maven.tests</groupId>
<artifactId>consumer-profile-property-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<!--
The property "managed.version" is ONLY defined inside a profile
with property-based activation. This simulates the real-world
scenario where parent POMs define version properties in profiles.
-->
<profiles>
<profile>
<id>default-versions</id>
<activation>
<property>
<name>!skipDefaultVersions</name>
</property>
</activation>
<properties>
<managed.version>1.2.3</managed.version>
</properties>
</profile>
</profiles>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>managed-lib</artifactId>
<version>${managed.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>