diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java index 85ab6f420b..1e03b58419 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java @@ -385,7 +385,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext } private Object stringifyIfNecessary(Object value) { - if (value == null || value.getClass().isPrimitive()) { + if (value == null || ClassUtils.isPrimitiveOrWrapper(value.getClass()) || value instanceof String) { return value; } if (CharSequence.class.isAssignableFrom(value.getClass())) { diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java index c0e606a923..8180021e5f 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java @@ -46,6 +46,9 @@ import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; import org.springframework.mock.env.MockPropertySource; import org.springframework.util.unit.DataSize; @@ -150,6 +153,21 @@ class ConfigurationPropertiesReportEndpointTests { .isEqualTo(Duration.ofSeconds(10).toString()))); } + @Test // gh-36076 + void descriptorWithWrapperProperty() { + this.contextRunner.withUserConfiguration(TestPropertiesConfiguration.class).withInitializer((context) -> { + ConfigurableEnvironment environment = context.getEnvironment(); + Map map = Collections.singletonMap("test.wrapper", 10); + PropertySource propertySource = new MapPropertySource("test", map); + environment.getPropertySources().addLast(propertySource); + }) + .run(assertProperties("test", (properties) -> assertThat(properties.get("wrapper")).isEqualTo(10), + (inputs) -> { + Map wrapper = (Map) inputs.get("wrapper"); + assertThat(wrapper.get("value")).isEqualTo(10); + })); + } + @Test void descriptorWithNonCamelCaseProperty() { this.contextRunner.withUserConfiguration(MixedCasePropertiesConfiguration.class) @@ -452,6 +470,8 @@ class ConfigurationPropertiesReportEndpointTests { private final String ignored = "dummy"; + private Integer wrapper; + public String getDbPassword() { return this.dbPassword; } @@ -488,6 +508,14 @@ class ConfigurationPropertiesReportEndpointTests { return this.ignored; } + public Integer getWrapper() { + return this.wrapper; + } + + public void setWrapper(Integer wrapper) { + this.wrapper = wrapper; + } + } @Configuration(proxyBeanMethods = false)