diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java index 0704cacdb4f..845a98ca12d 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java @@ -168,17 +168,17 @@ class JavaBeanBinder implements BeanBinder { } @SuppressWarnings("unchecked") - public static Bean get(Bindable bindable, - boolean useExistingValueForType) { + public static Bean get(Bindable bindable, boolean canCallGetValue) { Class type = bindable.getType().resolve(); Supplier value = bindable.getValue(); - if (value == null && !isInstantiable(type)) { - return null; - } - if (useExistingValueForType && value != null) { - T instance = value.get(); + T instance = null; + if (canCallGetValue && value != null) { + instance = value.get(); type = (instance != null ? instance.getClass() : type); } + if (instance == null && !isInstantiable(type)) { + return null; + } Bean bean = Bean.cached; if (bean == null || !type.equals(bean.getType())) { bean = new Bean<>(type); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BinderTests.java index b0431228cf2..41fe5dabad7 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BinderTests.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.validation.Validation; + import org.assertj.core.matcher.AssertionMatcher; import org.junit.Before; import org.junit.Rule; @@ -30,14 +32,21 @@ import org.junit.rules.ExpectedException; import org.mockito.Answers; import org.mockito.InOrder; +import org.springframework.boot.context.properties.bind.validation.ValidationBindHandler; import org.springframework.boot.context.properties.source.ConfigurationPropertyName; import org.springframework.boot.context.properties.source.ConfigurationPropertySource; +import org.springframework.boot.context.properties.source.ConfigurationPropertySources; import org.springframework.boot.context.properties.source.MockConfigurationPropertySource; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.ConversionFailedException; +import org.springframework.core.env.PropertySource; import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.Resource; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.test.context.support.TestPropertySourceUtils; +import org.springframework.validation.Validator; +import org.springframework.validation.annotation.Validated; +import org.springframework.validation.beanvalidation.SpringValidatorAdapter; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; @@ -239,6 +248,20 @@ public class BinderTests { this.binder.bind("foo", target); } + @Test + public void bindToValidatedBeanWithResourceAndNonEnumerablePropertySource() { + ConfigurationPropertySources.from(new PropertySource("test") { + @Override + public Object getProperty(String name) { + return null; + } + }).forEach(this.sources::add); + Validator validator = new SpringValidatorAdapter(Validation.byDefaultProvider() + .configure().buildValidatorFactory().getValidator()); + this.binder.bind("foo", Bindable.of(ResourceBean.class), + new ValidationBindHandler(validator)); + } + public static class JavaBean { private String value; @@ -265,4 +288,19 @@ public class BinderTests { } + @Validated + public static class ResourceBean { + + private Resource resource; + + public Resource getResource() { + return this.resource; + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + } + }