From 8528f7c140811bce3dc8d4a9c2bbe8ffe972c708 Mon Sep 17 00:00:00 2001 From: Madhura Bhave Date: Fri, 8 Feb 2019 09:51:30 -0800 Subject: [PATCH] Make spring.profiles.include behave consistently Previously, if profiles were included via a property source with higher precedence than config files, profiles activated via config files would not be taken into account. This commit makes spring.profiles.include behave consistently where it adds to active profiles rather than replacing them, regardless of property source. Fixes gh-15344 --- .../config/ConfigFileApplicationListener.java | 27 +++++++++++-------- .../ConfigFileApplicationListenerTests.java | 10 +++++++ .../resources/application-simple.properties | 1 + 3 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/test/resources/application-simple.properties diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java index 1ba833ba2d..296abc5642 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java @@ -348,10 +348,16 @@ public class ConfigFileApplicationListener // The default profile for these purposes is represented as null. We add it // first so that it is processed first and has lowest priority. this.profiles.add(null); - Set activatedViaProperty = getProfilesActivatedViaProperty(); - this.profiles.addAll(getOtherActiveProfiles(activatedViaProperty)); + Set activatedViaProperty = getProfilesFromProperty( + ACTIVE_PROFILES_PROPERTY); + Set includedViaProperty = getProfilesFromProperty( + INCLUDE_PROFILES_PROPERTY); + List otherActiveProfiles = getOtherActiveProfiles( + activatedViaProperty, includedViaProperty); + this.profiles.addAll(otherActiveProfiles); // Any pre-existing active profiles set via property sources (e.g. // System properties) take precedence over those added in config files. + this.profiles.addAll(includedViaProperty); addActiveProfiles(activatedViaProperty); if (this.profiles.size() == 1) { // only has null profile for (String defaultProfileName : this.environment.getDefaultProfiles()) { @@ -361,21 +367,20 @@ public class ConfigFileApplicationListener } } - private Set getProfilesActivatedViaProperty() { - if (!this.environment.containsProperty(ACTIVE_PROFILES_PROPERTY) - && !this.environment.containsProperty(INCLUDE_PROFILES_PROPERTY)) { + private Set getProfilesFromProperty(String profilesProperty) { + if (!this.environment.containsProperty(profilesProperty)) { return Collections.emptySet(); } Binder binder = Binder.get(this.environment); - Set activeProfiles = new LinkedHashSet<>(); - activeProfiles.addAll(getProfiles(binder, INCLUDE_PROFILES_PROPERTY)); - activeProfiles.addAll(getProfiles(binder, ACTIVE_PROFILES_PROPERTY)); - return activeProfiles; + Set profiles = getProfiles(binder, profilesProperty); + return new LinkedHashSet<>(profiles); } - private List getOtherActiveProfiles(Set activatedViaProperty) { + private List getOtherActiveProfiles(Set activatedViaProperty, + Set includedViaProperty) { return Arrays.stream(this.environment.getActiveProfiles()).map(Profile::new) - .filter((profile) -> !activatedViaProperty.contains(profile)) + .filter((profile) -> !activatedViaProperty.contains(profile) + && !includedViaProperty.contains(profile)) .collect(Collectors.toList()); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java index f3c77d28b6..496aa5312a 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java @@ -412,6 +412,16 @@ public class ConfigFileApplicationListenerTests { validateProfilePrecedence(null, "other", "dev"); } + @Test + public void profilesAddedViaIncludePropertyAndActivatedViaAnotherPropertySource() { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, + "spring.profiles.include=dev,simple"); + this.initializer.postProcessEnvironment(this.environment, this.application); + assertThat(this.environment.getActiveProfiles()).containsExactly("dev", "simple", + "other"); + validateProfilePrecedence("dev", "simple", "other"); + } + @Test public void profilesAddedToEnvironmentAndViaPropertyDuplicate() { TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, diff --git a/spring-boot-project/spring-boot/src/test/resources/application-simple.properties b/spring-boot-project/spring-boot/src/test/resources/application-simple.properties new file mode 100644 index 0000000000..228e3f38c3 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/application-simple.properties @@ -0,0 +1 @@ +spring.profiles.active=other