Skip to content

Commit

Permalink
Fix constructor binding with conversion to custom collection type
Browse files Browse the repository at this point in the history
Closes gh-37734
  • Loading branch information
wilkinsona committed Oct 18, 2023
1 parent 7d6532c commit 817debb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ class CollectionBinder extends IndexedElementsBinder<Collection<Object>> {
@Override
protected Object bindAggregate(ConfigurationPropertyName name, Bindable<?> target,
AggregateElementBinder elementBinder) {
Class<?> collectionType = (target.getValue() != null) ? List.class : target.getType().resolve(Object.class);
ResolvableType aggregateType = ResolvableType.forClassWithGenerics(List.class,
target.getType().asCollection().getGenerics());
ResolvableType elementType = target.getType().asCollection().getGeneric();
IndexedCollectionSupplier result = new IndexedCollectionSupplier(
() -> CollectionFactory.createCollection(collectionType, elementType.resolve(), 0));
() -> CollectionFactory.createCollection(List.class, elementType.resolve(), 0));
bindIndexed(name, target, elementBinder, aggregateType, elementType, result);
if (result.wasSupplied()) {
return result.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,19 @@ void loadWhenBindingWithCustomConverterAndObjectToObjectMethod() {
assertThat(bean.getItem().getValue()).isEqualTo("foo");
}

@Test
void loadWhenBindingToConstructorParametersWithConversionToCustomListImplementation() {
load(ConstructorBoundCustomListPropertiesConfiguration.class, "test.values=a,b");
assertThat(this.context.getBean(ConstructorBoundCustomListProperties.class).getValues()).containsExactly("a",
"b");
}

@Test
void loadWhenBindingToJavaBeanWithConversionToCustomListImplementation() {
load(SetterBoundCustomListPropertiesConfiguration.class, "test.values=a,b");
assertThat(this.context.getBean(SetterBoundCustomListProperties.class).getValues()).containsExactly("a", "b");
}

private AnnotationConfigApplicationContext load(Class<?> configuration, String... inlinedProperties) {
return load(new Class<?>[] { configuration }, inlinedProperties);
}
Expand Down Expand Up @@ -2857,4 +2870,83 @@ public WithPublicObjectToObjectMethod convert(String source) {

}

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(ConstructorBoundCustomListProperties.class)
static class ConstructorBoundCustomListPropertiesConfiguration {

@Bean
@ConfigurationPropertiesBinding
static Converter<ArrayList<?>, CustomList<?>> arrayListToCustomList() {
return new Converter<ArrayList<?>, CustomList<?>>() {

@Override
public CustomList<?> convert(ArrayList<?> source) {
return new CustomList<>(source);
}

};

}

}

@ConstructorBinding
@ConfigurationProperties("test")
static class ConstructorBoundCustomListProperties {

private final CustomList<String> values;

ConstructorBoundCustomListProperties(CustomList<String> values) {
this.values = values;
}

CustomList<String> getValues() {
return this.values;
}

}

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SetterBoundCustomListProperties.class)
static class SetterBoundCustomListPropertiesConfiguration {

@Bean
@ConfigurationPropertiesBinding
static Converter<ArrayList<?>, CustomList<?>> arrayListToCustomList() {
return new Converter<ArrayList<?>, CustomList<?>>() {

@Override
public CustomList<?> convert(ArrayList<?> source) {
return new CustomList<>(source);
}

};

}

}

@ConfigurationProperties("test")
static class SetterBoundCustomListProperties {

private CustomList<String> values;

CustomList<String> getValues() {
return this.values;
}

void setValues(CustomList<String> values) {
this.values = values;
}

}

static final class CustomList<E> extends ArrayList<E> {

CustomList(List<E> delegate) {
super(delegate);
}

}

}

0 comments on commit 817debb

Please sign in to comment.