Properties treated as Map<String, String> for bind

Fixes gh-9152
This commit is contained in:
Madhura Bhave
2017-05-11 17:03:05 -07:00
parent bfbabce163
commit c99be7c2b0
2 changed files with 27 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.boot.context.properties.bind;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import org.springframework.boot.context.properties.bind.convert.BinderConversionService;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
@@ -44,15 +45,24 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
protected Object bind(ConfigurationPropertyName name, Bindable<?> target,
AggregateElementBinder elementBinder, Class<?> type) {
Map<Object, Object> map = CollectionFactory.createMap(type, 0);
Bindable<?> resolvedTarget = resolveTarget(target);
for (ConfigurationPropertySource source : getContext().getSources()) {
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
source = source.filter(name::isAncestorOf);
}
new EntryBinder(name, target, elementBinder).bindEntries(source, map);
new EntryBinder(name, resolvedTarget, elementBinder).bindEntries(source, map);
}
return (map.isEmpty() ? null : map);
}
private Bindable<?> resolveTarget(Bindable<?> target) {
Class<?> type = target.getType().resolve();
if (Properties.class.isAssignableFrom(type)) {
return Bindable.mapOf(String.class, String.class);
}
return target;
}
@Override
protected Map<Object, Object> merge(Map<Object, Object> existing,
Map<Object, Object> additional) {

View File

@@ -21,6 +21,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.junit.Before;
import org.junit.Test;
@@ -372,4 +373,19 @@ public class MapBinderTests {
eq(target), any(), isA(Map.class));
}
@Test
public void bindToPropertiesShouldBeEquivalentToMapOfStringString() throws Exception {
this.sources
.add(new MockConfigurationPropertySource("foo.bar.baz", "1", "line1"));
BindHandler handler = mock(BindHandler.class,
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
Bindable<Properties> target = Bindable.of(Properties.class);
this.binder.bind("foo", target, handler);
InOrder inOrder = inOrder(handler);
inOrder.verify(handler).onSuccess(eq(ConfigurationPropertyName.of("foo.bar.baz")),
eq(Bindable.of(String.class)), any(), eq("1"));
inOrder.verify(handler).onSuccess(eq(ConfigurationPropertyName.of("foo")),
eq(target), any(), isA(Properties.class));
}
}