Restore binding of system environment using legacy names
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Remove `Binder` optimization introduced in commit 8f14dca164
so that
legacy format names in environment variables can be used again.
Fixes gh-46184
This commit is contained in:
parent
a06ce997a1
commit
6fe696b5cf
|
@ -107,7 +107,6 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
||||||
AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
|
AggregateElementBinder elementBinder, IndexedCollectionSupplier collection, ResolvableType elementType) {
|
||||||
Set<String> knownIndexedChildren = Collections.emptySet();
|
Set<String> knownIndexedChildren = Collections.emptySet();
|
||||||
if (source instanceof IterableConfigurationPropertySource iterableSource) {
|
if (source instanceof IterableConfigurationPropertySource iterableSource) {
|
||||||
source = iterableSource.filter(root::isAncestorOf);
|
|
||||||
knownIndexedChildren = getKnownIndexedChildren(iterableSource, root);
|
knownIndexedChildren = getKnownIndexedChildren(iterableSource, root);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < Integer.MAX_VALUE; i++) {
|
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) {
|
ConfigurationPropertyName root) {
|
||||||
Set<String> knownIndexedChildren = new HashSet<>();
|
Set<String> knownIndexedChildren = new HashSet<>();
|
||||||
for (ConfigurationPropertyName name : filteredSource) {
|
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
|
||||||
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
||||||
if (choppedName.isLastElementIndexed()) {
|
if (choppedName.isLastElementIndexed()) {
|
||||||
knownIndexedChildren.add(choppedName.getLastElement(Form.UNIFORM));
|
knownIndexedChildren.add(choppedName.getLastElement(Form.UNIFORM));
|
||||||
|
@ -136,17 +135,17 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
||||||
return knownIndexedChildren;
|
return knownIndexedChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren,
|
private void assertNoUnboundChildren(Set<String> unboundIndexedChildren, IterableConfigurationPropertySource source,
|
||||||
IterableConfigurationPropertySource filteredSource, ConfigurationPropertyName root) {
|
ConfigurationPropertyName root) {
|
||||||
if (unboundIndexedChildren.isEmpty()) {
|
if (unboundIndexedChildren.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<ConfigurationProperty> unboundProperties = new TreeSet<>();
|
Set<ConfigurationProperty> unboundProperties = new TreeSet<>();
|
||||||
for (ConfigurationPropertyName name : filteredSource) {
|
for (ConfigurationPropertyName name : source.filter(root::isAncestorOf)) {
|
||||||
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
ConfigurationPropertyName choppedName = name.chop(root.getNumberOfElements() + 1);
|
||||||
if (choppedName.isLastElementIndexed()
|
if (choppedName.isLastElementIndexed()
|
||||||
&& unboundIndexedChildren.contains(choppedName.getLastElement(Form.UNIFORM))) {
|
&& unboundIndexedChildren.contains(choppedName.getLastElement(Form.UNIFORM))) {
|
||||||
unboundProperties.add(filteredSource.getConfigurationProperty(name));
|
unboundProperties.add(source.getConfigurationProperty(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!unboundProperties.isEmpty()) {
|
if (!unboundProperties.isEmpty()) {
|
||||||
|
|
|
@ -19,9 +19,11 @@ package org.springframework.boot.context.properties.bind;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
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.boot.context.properties.source.MockConfigurationPropertySource;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
import org.springframework.core.env.SystemEnvironmentPropertySource;
|
||||||
import org.springframework.test.context.support.TestPropertySourceUtils;
|
import org.springframework.test.context.support.TestPropertySourceUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
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);
|
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 {
|
static class ExampleCollectionBean {
|
||||||
|
|
||||||
private final List<String> items = new ArrayList<>();
|
private final List<String> items = new ArrayList<>();
|
||||||
|
@ -607,6 +640,10 @@ class CollectionBinderTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record BeanWithCamelCaseNameList(List<Name> theNames) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
record Name(String first, String last) {
|
record Name(String first, String last) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue