commit
fe049e6570
|
@ -107,7 +107,6 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
|||
AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
|
||||
Set<String> knownIndexedChildren = Collections.emptySet();
|
||||
if (source instanceof IterableConfigurationPropertySource iterableSource) {
|
||||
source = iterableSource.filter(root::isAncestorOf);
|
||||
knownIndexedChildren = getKnownIndexedChildren(iterableSource, root);
|
||||
}
|
||||
for (int i = 0; i < Integer.MAX_VALUE; i++) {
|
||||
|
@ -124,10 +123,10 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
|||
}
|
||||
}
|
||||
|
||||
private Set<String> getKnownIndexedChildren(IterableConfigurationPropertySource filteredSource,
|
||||
private Set<String> getKnownIndexedChildren(IterableConfigurationPropertySource source,
|
||||
ConfigurationPropertyName root) {
|
||||
Set<String> knownIndexedChildren = new HashSet<>();
|
||||
for (ConfigurationPropertyName name : filteredSource) {
|
||||
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
|
||||
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
||||
if (choppedName.isLastElementIndexed()) {
|
||||
knownIndexedChildren.add(choppedName.getLastElement(Form.UNIFORM));
|
||||
|
@ -136,17 +135,17 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
|||
return knownIndexedChildren;
|
||||
}
|
||||
|
||||
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren,
|
||||
IterableConfigurationPropertySource filteredSource, ConfigurationPropertyName root) {
|
||||
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren, IterableConfigurationPropertySource source,
|
||||
ConfigurationPropertyName root) {
|
||||
if (unboundIndexedChildren.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Set<ConfigurationProperty> unboundProperties = new TreeSet<>();
|
||||
for (ConfigurationPropertyName name : filteredSource) {
|
||||
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
|
||||
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
||||
if (choppedName.isLastElementIndexed()
|
||||
&& unboundIndexedChildren.contains(choppedName.getLastElement(Form.UNIFORM))) {
|
||||
unboundProperties.add(filteredSource.getConfigurationProperty(name));
|
||||
unboundProperties.add(source.getConfigurationProperty(name));
|
||||
}
|
||||
}
|
||||
if (!unboundProperties.isEmpty()) {
|
||||
|
|
|
@ -19,9 +19,11 @@ package org.springframework.boot.context.properties.bind;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -33,6 +35,7 @@ import org.springframework.boot.context.properties.source.ConfigurationPropertyS
|
|||
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||
import org.springframework.test.context.support.TestPropertySourceUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -465,6 +468,36 @@ class CollectionBinderTests {
|
|||
assertThat(result.getValues().get(0)).containsExactly(ExampleEnum.FOO_BAR, ExampleEnum.BAR_BAZ);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToWellFormedSystemEnvironmentVariableProperty() {
|
||||
// gh-46184
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("FOO_THENAMES_0_FIRST", "spring");
|
||||
map.put("FOO_THENAMES_0_LAST", "boot");
|
||||
map.put("FOO_THENAMES_1_FIRST", "binding");
|
||||
map.put("FOO_THENAMES_1_LAST", "test");
|
||||
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, map);
|
||||
this.sources.add(ConfigurationPropertySource.from(propertySource));
|
||||
BeanWithCamelCaseNameList result = this.binder.bind("foo", BeanWithCamelCaseNameList.class).get();
|
||||
assertThat(result.theNames()).containsExactly(new Name("spring", "boot"), new Name("binding", "test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToLegacySystemEnvironmentVariableProperty() {
|
||||
// gh-46184
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("FOO_THE_NAMES_0_FIRST", "spring");
|
||||
map.put("FOO_THE_NAMES_0_LAST", "boot");
|
||||
map.put("FOO_THE_NAMES_1_FIRST", "binding");
|
||||
map.put("FOO_THE_NAMES_1_LAST", "test");
|
||||
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
|
||||
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, map);
|
||||
this.sources.add(ConfigurationPropertySource.from(propertySource));
|
||||
BeanWithCamelCaseNameList result = this.binder.bind("foo", BeanWithCamelCaseNameList.class).get();
|
||||
assertThat(result.theNames()).containsExactly(new Name("spring", "boot"), new Name("binding", "test"));
|
||||
}
|
||||
|
||||
static class ExampleCollectionBean {
|
||||
|
||||
private final List<String> items = new ArrayList<>();
|
||||
|
@ -607,6 +640,10 @@ class CollectionBinderTests {
|
|||
|
||||
}
|
||||
|
||||
record BeanWithCamelCaseNameList(List<Name> theNames) {
|
||||
|
||||
}
|
||||
|
||||
record Name(String first, String last) {
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue