From f12d96886a5f4dac5db7786b6318d31c689fa1f8 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 9 Jun 2025 17:33:50 +0100 Subject: [PATCH 1/2] Test SpringIterableConfigurationPropertySource support lower case names Add a test to ensure that `SpringIterableConfigurationPropertySource` can support lower case names. See gh-45741 --- ...rableConfigurationPropertySourceTests.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java index 30c97f02e7f..03c3ac35cfa 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java @@ -152,10 +152,12 @@ class SpringIterableConfigurationPropertySourceTests { } @Test - void containsDescendantOfWhenSystemEnvironmentPropertySourceShouldLegacyProperty() { + void containsDescendantOfWhenSystemEnvironmentPropertySourceShouldSupportLegacyProperty() { Map source = new LinkedHashMap<>(); source.put("FOO_BAR_BAZ_BONG", "bing"); source.put("FOO_ALPHABRAVO_GAMMA", "delta"); + source.put("loo_bar_baz_bong", "bing"); + source.put("loo_alphabravo_gamma", "delta"); SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource( StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, source); SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource( @@ -166,6 +168,27 @@ class SpringIterableConfigurationPropertySourceTests { .isEqualTo(ConfigurationPropertyState.PRESENT); assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("foo.blah"))) .isEqualTo(ConfigurationPropertyState.ABSENT); + assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("loo.bar-baz"))) + .isEqualTo(ConfigurationPropertyState.PRESENT); + assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("loo.alpha-bravo"))) + .isEqualTo(ConfigurationPropertyState.PRESENT); + assertThat(adapter.containsDescendantOf(ConfigurationPropertyName.of("loo.blah"))) + .isEqualTo(ConfigurationPropertyState.ABSENT); + } + + @Test + void getConfigurationPropertyWhenSystemEnvironmentPropertySourceShouldSupportLegacyProperty() { + Map source = new LinkedHashMap<>(); + source.put("TEST_VALUE_UPPER", "upper"); + source.put("test_value_lower", "lower"); + SystemEnvironmentPropertySource propertySource = new SystemEnvironmentPropertySource( + StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, source); + SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource( + propertySource, SystemEnvironmentPropertyMapper.INSTANCE, DefaultPropertyMapper.INSTANCE); + assertThat(adapter.getConfigurationProperty(ConfigurationPropertyName.of("test.value-upper")).getValue()) + .isEqualTo("upper"); + assertThat(adapter.getConfigurationProperty(ConfigurationPropertyName.of("test.value-lower")).getValue()) + .isEqualTo("lower"); } @Test From bb13eaa83799fb071c6e12c83680bba01895f5b5 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 9 Jun 2025 17:51:17 +0100 Subject: [PATCH 2/2] Support lower case configuration properties system environment names Update `SystemEnvironmentPropertyMapper` to generate both mappings in both the original case and upper case. This restores the behavior of Spring Boot 3.4 where the system environment could contain lowercase names. Fixes gh-45741 --- .../source/ConfigurationPropertyName.java | 13 ++++++------- .../source/SpringConfigurationPropertySource.java | 4 +++- .../source/SystemEnvironmentPropertyMapper.java | 12 ++++-------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java index 87d237bc236..1604d4b364e 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/ConfigurationPropertyName.java @@ -543,25 +543,24 @@ public final class ConfigurationPropertyName implements Comparable buildDefaultToString(); - case SYSTEM_ENVIRONMENT -> - buildSimpleToString('_', (i) -> getElement(i, Form.UNIFORM).toUpperCase(Locale.ENGLISH)); - case LEGACY_SYSTEM_ENVIRONMENT -> buildSimpleToString('_', - (i) -> getElement(i, Form.ORIGINAL).replace('-', '_').toUpperCase(Locale.ENGLISH)); + case SYSTEM_ENVIRONMENT -> buildSimpleToString('_', (i) -> getElement(i, Form.UNIFORM)); + case LEGACY_SYSTEM_ENVIRONMENT -> + buildSimpleToString('_', (i) -> getElement(i, Form.ORIGINAL).replace('-', '_')); }; } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java index 7065a72a959..3cdd55eeef3 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringConfigurationPropertySource.java @@ -16,6 +16,7 @@ package org.springframework.boot.context.properties.source; +import java.util.Locale; import java.util.Map; import java.util.Random; @@ -109,7 +110,8 @@ class SpringConfigurationPropertySource implements ConfigurationPropertySource { } Object getSystemEnvironmentProperty(Map systemEnvironment, String name) { - return systemEnvironment.get(name); + Object value = systemEnvironment.get(name); + return (value != null) ? value : systemEnvironment.get(name.toLowerCase(Locale.ROOT)); } @Override diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java index 2a74e213074..b2e301dd59f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SystemEnvironmentPropertyMapper.java @@ -16,8 +16,6 @@ package org.springframework.boot.context.properties.source; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.function.BiPredicate; @@ -42,12 +40,10 @@ final class SystemEnvironmentPropertyMapper implements PropertyMapper { @Override public List map(ConfigurationPropertyName configurationPropertyName) { - String name = configurationPropertyName.toString(ToStringFormat.SYSTEM_ENVIRONMENT); - String legacyName = configurationPropertyName.toString(ToStringFormat.LEGACY_SYSTEM_ENVIRONMENT); - if (name.equals(legacyName)) { - return Collections.singletonList(name); - } - return Arrays.asList(name, legacyName); + return List.of(configurationPropertyName.toString(ToStringFormat.SYSTEM_ENVIRONMENT, true), + configurationPropertyName.toString(ToStringFormat.LEGACY_SYSTEM_ENVIRONMENT, true), + configurationPropertyName.toString(ToStringFormat.SYSTEM_ENVIRONMENT, false), + configurationPropertyName.toString(ToStringFormat.LEGACY_SYSTEM_ENVIRONMENT, false)); } @Override