Skip to content

Commit 256ca68

Browse files
chang-chaophilwebb
authored andcommitted
Consider aliases when checking descendants
Update `AliasedConfigurationPropertySource` to consider aliases in `containsDescendantOf`. Prior to this commit, given a source containing `example.name` with a defined alias of `other.name -> example.name` calling `containsDescendantOf("other")` would incorrectly return `ConfigurationPropertyState.ABSENT`. Closes gh-14967
1 parent 7bb6df4 commit 256ca68

File tree

3 files changed

+43
-6
lines changed

3 files changed

+43
-6
lines changed

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.context.properties.source;
1818

19+
import java.util.Set;
20+
1921
import org.springframework.util.Assert;
2022

2123
/**
@@ -58,11 +60,17 @@ public ConfigurationPropertyState containsDescendantOf(
5860
if (result != ConfigurationPropertyState.ABSENT) {
5961
return result;
6062
}
61-
for (ConfigurationPropertyName alias : getAliases().getAliases(name)) {
62-
ConfigurationPropertyState aliasResult = this.source
63-
.containsDescendantOf(alias);
64-
if (aliasResult != ConfigurationPropertyState.ABSENT) {
65-
return aliasResult;
63+
Set<ConfigurationPropertyName> aliasNames = this.aliases.getAllNames();
64+
for (ConfigurationPropertyName configurationPropertyName : aliasNames) {
65+
boolean descendantPresentInAlias = this.aliases
66+
.getAliases(configurationPropertyName).stream()
67+
.filter(name::isAncestorOf).findFirst().isPresent();
68+
if (descendantPresentInAlias) {
69+
ConfigurationProperty configurationProperty = this.getSource()
70+
.getConfigurationProperty(configurationPropertyName);
71+
if (configurationProperty != null) {
72+
return ConfigurationPropertyState.PRESENT;
73+
}
6674
}
6775
}
6876
return ConfigurationPropertyState.ABSENT;

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Collections;
2121
import java.util.List;
2222
import java.util.Map;
23+
import java.util.Set;
2324

2425
import org.springframework.util.Assert;
2526
import org.springframework.util.LinkedMultiValueMap;
@@ -74,4 +75,8 @@ public ConfigurationPropertyName getNameForAlias(ConfigurationPropertyName alias
7475
.findFirst().orElse(null);
7576
}
7677

78+
public Set<ConfigurationPropertyName> getAllNames() {
79+
return this.aliases.keySet();
80+
}
81+
7782
}

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.junit.Test;
2020
import org.mockito.Answers;
2121

22+
import org.springframework.boot.origin.Origin;
23+
2224
import static org.assertj.core.api.Assertions.assertThat;
2325
import static org.mockito.BDDMockito.given;
2426
import static org.mockito.Mockito.mock;
@@ -105,8 +107,30 @@ public void containsDescendantOfWhenAnyIsPresentShouldReturnPresent() {
105107
.willReturn(ConfigurationPropertyState.ABSENT);
106108
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
107109
.willReturn(ConfigurationPropertyState.PRESENT);
110+
ConfigurationPropertyName barBar = ConfigurationPropertyName.of("bar.bar");
111+
given(source.getConfigurationProperty(barBar)).willReturn(
112+
new ConfigurationProperty(barBar, "barBarValue", mock(Origin.class)));
108113
ConfigurationPropertySource aliased = source
109-
.withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
114+
.withAliases(new ConfigurationPropertyNameAliases("bar.bar", "foo.foo"));
115+
assertThat(aliased.containsDescendantOf(name))
116+
.isEqualTo(ConfigurationPropertyState.PRESENT);
117+
}
118+
119+
@Test
120+
public void containsDescendantOfWhenPresentInAliasShouldReturnPresent() {
121+
ConfigurationPropertyName name = ConfigurationPropertyName.of("baz");
122+
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class,
123+
withSettings().defaultAnswer(Answers.CALLS_REAL_METHODS));
124+
given(source.containsDescendantOf(name))
125+
.willReturn(ConfigurationPropertyState.ABSENT);
126+
127+
ConfigurationPropertyName barFoo = ConfigurationPropertyName.of("bar.foo");
128+
129+
given(source.getConfigurationProperty(barFoo)).willReturn(
130+
new ConfigurationProperty(barFoo, "barFooValue", mock(Origin.class)));
131+
132+
ConfigurationPropertySource aliased = source
133+
.withAliases(new ConfigurationPropertyNameAliases("bar.foo", "baz.foo"));
110134
assertThat(aliased.containsDescendantOf(name))
111135
.isEqualTo(ConfigurationPropertyState.PRESENT);
112136
}

0 commit comments

Comments
 (0)