Introduce defined extension point for modifying the environment

The commit introduces a new extension point, EnvironmentPostProcessor,
that can be implemented by classes that want to modify the
environment. Implementations of EnvironmentPostProcessor are loaded
via spring.factories and called in response to the
ApplicationEnvironmentPreparedEvent. Application listeners that wish
to work with the post-processed environment can continue to listen
to ApplicationEnvironmentPreparedEvent and order themselves to
run after EnvironmentPostProcessingApplicationListener.

Existing ApplicationListeners that modify the environment have,
where possible, been updated to implement EnvironmentPostProcessor
instead.

Closes gh-3737
pull/3762/merge
Andy Wilkinson 9 years ago
parent 2f862cfb92
commit e370b592d6

@ -455,7 +455,7 @@ public class SpringApplication {
* @param environment this application's environment
* @param args arguments passed to the {@code run} method
* @see #configureEnvironment(ConfigurableEnvironment, String[])
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
* @see org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor
*/
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
environment.getActiveProfiles(); // ensure they are initialized

@ -25,11 +25,11 @@ import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.json.JsonParser;
import org.springframework.boot.json.JsonParserFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@ -39,8 +39,8 @@ import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.util.StringUtils;
/**
* An {@link ApplicationListener} that knows where to find VCAP (a.k.a. Cloud Foundry)
* meta data in the existing environment. It parses out the VCAP_APPLICATION and
* An {@link EnvironmentPostProcessor} that knows where to find VCAP (a.k.a. Cloud
* Foundry) meta data in the existing environment. It parses out the VCAP_APPLICATION and
* VCAP_SERVICES meta data and dumps it in a form that is easily consumed by
* {@link Environment} users. If the app is running in Cloud Foundry then both meta data
* items are JSON objects encoded in OS environment variables. VCAP_APPLICATION is a
@ -86,18 +86,19 @@ import org.springframework.util.StringUtils;
* Cloud is more convenient and more robust against potential changes in Cloud Foundry.
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class VcapApplicationListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
public class VcapEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
private static final Log logger = LogFactory.getLog(VcapApplicationListener.class);
private static final Log logger = LogFactory
.getLog(VcapEnvironmentPostProcessor.class);
private static final String VCAP_APPLICATION = "VCAP_APPLICATION";
private static final String VCAP_SERVICES = "VCAP_SERVICES";
// Before ConfigFileApplicationListener so values there can use these ones
private int order = ConfigFileApplicationListener.DEFAULT_ORDER - 1;
private int order = ConfigFileEnvironmentPostProcessor.DEFAULT_ORDER - 1;
private final JsonParser parser = JsonParserFactory.getJsonParser();
@ -111,8 +112,8 @@ public class VcapApplicationListener implements
}
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
if (!environment.containsProperty(VCAP_APPLICATION)
&& !environment.containsProperty(VCAP_SERVICES)) {
return;

@ -20,6 +20,7 @@ import org.springframework.boot.ansi.AnsiOutput;
import org.springframework.boot.ansi.AnsiOutput.Enabled;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.env.EnvironmentPostProcessingApplicationListener;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
@ -51,8 +52,9 @@ public class AnsiOutputApplicationListener implements
@Override
public int getOrder() {
// Apply after the ConfigFileApplicationListener
return ConfigFileApplicationListener.DEFAULT_ORDER + 1;
// Apply after the EnvironmentPostProcessingApplicationListener has called all
// EnvironmentPostProcessors
return EnvironmentPostProcessingApplicationListener.ORDER + 1;
}
}

@ -33,12 +33,11 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnumerableCompositePropertySource;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.PropertySourcesLoader;
import org.springframework.boot.logging.DeferredLog;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
@ -47,7 +46,6 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader;
@ -59,7 +57,7 @@ import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
/**
* {@link ApplicationListener} that configures the context environment by loading
* {@link EnvironmentPostProcessor} that configures the context environment by loading
* properties from well known file locations. By default properties will be loaded from
* 'application.properties' and/or 'application.yml' files in the following locations:
* <ul>
@ -89,9 +87,10 @@ import org.springframework.validation.BindException;
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
public class ConfigFileApplicationListener implements
ApplicationListener<ApplicationEvent>, Ordered {
public class ConfigFileEnvironmentPostProcessor implements EnvironmentPostProcessor,
ApplicationListener<ApplicationPreparedEvent>, Ordered {
private static final String DEFAULT_PROPERTIES = "defaultProperties";
@ -121,34 +120,15 @@ public class ConfigFileApplicationListener implements
private final ConversionService conversionService = new DefaultConversionService();
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
}
private void onApplicationEnvironmentPreparedEvent(
ApplicationEnvironmentPreparedEvent event) {
Environment environment = event.getEnvironment();
if (environment instanceof ConfigurableEnvironment) {
onApplicationEnvironmentPreparedEvent((ConfigurableEnvironment) environment,
event.getSpringApplication());
}
}
private void onApplicationEnvironmentPreparedEvent(
ConfigurableEnvironment environment, SpringApplication application) {
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
bindToSpringApplication(environment, application);
}
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
// logging is deferred because the Logging initialization might not have
// run at the time that config file decisions are taken
this.logger.replayTo(ConfigFileApplicationListener.class);
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
this.logger.replayTo(ConfigFileEnvironmentPostProcessor.class);
addPostProcessors(event.getApplicationContext());
}
@ -272,7 +252,7 @@ public class ConfigFileApplicationListener implements
*/
private class Loader {
private final Log logger = ConfigFileApplicationListener.this.logger;
private final Log logger = ConfigFileEnvironmentPostProcessor.this.logger;
private final ConfigurableEnvironment environment;
@ -472,7 +452,7 @@ public class ConfigFileApplicationListener implements
}
}
locations.addAll(asResolvedSet(
ConfigFileApplicationListener.this.searchLocations,
ConfigFileEnvironmentPostProcessor.this.searchLocations,
DEFAULT_SEARCH_LOCATIONS));
return locations;
}
@ -482,7 +462,8 @@ public class ConfigFileApplicationListener implements
return asResolvedSet(this.environment.getProperty(CONFIG_NAME_PROPERTY),
null);
}
return asResolvedSet(ConfigFileApplicationListener.this.names, DEFAULT_NAMES);
return asResolvedSet(ConfigFileEnvironmentPostProcessor.this.names,
DEFAULT_NAMES);
}
private Set<String> asResolvedSet(String value, String fallback) {

@ -18,7 +18,7 @@
* External configuration support allowing 'application.properties' to be loaded
* and used within a Spring Boot application.
*
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
* @see org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor
*/
package org.springframework.boot.context.config;

@ -0,0 +1,61 @@
/*
* Copyright 2012-2015 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.env;
import java.util.List;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.io.support.SpringFactoriesLoader;
/**
* An {@link ApplicationListener} that responds to an
* {@link ApplicationEnvironmentPreparedEvent} and calls all
* {@link EnvironmentPostProcessor EnvironmentPostProcessors} that are available via
* {@code spring.factories}.
* <p>
* Post-processors are called in the order defined by
* {@link AnnotationAwareOrderComparator}.
*
* @author Andy Wilkinson
* @since 1.3.0
* @see SpringFactoriesLoader#loadFactories(Class, ClassLoader)
*/
public class EnvironmentPostProcessingApplicationListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
public static final int ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
List<EnvironmentPostProcessor> postProcessors = SpringFactoriesLoader
.loadFactories(EnvironmentPostProcessor.class, getClass()
.getClassLoader());
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
}
@Override
public int getOrder() {
return ORDER;
}
}

@ -0,0 +1,41 @@
/*
* Copyright 2012-2015 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.env;
import org.springframework.boot.SpringApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
* Allows for customization of the application's {@link Environment} prior to the
* application context being refreshed.
*
* @author Andy Wilkinson
* @since 1.3.0
*/
public interface EnvironmentPostProcessor {
/**
* Post-process the given {@code environment}
*
* @param environment the environment to post-process
* @param application the application to which the environment belongs
*/
void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application);
}

@ -16,7 +16,7 @@
package org.springframework.boot.test;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
@ -27,14 +27,14 @@ import org.springframework.test.context.ContextConfiguration;
* {@literal application.properties}.
*
* @author Phillip Webb
* @see ConfigFileApplicationListener
* @see ConfigFileEnvironmentPostProcessor
*/
public class ConfigFileApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(final ConfigurableApplicationContext applicationContext) {
new ConfigFileApplicationListener() {
new ConfigFileEnvironmentPostProcessor() {
public void apply() {
addPropertySources(applicationContext.getEnvironment(),
applicationContext);

@ -17,11 +17,16 @@ org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloudfoundry.VcapApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloudfoundry.VcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor

@ -17,8 +17,6 @@
package org.springframework.boot.cloudfoundry;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@ -27,19 +25,17 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* Tests for {@link VcapApplicationListener}.
* Tests for {@link VcapEnvironmentPostProcessor}.
*
* @author Dave Syer
* @author Andy Wilkinson
*/
public class VcapApplicationListenerTests {
public class VcapEnvironmentPostProcessorTests {
private final VcapApplicationListener initializer = new VcapApplicationListener();
private final VcapEnvironmentPostProcessor initializer = new VcapEnvironmentPostProcessor();
private final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
private final ApplicationEnvironmentPreparedEvent event = new ApplicationEnvironmentPreparedEvent(
new SpringApplication(), new String[0], this.context.getEnvironment());
@Test
public void testApplicationProperties() {
EnvironmentTestUtils
@ -57,7 +53,7 @@ public class VcapApplicationListenerTests {
+ "\"name\":\"dsyerenv\",\"uris\":[\"dsyerenv.cfapps.io\"],"
+ "\"users\":[],\"start\":\"2013-05-29 02:37:59 +0000\","
+ "\"state_timestamp\":1369795079}");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertEquals("bb7935245adf3e650dfb7c58a06e9ece", this.context.getEnvironment()
.getProperty("vcap.application.instance_id"));
}
@ -68,7 +64,7 @@ public class VcapApplicationListenerTests {
.addEnvironment(
this.context,
"VCAP_APPLICATION:{\"instance_id\":\"bb7935245adf3e650dfb7c58a06e9ece\",\"instance_index\":0,\"uris\":[\"foo.cfapps.io\"]}");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertEquals("foo.cfapps.io",
this.context.getEnvironment().getProperty("vcap.application.uris[0]"));
}
@ -76,7 +72,7 @@ public class VcapApplicationListenerTests {
@Test
public void testUnparseableApplicationProperties() {
EnvironmentTestUtils.addEnvironment(this.context, "VCAP_APPLICATION:");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertNull(getProperty("vcap"));
}
@ -97,7 +93,7 @@ public class VcapApplicationListenerTests {
+ "\"name\":\"dsyerenv\",\"uris\":[\"dsyerenv.cfapps.io\"],"
+ "\"users\":[],\"start\":\"2013-05-29 02:37:59 +0000\","
+ "\"state_timestamp\":1369795079}");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertNull(getProperty("vcap"));
}
@ -115,7 +111,7 @@ public class VcapApplicationListenerTests {
+ "\"host\":\"mysql-service-public.clqg2e2w3ecf.us-east-1.rds.amazonaws.com\","
+ "\"port\":3306,\"user\":\"urpRuqTf8Cpe6\",\"username\":"
+ "\"urpRuqTf8Cpe6\",\"password\":\"pxLsGVpsC9A5S\"}}]}");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertEquals("mysql", getProperty("vcap.services.mysql.name"));
assertEquals("3306", getProperty("vcap.services.mysql.credentials.port"));
assertEquals("true", getProperty("vcap.services.mysql.credentials.ssl"));
@ -135,7 +131,7 @@ public class VcapApplicationListenerTests {
+ "\"port\":3306,\"user\":\"urpRuqTf8Cpe6\","
+ "\"username\":\"urpRuqTf8Cpe6\","
+ "\"password\":\"pxLsGVpsC9A5S\"}}]}");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.context.getEnvironment(), null);
assertEquals("mysql", getProperty("vcap.services.mysql.name"));
assertEquals("3306", getProperty("vcap.services.mysql.credentials.port"));
}

@ -35,8 +35,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.config.ConfigFileApplicationListener.ConfigurationPropertySources;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor.ConfigurationPropertySources;
import org.springframework.boot.env.EnumerableCompositePropertySource;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.ConfigurableApplicationContext;
@ -63,19 +62,18 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link ConfigFileApplicationListener}.
* Tests for {@link ConfigFileEnvironmentPostProcessor}.
*
* @author Phillip Webb
* @author Dave Syer
*/
public class ConfigFileApplicationListenerTests {
public class ConfigFileEnvironmentPostProcessorTests {
private final StandardEnvironment environment = new StandardEnvironment();
private final ApplicationEnvironmentPreparedEvent event = new ApplicationEnvironmentPreparedEvent(
new SpringApplication(), new String[0], this.environment);
private final SpringApplication application = new SpringApplication();
private final ConfigFileApplicationListener initializer = new ConfigFileApplicationListener();
private final ConfigFileEnvironmentPostProcessor initializer = new ConfigFileEnvironmentPostProcessor();
@Rule
public ExpectedException expected = ExpectedException.none();
@ -89,7 +87,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadCustomResource() throws Exception {
this.event.getSpringApplication().setResourceLoader(new ResourceLoader() {
this.application.setResourceLoader(new ResourceLoader() {
@Override
public Resource getResource(final String location) {
if (location.equals("classpath:/custom.properties")) {
@ -110,7 +108,7 @@ public class ConfigFileApplicationListenerTests {
}
});
this.initializer.setSearchNames("custom");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromcustom"));
}
@ -118,7 +116,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadPropertiesFile() throws Exception {
this.initializer.setSearchNames("testproperties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("frompropertiesfile"));
}
@ -127,7 +125,7 @@ public class ConfigFileApplicationListenerTests {
public void loadDefaultPropertiesFile() throws Exception {
this.environment.setDefaultProfiles("thedefault");
this.initializer.setSearchNames("testprofiles");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromdefaultpropertiesfile"));
}
@ -136,7 +134,7 @@ public class ConfigFileApplicationListenerTests {
public void loadTwoPropertiesFile() throws Exception {
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ "classpath:application.properties,classpath:testproperties.properties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("frompropertiesfile"));
}
@ -145,7 +143,7 @@ public class ConfigFileApplicationListenerTests {
public void loadTwoPropertiesFilesWithProfiles() throws Exception {
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ "classpath:enableprofile.properties,classpath:enableother.properties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertEquals("other", StringUtils.arrayToCommaDelimitedString(this.environment
.getActiveProfiles()));
String property = this.environment.getProperty("my.property");
@ -157,7 +155,7 @@ public class ConfigFileApplicationListenerTests {
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ "classpath:enabletwoprofiles.properties,"
+ "classpath:enableprofile.properties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertEquals("myprofile",
StringUtils.arrayToCommaDelimitedString(this.environment
.getActiveProfiles()));
@ -173,7 +171,7 @@ public class ConfigFileApplicationListenerTests {
EnvironmentTestUtils.addEnvironment(this.environment,
"spring.config.name:enabletwoprofiles",
"spring.config.location:classpath:enableprofile.properties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertEquals("myprofile",
StringUtils.arrayToCommaDelimitedString(this.environment
.getActiveProfiles()));
@ -197,7 +195,7 @@ public class ConfigFileApplicationListenerTests {
finally {
out.close();
}
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromlocalfile"));
}
@ -210,7 +208,7 @@ public class ConfigFileApplicationListenerTests {
public void moreSpecificLocationTakesPrecedenceOverRoot() throws Exception {
EnvironmentTestUtils.addEnvironment(this.environment,
"spring.config.name:specific");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("specific"));
}
@ -221,14 +219,14 @@ public class ConfigFileApplicationListenerTests {
+ "classpath:application.properties,"
+ "classpath:testproperties.properties,"
+ "classpath:nonexistent.properties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("frompropertiesfile"));
}
@Test
public void randomValue() throws Exception {
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("random.value");
assertThat(property, notNullValue());
}
@ -236,7 +234,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadTwoPropertiesFiles() throws Exception {
this.initializer.setSearchNames("moreproperties,testproperties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
// The search order has highest precedence last (like merging a map)
assertThat(property, equalTo("frompropertiesfile"));
@ -245,7 +243,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadYamlFile() throws Exception {
this.initializer.setSearchNames("testyaml");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromyamlfile"));
assertThat(this.environment.getProperty("my.array[0]"), equalTo("1"));
@ -255,7 +253,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadProfileEmptySameAsNotSpecified() throws Exception {
this.initializer.setSearchNames("testprofilesempty");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromemptyprofile"));
}
@ -264,7 +262,7 @@ public class ConfigFileApplicationListenerTests {
public void loadDefaultYamlDocument() throws Exception {
this.environment.setDefaultProfiles("thedefault");
this.initializer.setSearchNames("testprofilesdocument");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromdefaultprofile"));
}
@ -274,7 +272,7 @@ public class ConfigFileApplicationListenerTests {
this.environment.setDefaultProfiles("thedefault");
this.environment.setActiveProfiles("other");
this.initializer.setSearchNames("testprofilesdocument");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromotherprofile"));
}
@ -284,7 +282,7 @@ public class ConfigFileApplicationListenerTests {
this.environment.getPropertySources().addFirst(
new SimpleCommandLinePropertySource("--the.property=fromcommandline"));
this.initializer.setSearchNames("testproperties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromcommandline"));
}
@ -293,34 +291,27 @@ public class ConfigFileApplicationListenerTests {
public void systemPropertyWins() throws Exception {
System.setProperty("the.property", "fromsystem");
this.initializer.setSearchNames("testproperties");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromsystem"));
}
@Test
public void defaultPropertyAsFallback() throws Exception {
this.event
.getEnvironment()
.getPropertySources()
.addLast(
new MapPropertySource("defaultProperties", Collections
.singletonMap("my.fallback", (Object) "foo")));
this.initializer.onApplicationEvent(this.event);
this.environment.getPropertySources().addLast(
new MapPropertySource("defaultProperties", Collections.singletonMap(
"my.fallback", (Object) "foo")));
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.fallback");
assertThat(property, equalTo("foo"));
}
@Test
public void defaultPropertyAsFallbackDuringFileParsing() throws Exception {
this.event
.getEnvironment()
.getPropertySources()
.addLast(
new MapPropertySource("defaultProperties", Collections
.singletonMap("spring.config.name",
(Object) "testproperties")));
this.initializer.onApplicationEvent(this.event);
this.environment.getPropertySources().addLast(
new MapPropertySource("defaultProperties", Collections.singletonMap(
"spring.config.name", (Object) "testproperties")));
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("frompropertiesfile"));
}
@ -331,7 +322,7 @@ public class ConfigFileApplicationListenerTests {
// This should be the effect of calling
// SpringApplication.setAdditionalProfiles("other")
this.environment.setActiveProfiles("other");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
// The "other" profile is activated in SpringApplication so it should take
// precedence over the default profile
@ -343,7 +334,7 @@ public class ConfigFileApplicationListenerTests {
// This should be the effect of calling
// SpringApplication.setAdditionalProfiles("other", "dev")
this.environment.setActiveProfiles("other", "dev");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
// The "dev" profile is activated in SpringApplication so it should take
// precedence over the default profile
@ -353,7 +344,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void loadPropertiesThenProfilePropertiesActivatedInFirst() throws Exception {
this.initializer.setSearchNames("enableprofile");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
// The "myprofile" profile is activated in enableprofile.properties so its value
// should show up here
@ -366,7 +357,7 @@ public class ConfigFileApplicationListenerTests {
// EnvironmentTestUtils.addEnvironment(this.environment,
// "spring.profiles.active:other");
this.initializer.setSearchNames("enableprofile");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("other.property");
// The "other" profile is activated before any processing starts
assertThat(property, equalTo("fromotherpropertiesfile"));
@ -380,7 +371,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void profilePropertiesUsedInPlaceholders() throws Exception {
this.initializer.setSearchNames("enableprofile");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("one.more");
assertThat(property, equalTo("fromprofilepropertiesfile"));
}
@ -389,7 +380,7 @@ public class ConfigFileApplicationListenerTests {
public void yamlProfiles() throws Exception {
this.initializer.setSearchNames("testprofiles");
this.environment.setActiveProfiles("dev");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromdevprofile"));
property = this.environment.getProperty("my.other");
@ -400,7 +391,7 @@ public class ConfigFileApplicationListenerTests {
public void yamlTwoProfiles() throws Exception {
this.initializer.setSearchNames("testprofiles");
this.environment.setActiveProfiles("other", "dev");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromdevprofile"));
property = this.environment.getProperty("my.other");
@ -410,7 +401,7 @@ public class ConfigFileApplicationListenerTests {
@Test
public void yamlSetsProfiles() throws Exception {
this.initializer.setSearchNames("testsetprofiles");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertEquals("dev", StringUtils.arrayToCommaDelimitedString(this.environment
.getActiveProfiles()));
String property = this.environment.getProperty("my.property");
@ -444,7 +435,7 @@ public class ConfigFileApplicationListenerTests {
EnvironmentTestUtils.addEnvironment(this.environment,
"spring.profiles.active:prod");
this.initializer.setSearchNames("testsetprofiles");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles(), equalTo(new String[] { "prod" }));
}
@ -453,7 +444,7 @@ public class ConfigFileApplicationListenerTests {
EnvironmentTestUtils.addEnvironment(this.environment,
"spring.profiles.active=specificprofile",
"spring.config.name=specificfile");
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property, equalTo("fromspecificpropertiesfile"));
}
@ -463,7 +454,7 @@ public class ConfigFileApplicationListenerTests {
String location = "classpath:specificlocation.properties";
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ location);
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property, equalTo("fromspecificlocation"));
assertThat(this.environment, containsPropertySource("applicationConfig: "
@ -479,7 +470,7 @@ public class ConfigFileApplicationListenerTests {
String location = "file:src/test/resources/specificlocation.properties";
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ location);
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment, containsPropertySource("applicationConfig: ["
+ location + "]"));
}
@ -489,7 +480,7 @@ public class ConfigFileApplicationListenerTests {
String location = "src/test/resources/specificlocation.properties";
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ location);
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment, containsPropertySource("applicationConfig: [file:"
+ location + "]"));
}
@ -500,7 +491,7 @@ public class ConfigFileApplicationListenerTests {
.getAbsolutePath();
EnvironmentTestUtils.addEnvironment(this.environment, "spring.config.location:"
+ location);
this.initializer.onApplicationEvent(this.event);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment, containsPropertySource("applicationConfig: [file:"
+ location.replace(File.separatorChar, '/') + "]"));
}
@ -633,22 +624,20 @@ public class ConfigFileApplicationListenerTests {
public void bindsToSpringApplication() throws Exception {
// gh-346
this.initializer.setSearchNames("bindtoapplication");
this.initializer.onApplicationEvent(this.event);
SpringApplication application = this.event.getSpringApplication();
this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner");
field.setAccessible(true);
assertThat((Boolean) field.get(application), equalTo(false));
assertThat((Boolean) field.get(this.application), equalTo(false));
}
@Test
public void bindsSystemPropertyToSpringApplication() throws Exception {
// gh-951
System.setProperty("spring.main.showBanner", "false");
this.initializer.onApplicationEvent(this.event);
SpringApplication application = this.event.getSpringApplication();
this.initializer.postProcessEnvironment(this.environment, this.application);
Field field = ReflectionUtils.findField(SpringApplication.class, "showBanner");
field.setAccessible(true);
assertThat((Boolean) field.get(application), equalTo(false));
assertThat((Boolean) field.get(this.application), equalTo(false));
}
private static Matcher<? super ConfigurableEnvironment> containsPropertySource(
Loading…
Cancel
Save