diff --git a/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java b/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java index c68acd7618..3b8f7a318f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 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. @@ -47,6 +47,7 @@ import org.springframework.core.PriorityOrdered; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; @@ -108,6 +109,8 @@ public class ConfigurationPropertiesBindingPostProcessor private List> converters = Collections.emptyList(); + private List genericConverters = Collections.emptyList(); + private int order = Ordered.HIGHEST_PRECEDENCE + 1; /** @@ -121,6 +124,17 @@ public class ConfigurationPropertiesBindingPostProcessor this.converters = converters; } + /** + * A list of custom converters (in addition to the defaults) to use when converting + * properties for binding. + * @param converters the converters to set + */ + @Autowired(required = false) + @ConfigurationPropertiesBinding + public void setGenericConverters(List converters) { + this.genericConverters = converters; + } + /** * Set the order of the bean. * @param order the order @@ -407,6 +421,9 @@ public class ConfigurationPropertiesBindingPostProcessor for (Converter converter : this.converters) { conversionService.addConverter(converter); } + for (GenericConverter genericConverter : this.genericConverters) { + conversionService.addConverter(genericConverter); + } this.defaultConversionService = conversionService; } return this.defaultConversionService; diff --git a/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java b/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java index e5aaefc000..61a5bbd940 100644 --- a/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/bind/ConverterBindingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 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. @@ -16,6 +16,9 @@ package org.springframework.boot.bind; +import java.util.Collections; +import java.util.Set; + import org.junit.Test; import org.junit.runner.RunWith; @@ -30,7 +33,9 @@ import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.GenericConverter; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.hamcrest.Matchers.is; @@ -40,21 +45,26 @@ import static org.junit.Assert.assertThat; * Tests for {@link ConfigurationProperties} binding with custom converters. * * @author Dave Syer + * @author Stephane Nicoll */ @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(TestConfig.class) -@IntegrationTest("foo=bar") +@IntegrationTest({"foo=one", "bar=two"}) public class ConverterBindingTests { @Value("${foo:}") private String foo; + @Value("${bar:}") + private String bar; + @Autowired private Wrapper properties; @Test public void overridingOfPropertiesOrderOfAtPropertySources() { - assertThat(this.properties.getFoo().getName(), is(this.foo)); + assertThat(this.properties.getFoo().name, is(this.foo)); + assertThat(this.properties.getBar().name, is(this.bar)); } @Configuration @@ -68,9 +78,22 @@ public class ConverterBindingTests { @Override public Foo convert(String source) { - Foo foo = new Foo(); - foo.setName(source); - return foo; + return new Foo(source); + } + }; + } + + @Bean + public GenericConverter genericConverter() { + return new GenericConverter() { + @Override + public Set getConvertibleTypes() { + return Collections.singleton(new ConvertiblePair(String.class, Bar.class)); + } + + @Override + public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) { + return new Bar((String) source); } }; } @@ -84,16 +107,20 @@ public class ConverterBindingTests { public static class Foo { - private String name; + private final String name; - public String getName() { - return this.name; - } - - public void setName(String name) { + public Foo(String name) { this.name = name; } + } + public static class Bar { + + private final String name; + + public Bar(String name) { + this.name = name; + } } @ConfigurationProperties @@ -101,6 +128,8 @@ public class ConverterBindingTests { private Foo foo; + private Bar bar; + public Foo getFoo() { return this.foo; } @@ -109,6 +138,13 @@ public class ConverterBindingTests { this.foo = foo; } + public Bar getBar() { + return this.bar; + } + + public void setBar(Bar bar) { + this.bar = bar; + } } }