Skip to content

Commit 95174a0

Browse files
committed
Don't fail if aggregate merge can't get existing value
Fixes gh-13303
1 parent 8ce13c7 commit 95174a0

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> targe
5555
}
5656

5757
@Override
58-
@SuppressWarnings("unchecked")
5958
protected Collection<Object> merge(Supplier<?> existing,
6059
Collection<Object> additional) {
61-
Collection<Object> existingCollection = (Collection<Object>) existing.get();
60+
Collection<Object> existingCollection = getExistingIfPossible(existing);
6261
if (existingCollection == null) {
6362
return additional;
6463
}
@@ -72,6 +71,16 @@ protected Collection<Object> merge(Supplier<?> existing,
7271
}
7372
}
7473

74+
@SuppressWarnings("unchecked")
75+
private Collection<Object> getExistingIfPossible(Supplier<?> existing) {
76+
try {
77+
return (Collection<Object>) existing.get();
78+
}
79+
catch (Exception ex) {
80+
return null;
81+
}
82+
}
83+
7584
private Collection<Object> copyIfPossible(Collection<Object> collection) {
7685
try {
7786
return createNewCollection(collection);

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,9 @@ private Bindable<?> resolveTarget(Bindable<?> target) {
8383
}
8484

8585
@Override
86-
@SuppressWarnings("unchecked")
8786
protected Map<Object, Object> merge(Supplier<?> existing,
8887
Map<Object, Object> additional) {
89-
Map<Object, Object> existingMap = (Map<Object, Object>) existing.get();
88+
Map<Object, Object> existingMap = getExistingIfPossible(existing);
9089
if (existingMap == null) {
9190
return additional;
9291
}
@@ -101,6 +100,16 @@ protected Map<Object, Object> merge(Supplier<?> existing,
101100
}
102101
}
103102

103+
@SuppressWarnings("unchecked")
104+
private Map<Object, Object> getExistingIfPossible(Supplier<?> existing) {
105+
try {
106+
return (Map<Object, Object>) existing.get();
107+
}
108+
catch (Exception ex) {
109+
return null;
110+
}
111+
}
112+
104113
private Map<Object, Object> copyIfPossible(Map<Object, Object> map) {
105114
try {
106115
return createNewMap(map.getClass(), map);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/CollectionBinderTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ public void bindToBeanWithClonedArray() {
417417
assertThat(bean.getBar()).containsExactly("hello");
418418
}
419419

420+
@Test
421+
public void bindToBeanWithExceptionInGetterForExistingValue() {
422+
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
423+
source.put("foo.values", "a,b,c");
424+
this.sources.add(source);
425+
BeanWithGetterException result = this.binder
426+
.bind("foo", Bindable.of(BeanWithGetterException.class)).get();
427+
assertThat(result.getValues()).containsExactly("a", "b", "c");
428+
}
429+
420430
public static class ExampleCollectionBean {
421431

422432
private List<String> items = new ArrayList<>();
@@ -521,4 +531,18 @@ public void setBar(String[] bar) {
521531

522532
}
523533

534+
public static class BeanWithGetterException {
535+
536+
private List<String> values;
537+
538+
public void setValues(List<String> values) {
539+
this.values = values;
540+
}
541+
542+
public List<String> getValues() {
543+
return Collections.unmodifiableList(this.values);
544+
}
545+
546+
}
547+
524548
}

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/MapBinderTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,16 @@ public void bindToImmutableMapShouldReturnPopulatedCollection() {
631631
entry("e", "f"));
632632
}
633633

634+
@Test
635+
public void bindToBeanWithExceptionInGetterForExistingValue() {
636+
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
637+
source.put("foo.values.a", "b");
638+
this.sources.add(source);
639+
BeanWithGetterException result = this.binder
640+
.bind("foo", Bindable.of(BeanWithGetterException.class)).get();
641+
assertThat(result.getValues()).containsExactly(entry("a", "b"));
642+
}
643+
634644
private <K, V> Bindable<Map<K, V>> getMapBindable(Class<K> keyGeneric,
635645
ResolvableType valueType) {
636646
ResolvableType keyType = ResolvableType.forClass(keyGeneric);
@@ -736,4 +746,18 @@ public static class MyCustomWithDefaultConstructorMap
736746

737747
}
738748

749+
public static class BeanWithGetterException {
750+
751+
private Map<String, String> values;
752+
753+
public void setValues(Map<String, String> values) {
754+
this.values = values;
755+
}
756+
757+
public Map<String, String> getValues() {
758+
return Collections.unmodifiableMap(this.values);
759+
}
760+
761+
}
762+
739763
}

0 commit comments

Comments
 (0)