Skip to content

Commit e1d21e5

Browse files
committed
Allow multi-value spring.profiles properties
Update `ConfigFileApplicationListener` to correctly load properties that have `spring.profiles` values containing a list. Prior to this commit the loaded would attempt to add the same document twice resulting in a "property source cannot be added relative to itself" error. Closes gh-13362
1 parent 67b548d commit e1d21e5

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.Collections;
2323
import java.util.Deque;
2424
import java.util.HashMap;
25+
import java.util.HashSet;
2526
import java.util.LinkedHashMap;
2627
import java.util.LinkedHashSet;
2728
import java.util.LinkedList;
@@ -656,27 +657,35 @@ private Set<String> asResolvedSet(String value, String fallback) {
656657

657658
private void addLoadedPropertySources() {
658659
MutablePropertySources destination = this.environment.getPropertySources();
659-
String lastAdded = null;
660660
List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
661661
Collections.reverse(loaded);
662+
String lastAdded = null;
663+
Set<String> added = new HashSet<>();
662664
for (MutablePropertySources sources : loaded) {
663665
for (PropertySource<?> source : sources) {
664-
if (lastAdded == null) {
665-
if (destination.contains(DEFAULT_PROPERTIES)) {
666-
destination.addBefore(DEFAULT_PROPERTIES, source);
667-
}
668-
else {
669-
destination.addLast(source);
670-
}
671-
}
672-
else {
673-
destination.addAfter(lastAdded, source);
666+
if (added.add(source.getName())) {
667+
addLoadedPropertySource(destination, lastAdded, source);
668+
lastAdded = source.getName();
674669
}
675-
lastAdded = source.getName();
676670
}
677671
}
678672
}
679673

674+
private void addLoadedPropertySource(MutablePropertySources destination,
675+
String lastAdded, PropertySource<?> source) {
676+
if (lastAdded == null) {
677+
if (destination.contains(DEFAULT_PROPERTIES)) {
678+
destination.addBefore(DEFAULT_PROPERTIES, source);
679+
}
680+
else {
681+
destination.addLast(source);
682+
}
683+
}
684+
else {
685+
destination.addAfter(lastAdded, source);
686+
}
687+
}
688+
680689
}
681690

682691
/**

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,18 @@ public void includeLoop() {
900900
this.context = application.run("--spring.config.name=applicationloop");
901901
ConfigurableEnvironment environment = this.context.getEnvironment();
902902
assertThat(environment.acceptsProfiles("loop")).isTrue();
903+
}
903904

905+
@Test
906+
public void multiValueSpringProfiles() {
907+
// gh-13362
908+
SpringApplication application = new SpringApplication(Config.class);
909+
application.setWebApplicationType(WebApplicationType.NONE);
910+
this.context = application.run("--spring.config.name=applicationmultiprofiles");
911+
ConfigurableEnvironment environment = this.context.getEnvironment();
912+
assertThat(environment.acceptsProfiles("test")).isTrue();
913+
assertThat(environment.acceptsProfiles("another-test")).isTrue();
914+
assertThat(environment.getProperty("message")).isEqualTo("multiprofile");
904915
}
905916

906917
private Condition<ConfigurableEnvironment> matchingPropertySource(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
spring.profiles.active: test, another-test
2+
message: default
3+
---
4+
spring:
5+
profiles: test,another-test
6+
message: multiprofile

0 commit comments

Comments
 (0)