From 68bc82cfc220988da907a6fdf34c80b3b3144029 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Tue, 3 Dec 2019 18:09:28 -0800 Subject: [PATCH] Ignore CannotLoadBeanClassException in config props validator If the bean definition type contains a placeholder value, beanFactory.getType can throw a CannotLoadBeanClassException. We can ignore this exception while validating the bean definitions for constructor binding beans. Fixes gh-19207 --- ...tionPropertiesBeanDefinitionValidator.java | 17 ++++-- .../xml/SampleSpringXmlApplication.java | 2 + .../smoketest/xml/service/OtherService.java | 25 ++++++++ ...ringXmlPlaceholderBeanDefinitionTests.java | 59 +++++++++++++++++++ .../src/test/resources/META-INF/context.xml | 13 ++++ .../src/test/resources/application.properties | 1 + 6 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/service/OtherService.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/java/smoketest/xml/SampleSpringXmlPlaceholderBeanDefinitionTests.java create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/META-INF/context.xml create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/application.properties diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanDefinitionValidator.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanDefinitionValidator.java index 413fedb99a03..3b34b4da59e3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanDefinitionValidator.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanDefinitionValidator.java @@ -18,6 +18,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -57,12 +58,18 @@ public int getOrder() { } private void validate(ConfigurableListableBeanFactory beanFactory, String beanName) { - Class beanClass = beanFactory.getType(beanName, false); - if (beanClass != null && BindMethod.forType(beanClass) == BindMethod.VALUE_OBJECT) { - throw new BeanCreationException(beanName, - "@EnableConfigurationProperties or @ConfigurationPropertiesScan must be used to add " - + "@ConstructorBinding type " + beanClass.getName()); + try { + Class beanClass = beanFactory.getType(beanName, false); + if (beanClass != null && BindMethod.forType(beanClass) == BindMethod.VALUE_OBJECT) { + throw new BeanCreationException(beanName, + "@EnableConfigurationProperties or @ConfigurationPropertiesScan must be used to add " + + "@ConstructorBinding type " + beanClass.getName()); + } + } + catch (CannotLoadBeanClassException ex) { + // Ignore } + } /** diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/SampleSpringXmlApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/SampleSpringXmlApplication.java index 4b0dd3f13237..019b4fc77116 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/SampleSpringXmlApplication.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/SampleSpringXmlApplication.java @@ -23,7 +23,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +@SpringBootApplication public class SampleSpringXmlApplication implements CommandLineRunner { private static final String CONTEXT_XML = "classpath:/META-INF/application-context.xml"; diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/service/OtherService.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/service/OtherService.java new file mode 100644 index 000000000000..d42eef7a8c1e --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/main/java/smoketest/xml/service/OtherService.java @@ -0,0 +1,25 @@ +/* + * 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 smoketest.xml.service; + +public class OtherService { + + public String getMessage() { + return "Hello Other World"; + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/java/smoketest/xml/SampleSpringXmlPlaceholderBeanDefinitionTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/java/smoketest/xml/SampleSpringXmlPlaceholderBeanDefinitionTests.java new file mode 100644 index 000000000000..1d5128e8c2f5 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/java/smoketest/xml/SampleSpringXmlPlaceholderBeanDefinitionTests.java @@ -0,0 +1,59 @@ +/* + * 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 smoketest.xml; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import smoketest.xml.service.OtherService; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for XML config with placeholders in bean definitions. + * + * @author Madhura Bhave + */ +@SpringBootTest( + classes = { SampleSpringXmlApplication.class, SampleSpringXmlPlaceholderBeanDefinitionTests.TestConfig.class }) +@ExtendWith(OutputCaptureExtension.class) +class SampleSpringXmlPlaceholderBeanDefinitionTests { + + @Test + void beanWithPlaceholderShouldNotFail(CapturedOutput output) throws Exception { + assertThat(output).contains("Hello Other World"); + } + + @Configuration(proxyBeanMethods = false) + @ImportResource({ "classpath:/META-INF/context.xml" }) + static class TestConfig { + + @Bean + CommandLineRunner testCommandLineRunner(OtherService service) { + return (args) -> System.out.println(service.getMessage()); + } + + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/META-INF/context.xml b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/META-INF/context.xml new file mode 100644 index 000000000000..8138221a18ff --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/META-INF/context.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/application.properties new file mode 100644 index 000000000000..5d00bf43bf51 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-xml/src/test/resources/application.properties @@ -0,0 +1 @@ +bean.name=smoketest.xml.service.OtherService \ No newline at end of file