From 2c4a1f1c1537b3aeba7f8f08a75e26e8bbb2d30a Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Wed, 4 Dec 2019 14:39:20 -0800 Subject: [PATCH] Display @Validated constructor bound properties in configprops endpoint Fixes gh-19219 --- .../spring-boot-actuator/pom.xml | 5 +++ ...ConfigurationPropertiesReportEndpoint.java | 3 +- ...ionPropertiesReportEndpointProxyTests.java | 30 +++++++++++++ ...ValidatedConstructorBindingProperties.java | 44 +++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ValidatedConstructorBindingProperties.java diff --git a/spring-boot-project/spring-boot-actuator/pom.xml b/spring-boot-project/spring-boot-actuator/pom.xml index c18b3ce871..cedc88716c 100644 --- a/spring-boot-project/spring-boot-actuator/pom.xml +++ b/spring-boot-project/spring-boot-actuator/pom.xml @@ -345,6 +345,11 @@ log4j-to-slf4j test + + org.apache.tomcat.embed + tomcat-embed-el + test + org.glassfish.jersey.media jersey-media-json-jackson 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 f09686b299..88a51d12c8 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 @@ -310,7 +310,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext public List changeProperties(SerializationConfig config, BeanDescription beanDesc, List beanProperties) { List result = new ArrayList<>(); - Constructor bindConstructor = findBindConstructor(beanDesc.getType().getRawClass()); + Class beanClass = beanDesc.getType().getRawClass(); + Constructor bindConstructor = findBindConstructor(ClassUtils.getUserClass(beanClass)); for (BeanPropertyWriter writer : beanProperties) { if (isCandidate(beanDesc, writer, bindConstructor)) { result.add(writer); diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointProxyTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointProxyTests.java index 9a1a3c46f1..61c7a82709 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointProxyTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointProxyTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.actuate.context.properties; +import java.util.Map; + import javax.sql.DataSource; import org.junit.jupiter.api.Test; @@ -27,6 +29,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; @@ -35,6 +38,7 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import static org.assertj.core.api.Assertions.assertThat; @@ -44,6 +48,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Phillip Webb * @author Andy Wilkinson + * @author Madhura Bhave */ class ConfigurationPropertiesReportEndpointProxyTests { @@ -60,6 +65,19 @@ class ConfigurationPropertiesReportEndpointProxyTests { }); } + @Test + void proxiedConstructorBoundPropertiesShouldBeAvailableInReport() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(ValidatedConfiguration.class).withPropertyValues("validated.name=baz"); + contextRunner.run((context) -> { + ApplicationConfigurationProperties applicationProperties = context + .getBean(ConfigurationPropertiesReportEndpoint.class).configurationProperties(); + Map properties = applicationProperties.getContexts().get(context.getId()).getBeans() + .values().stream().map(ConfigurationPropertiesBeanDescriptor::getProperties).findFirst().get(); + assertThat(properties.get("name")).isEqualTo("baz"); + }); + } + @Configuration(proxyBeanMethods = false) @EnableTransactionManagement(proxyTargetClass = false) @EnableConfigurationProperties @@ -75,6 +93,11 @@ class ConfigurationPropertiesReportEndpointProxyTests { return new DataSourceTransactionManager(dataSource); } + @Bean + MethodValidationPostProcessor testPostProcessor() { + return new MethodValidationPostProcessor(); + } + @Bean DataSource dataSource() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).build(); @@ -103,4 +126,11 @@ class ConfigurationPropertiesReportEndpointProxyTests { } + @Configuration(proxyBeanMethods = false) + @EnableConfigurationProperties(ValidatedConstructorBindingProperties.class) + @Import(Config.class) + static class ValidatedConfiguration { + + } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ValidatedConstructorBindingProperties.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ValidatedConstructorBindingProperties.java new file mode 100644 index 0000000000..3bb8722ad4 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ValidatedConstructorBindingProperties.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2019 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.context.properties; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; +import org.springframework.validation.annotation.Validated; + +/** + * Used for testing the {@link ConfigurationPropertiesReportEndpoint} endpoint with + * validated {@link ConfigurationProperties @ConfigurationProperties}. + * + * @author Madhura Bhave + */ +@Validated +@ConstructorBinding +@ConfigurationProperties(prefix = "validated") +public class ValidatedConstructorBindingProperties { + + private final String name; + + ValidatedConstructorBindingProperties(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + +}