Fix spring.active.profiles repeated loading

Fix `ConfigFileApplicationListener` to repeatedly load property sources
and activate profiles using any defined `spring.active.profiles`
properties.

This restores the ability to have a property in a profile specific
file that defines additional profiles.

Fixes gh-308
This commit is contained in:
Phillip Webb 2014-02-03 23:36:56 -08:00
parent 0f083c2f9d
commit 37069d91d8
5 changed files with 98 additions and 13 deletions

View File

@ -87,8 +87,8 @@ public class ConfigFileApplicationListener implements
private static final String LOCATION_VARIABLE = "${spring.config.location}";
private String[] searchLocations = new String[] { "classpath:", "file:./",
"classpath:config/", "file:./config/" };
private String[] searchLocations = new String[] { "classpath:/", "file:./",
"classpath:/config/", "file:./config/" };
private String names = "${spring.config.name:application}";
@ -147,24 +147,39 @@ public class ConfigFileApplicationListener implements
PropertySource<?> defaultProperties = environment.getPropertySources().remove(
"defaultProperties");
addActiveProfiles(environment);
String firstPropertySourceName = loadInitial(environment, resourceLoader,
candidates);
if (environment.containsProperty(ACTIVE_PROFILES_PROPERTY)) {
for (String activeProfile : StringUtils.commaDelimitedListToSet(environment
.getProperty(ACTIVE_PROFILES_PROPERTY).toString())) {
environment.addActiveProfile(activeProfile);
}
// Repeatedly load property sources in case additional profiles are activated
int numberOfPropertySources;
do {
numberOfPropertySources = environment.getPropertySources().size();
addActiveProfiles(environment);
loadAgain(environment, resourceLoader, candidates, firstPropertySourceName);
}
// Second load for specific profiles
loadAgain(environment, resourceLoader, candidates, firstPropertySourceName);
while (environment.getPropertySources().size() > numberOfPropertySources);
if (defaultProperties != null) {
environment.getPropertySources().addLast(defaultProperties);
}
}
/**
* @param environment
*/
private void addActiveProfiles(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);
}
}
}
}
private String loadInitial(ConfigurableEnvironment environment,
ResourceLoader resourceLoader, LoadCandidates candidates) {
String firstSourceName = null;

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Tests to reproduce reported issues.
*
* @author Phillip Webb
*/
public class ReproTests {
@Test
public void enableProfileViaApplicationProperties() throws Exception {
// gh-308
SpringApplication application = new SpringApplication(Config.class);
application.setWebEnvironment(false);
ConfigurableApplicationContext context = application.run(
"--spring.config.name=enableprofileviaapplicationproperties",
"--spring.profiles.active=dev");
assertThat(context.getEnvironment().acceptsProfiles("dev"), equalTo(true));
assertThat(context.getEnvironment().acceptsProfiles("a"), equalTo(true));
}
@Configuration
public static class Config {
}
}

View File

@ -186,8 +186,8 @@ public class ConfigFileApplicationListenerTests {
"spring.profiles.active:prod");
this.initializer.setNames("testsetprofiles");
this.initializer.onApplicationEvent(this.event);
assertThat(Arrays.asList(this.environment.getActiveProfiles()).toString(),
equalTo("[prod]"));
assertThat(this.environment.getActiveProfiles(), equalTo(new String[] { "prod",
"dev" }));
}
@Test
@ -212,7 +212,7 @@ public class ConfigFileApplicationListenerTests {
// The default property source is still there
assertThat(
this.environment.getPropertySources().contains(
"classpath:application.properties"), is(true));
"classpath:/application.properties"), is(true));
assertThat(this.environment.getProperty("foo"), equalTo("bucket"));
}
@ -347,11 +347,27 @@ public class ConfigFileApplicationListenerTests {
context.close();
}
@Test
public void activateProfileFromProfileSpecificProperties() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebEnvironment(false);
ConfigurableApplicationContext context = application
.run("--spring.profiles.active=activateprofile");
assertThat(context.getEnvironment().acceptsProfiles("activateprofile"),
equalTo(true));
assertThat(context.getEnvironment().acceptsProfiles("specific"), equalTo(true));
}
@Test
public void defaultApplicationProperties() throws Exception {
}
@Configuration
protected static class Config {
}
@Configuration
@PropertySource("classpath:/specificlocation.properties")
protected static class WithPropertySource {

View File

@ -0,0 +1 @@
spring.profiles.active=specific

View File

@ -0,0 +1,3 @@
spring:
profiles:
active: a