Skip to content

Commit 817debb

Browse files
committed
Fix constructor binding with conversion to custom collection type
Closes gh-37734
1 parent 7d6532c commit 817debb

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,11 @@ class CollectionBinder extends IndexedElementsBinder<Collection<Object>> {
4040
@Override
4141
protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> target,
4242
AggregateElementBinder elementBinder) {
43-
Class<?> collectionType = (target.getValue() != null) ? List.class : target.getType().resolve(Object.class);
4443
ResolvableType aggregateType = ResolvableType.forClassWithGenerics(List.class,
4544
target.getType().asCollection().getGenerics());
4645
ResolvableType elementType = target.getType().asCollection().getGeneric();
4746
IndexedCollectionSupplier result = new IndexedCollectionSupplier(
48-
() -> CollectionFactory.createCollection(collectionType, elementType.resolve(), 0));
47+
() -> CollectionFactory.createCollection(List.class, elementType.resolve(), 0));
4948
bindIndexed(name, target, elementBinder, aggregateType, elementType, result);
5049
if (result.wasSupplied()) {
5150
return result.get();

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

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,19 @@ void loadWhenBindingWithCustomConverterAndObjectToObjectMethod() {
11171117
assertThat(bean.getItem().getValue()).isEqualTo("foo");
11181118
}
11191119

1120+
@Test
1121+
void loadWhenBindingToConstructorParametersWithConversionToCustomListImplementation() {
1122+
load(ConstructorBoundCustomListPropertiesConfiguration.class, "test.values=a,b");
1123+
assertThat(this.context.getBean(ConstructorBoundCustomListProperties.class).getValues()).containsExactly("a",
1124+
"b");
1125+
}
1126+
1127+
@Test
1128+
void loadWhenBindingToJavaBeanWithConversionToCustomListImplementation() {
1129+
load(SetterBoundCustomListPropertiesConfiguration.class, "test.values=a,b");
1130+
assertThat(this.context.getBean(SetterBoundCustomListProperties.class).getValues()).containsExactly("a", "b");
1131+
}
1132+
11201133
private AnnotationConfigApplicationContext load(Class<?> configuration, String... inlinedProperties) {
11211134
return load(new Class<?>[] { configuration }, inlinedProperties);
11221135
}
@@ -2857,4 +2870,83 @@ public WithPublicObjectToObjectMethod convert(String source) {
28572870

28582871
}
28592872

2873+
@Configuration(proxyBeanMethods = false)
2874+
@EnableConfigurationProperties(ConstructorBoundCustomListProperties.class)
2875+
static class ConstructorBoundCustomListPropertiesConfiguration {
2876+
2877+
@Bean
2878+
@ConfigurationPropertiesBinding
2879+
static Converter<ArrayList<?>, CustomList<?>> arrayListToCustomList() {
2880+
return new Converter<ArrayList<?>, CustomList<?>>() {
2881+
2882+
@Override
2883+
public CustomList<?> convert(ArrayList<?> source) {
2884+
return new CustomList<>(source);
2885+
}
2886+
2887+
};
2888+
2889+
}
2890+
2891+
}
2892+
2893+
@ConstructorBinding
2894+
@ConfigurationProperties("test")
2895+
static class ConstructorBoundCustomListProperties {
2896+
2897+
private final CustomList<String> values;
2898+
2899+
ConstructorBoundCustomListProperties(CustomList<String> values) {
2900+
this.values = values;
2901+
}
2902+
2903+
CustomList<String> getValues() {
2904+
return this.values;
2905+
}
2906+
2907+
}
2908+
2909+
@Configuration(proxyBeanMethods = false)
2910+
@EnableConfigurationProperties(SetterBoundCustomListProperties.class)
2911+
static class SetterBoundCustomListPropertiesConfiguration {
2912+
2913+
@Bean
2914+
@ConfigurationPropertiesBinding
2915+
static Converter<ArrayList<?>, CustomList<?>> arrayListToCustomList() {
2916+
return new Converter<ArrayList<?>, CustomList<?>>() {
2917+
2918+
@Override
2919+
public CustomList<?> convert(ArrayList<?> source) {
2920+
return new CustomList<>(source);
2921+
}
2922+
2923+
};
2924+
2925+
}
2926+
2927+
}
2928+
2929+
@ConfigurationProperties("test")
2930+
static class SetterBoundCustomListProperties {
2931+
2932+
private CustomList<String> values;
2933+
2934+
CustomList<String> getValues() {
2935+
return this.values;
2936+
}
2937+
2938+
void setValues(CustomList<String> values) {
2939+
this.values = values;
2940+
}
2941+
2942+
}
2943+
2944+
static final class CustomList<E> extends ArrayList<E> {
2945+
2946+
CustomList(List<E> delegate) {
2947+
super(delegate);
2948+
}
2949+
2950+
}
2951+
28602952
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy