Skip to content

Commit 9068fc3

Browse files
committed
Support binding Maps with updated MapPropertySource
In spring-boot 2x `Maps` in `@ConfigurationProperties` are not being updated from the **second** `EnvironmentChangeEvent` onwards. i.e. Following test fails in spring-boot 2x, but passed in spring-boot 1x. - In case of `MapPropertySource`, `SpringIterableConfigurationPropertySource#getCacheKey()` [here](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java#L146) always returns the reference to the same object in the heap (for different invocations), even though the property-source state has changed. i.e. <br/> `return ((MapPropertySource) getPropertySource()).getSource().keySet();` - As a result, `if (ObjectUtils.nullSafeEquals(cacheKey, this.cacheKey))` [here](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java#L136) always evaluates to true (same reference) and `getCache()` returns the old/ initial cache. Consequently, `SpringIterableConfigurationPropertySource#iterator()` having reference only to the initial/ old property-keys - hence the `MapBinder` fails [here](https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/MapBinder.java#L152) to bind updated properties.
1 parent 37a7457 commit 9068fc3

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySource.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,7 @@ private Cache getCache() {
142142
}
143143

144144
private Object getCacheKey() {
145-
if (getPropertySource() instanceof MapPropertySource) {
146-
return ((MapPropertySource) getPropertySource()).getSource().keySet();
147-
}
145+
// see gh-13344
148146
return getPropertySource().getPropertyNames();
149147
}
150148

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
* @author Andy Wilkinson
7777
* @author Stephane Nicoll
7878
* @author Ben Hale
79+
* @author Fahim Farook
7980
*/
8081
@RunWith(ModifiedClassPathRunner.class)
8182
@ClassPathExclusions("log4j*.jar")
@@ -500,12 +501,23 @@ public void systemPropertiesAreSetForLoggingConfiguration() {
500501
@Test
501502
public void environmentPropertiesIgnoreUnresolvablePlaceholders() {
502503
// gh-7719
504+
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
505+
"logging.pattern.console=console ${doesnotexist}");
506+
this.initializer.initialize(this.context.getEnvironment(),
507+
this.context.getClassLoader());
508+
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_PATTERN))
509+
.isEqualTo("console ${doesnotexist}");
510+
}
511+
512+
@Test
513+
public void environmentPropertiesResolvePlaceholders() {
503514
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
504515
"logging.pattern.console=console ${pid}");
505516
this.initializer.initialize(this.context.getEnvironment(),
506517
this.context.getClassLoader());
507518
assertThat(System.getProperty(LoggingSystemProperties.CONSOLE_LOG_PATTERN))
508-
.isEqualTo("console ${pid}");
519+
.isEqualTo(this.context.getEnvironment()
520+
.getProperty("logging.pattern.console"));
509521
}
510522

511523
@Test

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/source/SpringIterableConfigurationPropertySourceTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
*
3838
* @author Phillip Webb
3939
* @author Madhura Bhave
40+
* @author Fahim Farook
4041
*/
4142
public class SpringIterableConfigurationPropertySourceTests {
4243

@@ -157,6 +158,24 @@ public void containsDescendantOfShouldCheckSourceNames() {
157158
.isEqualTo(ConfigurationPropertyState.ABSENT);
158159
}
159160

161+
@SuppressWarnings("unchecked")
162+
@Test
163+
public void propertySourceChangeReflects() {
164+
// see gh-13344
165+
final Map<String, Object> source = new LinkedHashMap<>();
166+
source.put("key1", "value1");
167+
source.put("key2", "value2");
168+
final EnumerablePropertySource<?> propertySource = new MapPropertySource("test",
169+
source);
170+
final SpringIterableConfigurationPropertySource adapter = new SpringIterableConfigurationPropertySource(
171+
propertySource, DefaultPropertyMapper.INSTANCE);
172+
assertThat(adapter.stream().count()).isEqualTo(2);
173+
174+
((Map<String, Object>) adapter.getPropertySource().getSource()).put("key3",
175+
"value3");
176+
assertThat(adapter.stream().count()).isEqualTo(3);
177+
}
178+
160179
/**
161180
* Test {@link PropertySource} that's also an {@link OriginLookup}.
162181
*/

0 commit comments

Comments
 (0)