diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java index 49e8e68b324..fb0af8a63c6 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Map; import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationConfig; import com.fasterxml.jackson.databind.SerializationFeature; @@ -329,15 +330,17 @@ public class ConfigurationPropertiesReportEndpoint private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) { Class parentType = beanDesc.getType().getRawClass(); - Class type = writer.getType().getRawClass(); + JavaType type = writer.getType(); AnnotatedMethod setter = findSetter(beanDesc, writer); // If there's a setter, we assume it's OK to report on the value, // similarly, if there's no setter but the package names match, we assume // that its a nested class used solely for binding to config props, so it // should be kosher. This filter is not used if there is JSON metadata for // the property, so it's mainly for user-defined beans. - return (setter != null) || ClassUtils.getPackageName(parentType) - .equals(ClassUtils.getPackageName(type)); + return (setter != null) + || ClassUtils.getPackageName(parentType).equals(ClassUtils.getPackageName(type.getRawClass())) + || type.isMapLikeType() + || type.isCollectionLikeType(); } private AnnotatedMethod findSetter(BeanDescription beanDesc, @@ -354,5 +357,4 @@ public class ConfigurationPropertiesReportEndpoint } } - } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointSerializationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointSerializationTests.java index 2c9535437e3..388e30e4373 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointSerializationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointSerializationTests.java @@ -17,6 +17,8 @@ package org.springframework.boot.actuate.endpoint; import java.net.InetAddress; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -195,6 +197,40 @@ public class ConfigurationPropertiesReportEndpointSerializationTests { assertThat(map.get("address")).isEqualTo("192.168.1.10"); } + @Test + @SuppressWarnings("unchecked") + public void testOutputAllOnlyGetterProperties() throws Exception { + this.context.register(OnlyGetterPropertiesConfig.class); + EnvironmentTestUtils.addEnvironment(this.context, "foo.map.entryOne:true", + "foo.list[0]:abc"); + this.context.refresh(); + ConfigurationPropertiesReportEndpoint report = this.context + .getBean(ConfigurationPropertiesReportEndpoint.class); + Map properties = report.invoke(); + Map nestedProperties = (Map) properties + .get("foo"); + assertThat(nestedProperties).isNotNull(); + System.err.println(nestedProperties); + assertThat(nestedProperties.get("prefix")).isEqualTo("foo"); + Map propertiesMap = (Map) nestedProperties + .get("properties"); + assertThat(propertiesMap).isNotNull(); + assertThat(propertiesMap).hasSize(4); + String summary = (String) propertiesMap + .get("summary"); + assertThat(summary).isNull(); + Map map = (Map) propertiesMap + .get("map"); + assertThat(map).isNotNull(); + assertThat(map).hasSize(1); + assertThat(map.get("entryOne")).isEqualTo(true); + List list = (List) propertiesMap + .get("list"); + assertThat(list).isNotNull(); + assertThat(list).hasSize(1); + assertThat(list.get(0)).isEqualTo("abc"); + } + @Configuration @EnableConfigurationProperties public static class Base { @@ -290,6 +326,16 @@ public class ConfigurationPropertiesReportEndpointSerializationTests { } + @Configuration + @Import(Base.class) + public static class OnlyGetterPropertiesConfig { + @Bean + @ConfigurationProperties(prefix = "foo") + public OnlyGetterProperties foo() { + return new OnlyGetterProperties(); + } + } + public static class Foo { private String name = "654321"; @@ -393,4 +439,17 @@ public class ConfigurationPropertiesReportEndpointSerializationTests { } + public static class OnlyGetterProperties extends Foo { + private Map map = new HashMap<>(); + private List list = new ArrayList<>(); + + public Map getMap() { + return this.map; + } + + public List getList() { + return this.list; + } + } + }