From 51ee702dac27faad054e26f90322c79568935e22 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sun, 2 Jul 2023 13:55:30 +0100 Subject: [PATCH] Allow configprops endpoint stringify primitive wrappers Update `ConfigurationPropertiesReportEndpoint` so that primitive wrapper input values in the Environment are stringified for display. Fixes gh-36076 --- ...ConfigurationPropertiesReportEndpoint.java | 2 +- ...gurationPropertiesReportEndpointTests.java | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) 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 ee9a1932b15..221d7c75719 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 @@ -394,7 +394,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 c6cfc7b1de3..816c4d1c887 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 @@ -44,7 +44,10 @@ 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.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; import org.springframework.mock.env.MockPropertySource; import org.springframework.util.unit.DataSize; @@ -143,6 +146,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) @@ -476,6 +494,8 @@ class ConfigurationPropertiesReportEndpointTests { private String ignored = "dummy"; + private Integer wrapper; + public String getDbPassword() { return this.dbPassword; } @@ -512,6 +532,14 @@ class ConfigurationPropertiesReportEndpointTests { return this.ignored; } + public Integer getWrapper() { + return this.wrapper; + } + + public void setWrapper(Integer wrapper) { + this.wrapper = wrapper; + } + } @Configuration(proxyBeanMethods = false)