Skip to content

Commit fe049e6

Browse files
committed
Merge branch '3.5.x'
Fixes gh-46197
2 parents 1b1fa0b + 6fe696b commit fe049e6

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ private void bindIndexed(ConfigurationPropertySource source, ConfigurationProper
107107
AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
108108
Set<String> knownIndexedChildren = Collections.emptySet();
109109
if (source instanceof IterableConfigurationPropertySource iterableSource) {
110-
source = iterableSource.filter(root::isAncestorOf);
111110
knownIndexedChildren = getKnownIndexedChildren(iterableSource, root);
112111
}
113112
for (int i = 0; i < Integer.MAX_VALUE; i++) {
@@ -124,10 +123,10 @@ private void bindIndexed(ConfigurationPropertySource source, ConfigurationProper
124123
}
125124
}
126125

127-
private Set<String> getKnownIndexedChildren(IterableConfigurationPropertySource filteredSource,
126+
private Set<String> getKnownIndexedChildren(IterableConfigurationPropertySource source,
128127
ConfigurationPropertyName root) {
129128
Set<String> knownIndexedChildren = new HashSet<>();
130-
for (ConfigurationPropertyName name : filteredSource) {
129+
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
131130
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
132131
if (choppedName.isLastElementIndexed()) {
133132
knownIndexedChildren.add(choppedName.getLastElement(Form.UNIFORM));
@@ -136,17 +135,17 @@ private Set<String> getKnownIndexedChildren(IterableConfigurationPropertySource
136135
return knownIndexedChildren;
137136
}
138137

139-
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren,
140-
IterableConfigurationPropertySource filteredSource, ConfigurationPropertyName root) {
138+
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren, IterableConfigurationPropertySource source,
139+
ConfigurationPropertyName root) {
141140
if (unboundIndexedChildren.isEmpty()) {
142141
return;
143142
}
144143
Set<ConfigurationProperty> unboundProperties = new TreeSet<>();
145-
for (ConfigurationPropertyName name : filteredSource) {
144+
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
146145
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
147146
if (choppedName.isLastElementIndexed()
148147
&& unboundIndexedChildren.contains(choppedName.getLastElement(Form.UNIFORM))) {
149-
unboundProperties.add(filteredSource.getConfigurationProperty(name));
148+
unboundProperties.add(source.getConfigurationProperty(name));
150149
}
151150
}
152151
if (!unboundProperties.isEmpty()) {

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
import java.util.ArrayList;
2020
import java.util.Collections;
2121
import java.util.EnumSet;
22+
import java.util.LinkedHashMap;
2223
import java.util.LinkedHashSet;
2324
import java.util.LinkedList;
2425
import java.util.List;
26+
import java.util.Map;
2527
import java.util.Set;
2628

2729
import org.junit.jupiter.api.Test;
@@ -33,6 +35,7 @@
3335
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
3436
import org.springframework.core.ResolvableType;
3537
import org.springframework.core.env.StandardEnvironment;
38+
import org.springframework.core.env.SystemEnvironmentPropertySource;
3639
import org.springframework.test.context.support.TestPropertySourceUtils;
3740

3841
import static org.assertj.core.api.Assertions.assertThat;
@@ -465,6 +468,36 @@ void bindToBeanWithEnumSetCollection() {
465468
assertThat(result.getValues().get(0)).containsExactly(ExampleEnum.FOO_BAR, ExampleEnum.BAR_BAZ);
466469
}
467470

471+
@Test
472+
void bindToWellFormedSystemEnvironmentVariableProperty() {
473+
// gh-46184
474+
Map<String, Object> map = new LinkedHashMap<>();
475+
map.put("FOO_THENAMES_0_FIRST", "spring");
476+
map.put("FOO_THENAMES_0_LAST", "boot");
477+
map.put("FOO_THENAMES_1_FIRST", "binding");
478+
map.put("FOO_THENAMES_1_LAST", "test");
479+
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
480+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, map);
481+
this.sources.add(ConfigurationPropertySource.from(propertySource));
482+
BeanWithCamelCaseNameList result = this.binder.bind("foo", BeanWithCamelCaseNameList.class).get();
483+
assertThat(result.theNames()).containsExactly(new Name("spring", "boot"), new Name("binding", "test"));
484+
}
485+
486+
@Test
487+
void bindToLegacySystemEnvironmentVariableProperty() {
488+
// gh-46184
489+
Map<String, Object> map = new LinkedHashMap<>();
490+
map.put("FOO_THE_NAMES_0_FIRST", "spring");
491+
map.put("FOO_THE_NAMES_0_LAST", "boot");
492+
map.put("FOO_THE_NAMES_1_FIRST", "binding");
493+
map.put("FOO_THE_NAMES_1_LAST", "test");
494+
SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource(
495+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, map);
496+
this.sources.add(ConfigurationPropertySource.from(propertySource));
497+
BeanWithCamelCaseNameList result = this.binder.bind("foo", BeanWithCamelCaseNameList.class).get();
498+
assertThat(result.theNames()).containsExactly(new Name("spring", "boot"), new Name("binding", "test"));
499+
}
500+
468501
static class ExampleCollectionBean {
469502

470503
private final List<String> items = new ArrayList<>();
@@ -607,6 +640,10 @@ List<EnumSet<ExampleEnum>> getValues() {
607640

608641
}
609642

643+
record BeanWithCamelCaseNameList(List<Name> theNames) {
644+
645+
}
646+
610647
record Name(String first, String last) {
611648

612649
}

0 commit comments

Comments
 (0)