parent
0f69a157ac
commit
4ff8126217
|
@ -26,7 +26,6 @@ import org.springframework.boot.context.properties.bind.validation.ValidationBin
|
|||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -39,10 +38,9 @@ import org.springframework.validation.Validator;
|
|||
* {@link PropertySource}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
* @see ConfigurationPropertiesBinderBuilder
|
||||
*/
|
||||
public class ConfigurationPropertiesBinder {
|
||||
class ConfigurationPropertiesBinder {
|
||||
|
||||
private final Iterable<PropertySource<?>> propertySources;
|
||||
|
||||
|
@ -61,20 +59,6 @@ public class ConfigurationPropertiesBinder {
|
|||
this.configurationSources = ConfigurationPropertySources.from(propertySources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the specified {@code target} object if it is annotated with
|
||||
* {@link ConfigurationProperties}, otherwise ignore it.
|
||||
* @param target the target to bind the configuration property sources to
|
||||
* @throws ConfigurationPropertiesBindingException if the binding failed
|
||||
*/
|
||||
public void bind(Object target) {
|
||||
ConfigurationProperties annotation = AnnotationUtils
|
||||
.findAnnotation(target.getClass(), ConfigurationProperties.class);
|
||||
if (annotation != null) {
|
||||
bind(target, annotation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the specified {@code target} object using the configuration defined by the
|
||||
* specified {@code annotation}.
|
||||
|
@ -93,8 +77,10 @@ public class ConfigurationPropertiesBinder {
|
|||
binder.bind(annotation.prefix(), bindable, handler);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ConfigurationPropertiesBindingException(target.getClass(),
|
||||
getAnnotationDetails(annotation), ex);
|
||||
String message = "Could not bind properties to '"
|
||||
+ ClassUtils.getShortName(target.getClass()) + "': "
|
||||
+ getAnnotationDetails(annotation);
|
||||
throw new ConfigurationPropertiesBindingException(message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,19 +38,18 @@ import org.springframework.validation.Validator;
|
|||
* {@link ApplicationContext}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ConfigurationPropertiesBinderBuilder {
|
||||
class ConfigurationPropertiesBinderBuilder {
|
||||
|
||||
/**
|
||||
* The bean name of the configuration properties validator.
|
||||
*/
|
||||
public static final String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";
|
||||
private static final String VALIDATOR_BEAN_NAME = ConfigurationPropertiesBindingPostProcessor.VALIDATOR_BEAN_NAME;
|
||||
|
||||
/**
|
||||
* The bean name of the configuration properties conversion service.
|
||||
*/
|
||||
public static final String CONVERSION_SERVICE_BEAN_NAME = ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME;
|
||||
private static final String CONVERSION_SERVICE_BEAN_NAME = ConfigurableApplicationContext.CONVERSION_SERVICE_BEAN_NAME;
|
||||
|
||||
private static final String[] VALIDATOR_CLASSES = { "javax.validation.Validator",
|
||||
"javax.validation.ValidatorFactory",
|
||||
|
@ -68,7 +67,7 @@ public class ConfigurationPropertiesBinderBuilder {
|
|||
* Creates an instance with the {@link ApplicationContext} to use.
|
||||
* @param applicationContext the application context
|
||||
*/
|
||||
public ConfigurationPropertiesBinderBuilder(ApplicationContext applicationContext) {
|
||||
ConfigurationPropertiesBinderBuilder(ApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "ApplicationContext must not be null");
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
|
|
@ -17,32 +17,18 @@
|
|||
package org.springframework.boot.context.properties;
|
||||
|
||||
import org.springframework.core.NestedExceptionUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Exception thrown when a {@code @ConfigurationProperties} annotated object failed to be
|
||||
* bound.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ConfigurationPropertiesBindingException extends RuntimeException {
|
||||
class ConfigurationPropertiesBindingException extends RuntimeException {
|
||||
|
||||
private final Class<?> targetClass;
|
||||
|
||||
public ConfigurationPropertiesBindingException(Class<?> targetClass, String message,
|
||||
ConfigurationPropertiesBindingException(String message,
|
||||
Throwable cause) {
|
||||
super("Could not bind properties to '" + ClassUtils.getShortName(targetClass)
|
||||
+ "': " + message, cause);
|
||||
this.targetClass = targetClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target type of the object that failed to be bound.
|
||||
* @return the target {@link Class}
|
||||
*/
|
||||
public Class<?> getTargetClass() {
|
||||
return this.targetClass;
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,6 +55,11 @@ public class ConfigurationPropertiesBindingPostProcessor
|
|||
implements BeanPostProcessor, BeanFactoryAware, EnvironmentAware,
|
||||
ApplicationContextAware, InitializingBean, PriorityOrdered {
|
||||
|
||||
/**
|
||||
* The bean name of the configuration properties validator.
|
||||
*/
|
||||
public static final String VALIDATOR_BEAN_NAME = "configurationPropertiesValidator";
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(ConfigurationPropertiesBindingPostProcessor.class);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.junit.Test;
|
|||
import org.springframework.boot.context.properties.bind.validation.BindValidationException;
|
||||
import org.springframework.boot.context.properties.bind.validation.ValidationErrors;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
|
@ -63,7 +64,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
.withEnvironment(this.environment)
|
||||
.withConversionService(conversionService).build();
|
||||
PropertyWithAddress target = new PropertyWithAddress();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getAddress()).isNotNull();
|
||||
assertThat(target.getAddress().streetName).isEqualTo("FooStreet");
|
||||
assertThat(target.getAddress().number).isEqualTo(42);
|
||||
|
@ -86,7 +87,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
ConfigurationPropertiesBinder binder = this.builder
|
||||
.withEnvironment(this.environment).build();
|
||||
PropertyWithDuration target = new PropertyWithDuration();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getDuration().getSeconds()).isEqualTo(60);
|
||||
}
|
||||
|
||||
|
@ -122,7 +123,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
.withEnvironment(this.environment).build();
|
||||
assertThat(
|
||||
bindWithValidationErrors(binder, new PropertyWithJSR303()).getAllErrors())
|
||||
.hasSize(2);
|
||||
.hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -132,7 +133,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithJSR303 target = new PropertyWithJSR303();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getFoo()).isEqualTo("123456");
|
||||
assertThat(target.getBar()).isEqualTo("654321");
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
private ValidationErrors bindWithValidationErrors(
|
||||
ConfigurationPropertiesBinder binder, Object target) {
|
||||
try {
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
throw new AssertionError("Should have failed to bind " + target);
|
||||
}
|
||||
catch (ConfigurationPropertiesBindingException ex) {
|
||||
|
@ -150,6 +151,11 @@ public class ConfigurationPropertiesBinderBuilderTests {
|
|||
}
|
||||
}
|
||||
|
||||
private void bind(ConfigurationPropertiesBinder binder, Object target) {
|
||||
binder.bind(target, AnnotationUtils
|
||||
.findAnnotation(target.getClass(), ConfigurationProperties.class));
|
||||
}
|
||||
|
||||
@ConfigurationProperties(prefix = "test")
|
||||
public static class PropertyWithAddress {
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.junit.Test;
|
|||
import org.springframework.boot.context.properties.bind.BindException;
|
||||
import org.springframework.boot.context.properties.bind.validation.BindValidationException;
|
||||
import org.springframework.boot.context.properties.bind.validation.ValidationErrors;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
@ -61,7 +62,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PersonProperties target = new PersonProperties();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.name).isEqualTo("John Smith");
|
||||
assertThat(target.age).isEqualTo(42);
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
this.environment.getPropertySources(), null, null);
|
||||
PersonProperties target = new PersonProperties();
|
||||
try {
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (ConfigurationPropertiesBindingException ex) {
|
||||
|
@ -92,17 +93,10 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithIgnoreInvalidFields target = new PropertyWithIgnoreInvalidFields();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getBar()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindNonAnnotatedObject() {
|
||||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
binder.bind("FooBar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindToEnum() {
|
||||
bindToEnum("test.theValue=foo");
|
||||
|
@ -120,7 +114,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithEnum target = new PropertyWithEnum();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getTheValue()).isEqualTo(FooEnum.FOO);
|
||||
}
|
||||
|
||||
|
@ -136,7 +130,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithEnum target = new PropertyWithEnum();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getTheValues()).contains(expected);
|
||||
}
|
||||
|
||||
|
@ -147,7 +141,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithCharArray target = new PropertyWithCharArray();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getChars()).isEqualTo("word".toCharArray());
|
||||
}
|
||||
|
||||
|
@ -163,7 +157,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithRelaxedNames target = new PropertyWithRelaxedNames();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getFooBar()).isEqualTo("test2");
|
||||
assertThat(target.getBarBAZ()).isEqualTo("testb");
|
||||
}
|
||||
|
@ -175,7 +169,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithNestedValue target = new PropertyWithNestedValue();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getNested().getValue()).isEqualTo("test1");
|
||||
}
|
||||
|
||||
|
@ -186,7 +180,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, null);
|
||||
PropertiesWithMap target = new PropertiesWithMap();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getMap()).containsOnly(entry("foo", "bar"));
|
||||
}
|
||||
|
||||
|
@ -199,7 +193,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
propertySources, null, null);
|
||||
PropertiesWithComplexMap target = new PropertiesWithComplexMap();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getMap()).containsOnlyKeys("foo");
|
||||
assertThat(target.getMap().get("foo")).containsOnly(entry("bar", "baz"));
|
||||
}
|
||||
|
@ -214,7 +208,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
propertySources, null, null);
|
||||
PersonProperties target = new PersonProperties();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.name).isEqualTo("Jane");
|
||||
}
|
||||
|
||||
|
@ -226,7 +220,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
this.environment.getPropertySources(), null, null);
|
||||
PropertyWithValidatingSetter target = new PropertyWithValidatingSetter();
|
||||
try {
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (ConfigurationPropertiesBindingException ex) {
|
||||
|
@ -255,7 +249,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
ConfigurationPropertiesBinder binder = new ConfigurationPropertiesBinder(
|
||||
this.environment.getPropertySources(), null, validator);
|
||||
PropertyWithValidatingSetter target = new PropertyWithValidatingSetter();
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
assertThat(target.getFoo()).isEqualTo("bar");
|
||||
verify(validator, times(0)).validate(eq(target), any(Errors.class));
|
||||
}
|
||||
|
@ -263,7 +257,7 @@ public class ConfigurationPropertiesBinderTests {
|
|||
private ValidationErrors bindWithValidationErrors(
|
||||
ConfigurationPropertiesBinder binder, Object target) {
|
||||
try {
|
||||
binder.bind(target);
|
||||
bind(binder, target);
|
||||
throw new AssertionError("Should have failed to bind " + target);
|
||||
}
|
||||
catch (ConfigurationPropertiesBindingException ex) {
|
||||
|
@ -273,6 +267,11 @@ public class ConfigurationPropertiesBinderTests {
|
|||
}
|
||||
}
|
||||
|
||||
private void bind(ConfigurationPropertiesBinder binder, Object target) {
|
||||
binder.bind(target, AnnotationUtils
|
||||
.findAnnotation(target.getClass(), ConfigurationProperties.class));
|
||||
}
|
||||
|
||||
@ConfigurationProperties(value = "person", ignoreUnknownFields = false)
|
||||
static class PersonProperties {
|
||||
|
||||
|
|
Loading…
Reference in New Issue