Browse Source

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
pull/13388/head
Phillip Webb 8 years ago
parent
commit
e1d21e52d5
  1. 33
      spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java
  2. 11
      spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java
  3. 6
      spring-boot-project/spring-boot/src/test/resources/applicationmultiprofiles.yml

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

@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
@ -656,27 +657,35 @@ public class ConfigFileApplicationListener
private void addLoadedPropertySources() { private void addLoadedPropertySources() {
MutablePropertySources destination = this.environment.getPropertySources(); MutablePropertySources destination = this.environment.getPropertySources();
String lastAdded = null;
List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values()); List<MutablePropertySources> loaded = new ArrayList<>(this.loaded.values());
Collections.reverse(loaded); Collections.reverse(loaded);
String lastAdded = null;
Set<String> added = new HashSet<>();
for (MutablePropertySources sources : loaded) { for (MutablePropertySources sources : loaded) {
for (PropertySource<?> source : sources) { for (PropertySource<?> source : sources) {
if (lastAdded == null) { if (added.add(source.getName())) {
if (destination.contains(DEFAULT_PROPERTIES)) { addLoadedPropertySource(destination, lastAdded, source);
destination.addBefore(DEFAULT_PROPERTIES, source); lastAdded = source.getName();
}
else {
destination.addLast(source);
}
}
else {
destination.addAfter(lastAdded, source);
} }
lastAdded = source.getName();
} }
} }
} }
private void addLoadedPropertySource(MutablePropertySources destination,
String lastAdded, PropertySource<?> source) {
if (lastAdded == null) {
if (destination.contains(DEFAULT_PROPERTIES)) {
destination.addBefore(DEFAULT_PROPERTIES, source);
}
else {
destination.addLast(source);
}
}
else {
destination.addAfter(lastAdded, source);
}
}
} }
/** /**

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

@ -900,7 +900,18 @@ public class ConfigFileApplicationListenerTests {
this.context = application.run("--spring.config.name=applicationloop"); this.context = application.run("--spring.config.name=applicationloop");
ConfigurableEnvironment environment = this.context.getEnvironment(); ConfigurableEnvironment environment = this.context.getEnvironment();
assertThat(environment.acceptsProfiles("loop")).isTrue(); assertThat(environment.acceptsProfiles("loop")).isTrue();
}
@Test
public void multiValueSpringProfiles() {
// gh-13362
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.config.name=applicationmultiprofiles");
ConfigurableEnvironment environment = this.context.getEnvironment();
assertThat(environment.acceptsProfiles("test")).isTrue();
assertThat(environment.acceptsProfiles("another-test")).isTrue();
assertThat(environment.getProperty("message")).isEqualTo("multiprofile");
} }
private Condition<ConfigurableEnvironment> matchingPropertySource( private Condition<ConfigurableEnvironment> matchingPropertySource(

6
spring-boot-project/spring-boot/src/test/resources/applicationmultiprofiles.yml

@ -0,0 +1,6 @@
spring.profiles.active: test, another-test
message: default
---
spring:
profiles: test,another-test
message: multiprofile
Loading…
Cancel
Save