From 6ddbf3bd92d189d072c73458b20cfd7c8d926215 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 4 Feb 2014 14:06:02 -0800 Subject: [PATCH] Restore active profile logic and support `+` Restore the previous `spring.profiles.active` logic effectively reverting commit 37069d9. This ensures that active profiles defined in a higher `PropertySource` replace those lower down. In addition, add support for a `+` prefix that can be used to indicate that a profile should be added to the active set. For example: # application-prod.properties spring.profiles.active=+proddb,+prodmq Fixed gh-308, gh-309 --- docs/howto.md | 3 +- spring-boot/README.md | 22 +++++++++++- .../ConfigFileApplicationListener.java | 36 +++++++++++++------ .../ConfigFileApplicationListenerTests.java | 8 +++-- .../application-activateprofile.properties | 2 +- .../application-morespecific.properties | 1 + .../resources/application-specific.properties | 1 + .../enableprofileviaapplicationproperties.yml | 2 +- 8 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 spring-boot/src/test/resources/application-morespecific.properties create mode 100644 spring-boot/src/test/resources/application-specific.properties diff --git a/docs/howto.md b/docs/howto.md index c3079daa800..3f14a9baf34 100644 --- a/docs/howto.md +++ b/docs/howto.md @@ -894,7 +894,7 @@ In Spring Boot you can also set the active profile in `application.properties`, e.g. ```properties -spring.profiles.active: production +spring.profiles.active=production ``` A value set this way is replaced by the System property or environment @@ -902,6 +902,7 @@ variable setting, but not by the `SpringApplicationBuilder.profiles()` method. Thus the latter Java API can be used to augment the profiles without changing the defaults. + ## Change the Location of External Properties of an Application By default properties from different sources are added to the Spring diff --git a/spring-boot/README.md b/spring-boot/README.md index 606efd783e8..103e15ab82c 100644 --- a/spring-boot/README.md +++ b/spring-boot/README.md @@ -157,6 +157,26 @@ spring.profiles.active=dev,hsqldb or specify on the command line using the switch `--spring.profiles.active=dev,hsqldb`. +#### Adding active profiles +The `spring.profiles.active` property follows the same ordering rules as other +properties, the highest `PropertySource` will win. This means that you can specify +active profiles in `application.properties` then **replace** them using the command line +switch. + +Sometimes it is useful to have profile specific properties that **add** to the active +profiles rather than replace them. The `+` prefix can be used to add active profiles. + +For example, when an application with following properties is run using the switch +`--spring.profiles.active=prod` the `proddb` and `prodmq` profiles will also be activated: + +```yaml +--- +my.property: fromyamlfile +--- +spring.profiles: prod +spring.profiles.active: +proddb,+prodmq +``` + ### Application Context Initializers Spring provides a convenient `ApplicationContextInitializer` interface that can be used to customize an `ApplicationContext` before it is used. If you need to use an initializer @@ -451,7 +471,7 @@ to specify: * The Tomcat `base directory` (`server.tomcat.basedir`) ## Customizing Logging -Spring Boot uses [Commons Logging](commons.apache.org/logging/‎) for all internal logging, +Spring Boot uses [Commons Logging](commons.apache.org/logging) for all internal logging, but leaves the underlying log implementation open. Default configurations are provided for [Java Util Logging](http://docs.oracle.com/javase/7/docs/api/java/util/logging/package-summary.html), [Log4J](http://logging.apache.org/log4j/) and [Logback](http://logback.qos.ch/). diff --git a/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java index 4dbf87f472e..eefedd4c1de 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/listener/ConfigFileApplicationListener.java @@ -147,15 +147,24 @@ public class ConfigFileApplicationListener implements PropertySource defaultProperties = environment.getPropertySources().remove( "defaultProperties"); - addActiveProfiles(environment); + // Load to allow a file that defines active profiles to be considered String firstPropertySourceName = loadInitial(environment, resourceLoader, candidates); + // Apply the active profiles (if any) from the first property source + if (environment.containsProperty(ACTIVE_PROFILES_PROPERTY)) { + activeProfilesFromProperty(environment, + environment.getProperty(ACTIVE_PROFILES_PROPERTY), true); + } + + // Apply any profile additions from any source + activeProfileAdditionsFromAnySource(environment); + // Repeatedly load property sources in case additional profiles are activated int numberOfPropertySources; do { numberOfPropertySources = environment.getPropertySources().size(); - addActiveProfiles(environment); + activeProfileAdditionsFromAnySource(environment); loadAgain(environment, resourceLoader, candidates, firstPropertySourceName); } while (environment.getPropertySources().size() > numberOfPropertySources); @@ -165,17 +174,22 @@ public class ConfigFileApplicationListener implements } } - /** - * @param environment - */ - private void addActiveProfiles(ConfigurableEnvironment environment) { + private void activeProfileAdditionsFromAnySource(ConfigurableEnvironment environment) { for (PropertySource propertySource : environment.getPropertySources()) { if (propertySource.containsProperty(ACTIVE_PROFILES_PROPERTY)) { - Object profiles = propertySource.getProperty(ACTIVE_PROFILES_PROPERTY); - for (String profile : StringUtils.commaDelimitedListToSet(profiles - .toString())) { - environment.addActiveProfile(profile); - } + activeProfilesFromProperty(environment, + propertySource.getProperty(ACTIVE_PROFILES_PROPERTY), false); + } + } + } + + private void activeProfilesFromProperty(ConfigurableEnvironment environment, + Object property, boolean addAll) { + for (String profile : StringUtils.commaDelimitedListToSet(property.toString())) { + boolean addition = profile.startsWith("+"); + profile = (addition ? profile.substring(1) : profile); + if (addAll || addition) { + environment.addActiveProfile(profile); } } } diff --git a/spring-boot/src/test/java/org/springframework/boot/context/listener/ConfigFileApplicationListenerTests.java b/spring-boot/src/test/java/org/springframework/boot/context/listener/ConfigFileApplicationListenerTests.java index aacb82f6539..250a4032c29 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/listener/ConfigFileApplicationListenerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/listener/ConfigFileApplicationListenerTests.java @@ -186,8 +186,7 @@ public class ConfigFileApplicationListenerTests { "spring.profiles.active:prod"); this.initializer.setNames("testsetprofiles"); this.initializer.onApplicationEvent(this.event); - assertThat(this.environment.getActiveProfiles(), equalTo(new String[] { "prod", - "dev" })); + assertThat(this.environment.getActiveProfiles(), equalTo(new String[] { "prod" })); } @Test @@ -356,6 +355,11 @@ public class ConfigFileApplicationListenerTests { assertThat(context.getEnvironment().acceptsProfiles("activateprofile"), equalTo(true)); assertThat(context.getEnvironment().acceptsProfiles("specific"), equalTo(true)); + assertThat(context.getEnvironment().acceptsProfiles("morespecific"), + equalTo(true)); + assertThat(context.getEnvironment().acceptsProfiles("yetmorespecific"), + equalTo(true)); + assertThat(context.getEnvironment().acceptsProfiles("missing"), equalTo(false)); } @Test diff --git a/spring-boot/src/test/resources/application-activateprofile.properties b/spring-boot/src/test/resources/application-activateprofile.properties index 42970aaa301..3fad5d00432 100644 --- a/spring-boot/src/test/resources/application-activateprofile.properties +++ b/spring-boot/src/test/resources/application-activateprofile.properties @@ -1 +1 @@ -spring.profiles.active=specific +spring.profiles.active=+specific diff --git a/spring-boot/src/test/resources/application-morespecific.properties b/spring-boot/src/test/resources/application-morespecific.properties new file mode 100644 index 00000000000..0d1f6ccb978 --- /dev/null +++ b/spring-boot/src/test/resources/application-morespecific.properties @@ -0,0 +1 @@ +spring.profiles.active=+yetmorespecific,missing diff --git a/spring-boot/src/test/resources/application-specific.properties b/spring-boot/src/test/resources/application-specific.properties new file mode 100644 index 00000000000..51cf719b6bc --- /dev/null +++ b/spring-boot/src/test/resources/application-specific.properties @@ -0,0 +1 @@ +spring.profiles.active=+morespecific diff --git a/spring-boot/src/test/resources/enableprofileviaapplicationproperties.yml b/spring-boot/src/test/resources/enableprofileviaapplicationproperties.yml index afdf33c9b0e..74f7f5b6f15 100644 --- a/spring-boot/src/test/resources/enableprofileviaapplicationproperties.yml +++ b/spring-boot/src/test/resources/enableprofileviaapplicationproperties.yml @@ -1,3 +1,3 @@ spring: profiles: - active: a \ No newline at end of file + active: +a