Guard against binding non-instantiable types

Update `JavaBeanBinder` so that null instances that are non-instantiable
are not bound.

Fixes gh-10131
pull/10590/head
Madhura Bhave 7 years ago committed by Phillip Webb
parent b7c37c2807
commit 3ec3b64d45

@ -168,17 +168,17 @@ class JavaBeanBinder implements BeanBinder {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Bean<T> get(Bindable<T> bindable, public static <T> Bean<T> get(Bindable<T> bindable, boolean canCallGetValue) {
boolean useExistingValueForType) {
Class<?> type = bindable.getType().resolve(); Class<?> type = bindable.getType().resolve();
Supplier<T> value = bindable.getValue(); Supplier<T> value = bindable.getValue();
if (value == null && !isInstantiable(type)) { T instance = null;
return null; if (canCallGetValue && value != null) {
} instance = value.get();
if (useExistingValueForType && value != null) {
T instance = value.get();
type = (instance != null ? instance.getClass() : type); type = (instance != null ? instance.getClass() : type);
} }
if (instance == null && !isInstantiable(type)) {
return null;
}
Bean<?> bean = Bean.cached; Bean<?> bean = Bean.cached;
if (bean == null || !type.equals(bean.getType())) { if (bean == null || !type.equals(bean.getType())) {
bean = new Bean<>(type); bean = new Bean<>(type);

@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.validation.Validation;
import org.assertj.core.matcher.AssertionMatcher; import org.assertj.core.matcher.AssertionMatcher;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
@ -30,14 +32,21 @@ import org.junit.rules.ExpectedException;
import org.mockito.Answers; import org.mockito.Answers;
import org.mockito.InOrder; 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.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource; 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.boot.context.properties.source.MockConfigurationPropertySource;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment; import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.test.context.support.TestPropertySourceUtils; 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.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -239,6 +248,20 @@ public class BinderTests {
this.binder.bind("foo", target); this.binder.bind("foo", target);
} }
@Test
public void bindToValidatedBeanWithResourceAndNonEnumerablePropertySource() {
ConfigurationPropertySources.from(new PropertySource<String>("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 { public static class JavaBean {
private String value; 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;
}
}
} }

Loading…
Cancel
Save