Propagate Map conversion failures

Align `MapBinder` with `IndexedBinder` so that if a value is specified
any converter exception are propagated.

See gh-11493
pull/11498/merge
Phillip Webb 7 years ago
parent 25609c060e
commit 79fc8838fd

@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
@ -27,7 +27,6 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyS
import org.springframework.boot.context.properties.source.IterableConfigurationPropertySource;
import org.springframework.core.CollectionFactory;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.util.ClassUtils;
/**
@ -58,9 +57,12 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
Bindable<?> resolvedTarget = resolveTarget(target);
for (ConfigurationPropertySource source : getContext().getSources()) {
if (!ConfigurationPropertyName.EMPTY.equals(name)) {
Object converted = convertIfFound(name, source, resolvedTarget);
if (converted != null) {
return converted;
ConfigurationProperty property = source.getConfigurationProperty(name);
if (property != null) {
Object value = getContext().getPlaceholdersResolver()
.resolvePlaceholders(property.getValue());
return ResolvableTypeDescriptor.forType(target.getType())
.convert(getContext().getConversionService(), value);
}
source = source.filter(name::isAncestorOf);
}
@ -77,20 +79,6 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
return target;
}
private Object convertIfFound(ConfigurationPropertyName name, ConfigurationPropertySource source, Bindable<?> target) {
ConfigurationProperty configurationProperty = source.getConfigurationProperty(name);
if (configurationProperty != null) {
try {
return ResolvableTypeDescriptor.forType(target.getType())
.convert(getContext().getConversionService(), configurationProperty.getValue());
}
catch (ConverterNotFoundException ex) {
}
}
return null;
}
@Override
protected Map<Object, Object> merge(Map<Object, Object> existing,
Map<Object, Object> additional) {

@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2018 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.
@ -26,7 +26,9 @@ import java.util.Properties;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
@ -75,6 +77,9 @@ public class MapBinderTests {
private static final Bindable<Map<String, String[]>> STRING_ARRAY_MAP = Bindable
.mapOf(String.class, String[].class);
@Rule
public ExpectedException thrown = ExpectedException.none();
private List<ConfigurationPropertySource> sources = new ArrayList<>();
private Binder binder;
@ -532,7 +537,6 @@ public class MapBinderTests {
DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new MapConverter());
Binder binder = new Binder(this.sources, null, conversionService);
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo", "a,b");
this.sources.add(source);
@ -546,8 +550,8 @@ public class MapBinderTests {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo", "a,b");
this.sources.add(source);
BindResult<Map<String, String>> result = this.binder.bind("foo", STRING_STRING_MAP);
assertThat(result.isBound()).isFalse();
this.thrown.expect(BindException.class);
this.binder.bind("foo", STRING_STRING_MAP);
}
private <K, V> Bindable<Map<K, V>> getMapBindable(Class<K> keyGeneric,
@ -603,12 +607,14 @@ public class MapBinderTests {
}
static class MapConverter implements Converter<String, Map<String, String>> {
@Override
public Map<String, String> convert(String s) {
Map<String, String> map = new HashMap<>();
StringUtils.commaDelimitedListToSet(s).forEach(k -> map.put(k, ""));
return map;
}
}
}

Loading…
Cancel
Save