Fix self-referential parentId in MappingsEndpoint

The mappings endpoint reported the context's own id as `parentId`
instead of the parent context's id, preventing clients from
reconstructing the context hierarchy from the response. Align with
sibling endpoints (`BeansEndpoint`,
`ConfigurationPropertiesReportEndpoint`, `ConditionsReportEndpoint`)
which already use `parent.getId()`.

See gh-50373

Signed-off-by: Lee JiWon <dlwldnjs1009@gmail.com>
This commit is contained in:
Lee JiWon
2026-05-12 12:26:19 -07:00
committed by Phillip Webb
parent f6ef0c1f69
commit e3058d849b
2 changed files with 66 additions and 1 deletions
@@ -0,0 +1,65 @@
/*
* Copyright 2012-present the original author or authors.
*
* Licensed 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
*
* https://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.springframework.boot.actuate.web.mappings;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.springframework.boot.actuate.web.mappings.MappingsEndpoint.ApplicationMappingsDescriptor;
import org.springframework.boot.actuate.web.mappings.MappingsEndpoint.ContextMappingsDescriptor;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MappingsEndpoint}.
*
* @author Lee JiWon
*/
class MappingsEndpointTests {
@Test
void mappingsParentIdMatchesParentContextId() {
ApplicationContextRunner parentRunner = new ApplicationContextRunner();
parentRunner.run((parent) -> new ApplicationContextRunner().withUserConfiguration(EndpointConfiguration.class)
.withParent(parent)
.run((child) -> {
ApplicationMappingsDescriptor result = child.getBean(MappingsEndpoint.class).mappings();
ContextMappingsDescriptor parentDescriptor = result.getContexts().get(parent.getId());
ContextMappingsDescriptor childDescriptor = result.getContexts().get(child.getId());
assertThat(parentDescriptor).isNotNull();
assertThat(parentDescriptor.getParentId()).isNull();
assertThat(childDescriptor).isNotNull();
assertThat(childDescriptor.getParentId()).isEqualTo(parent.getId());
}));
}
@Configuration(proxyBeanMethods = false)
static class EndpointConfiguration {
@Bean
MappingsEndpoint mappingsEndpoint(ConfigurableApplicationContext context) {
return new MappingsEndpoint(Collections.emptyList(), context);
}
}
}
@@ -59,7 +59,7 @@ public class MappingsEndpoint {
this.descriptionProviders.forEach(
(provider) -> mappings.put(provider.getMappingName(), provider.describeMappings(applicationContext)));
return new ContextMappingsDescriptor(mappings,
(applicationContext.getParent() != null) ? applicationContext.getId() : null);
(applicationContext.getParent() != null) ? applicationContext.getParent().getId() : null);
}
/**