/*
* Copyright 2012-2017 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.context.config;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.assertj.core.api.Condition;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.testutil.InternalOutputCapture;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.SimpleCommandLinePropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.StringUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ConfigFileApplicationListener}.
*
* @author Phillip Webb
* @author Dave Syer
* @author EddĂș MelĂ©ndez
*/
public class ConfigFileApplicationListenerTests {
private final StandardEnvironment environment = new StandardEnvironment();
private final SpringApplication application = new SpringApplication();
private final ConfigFileApplicationListener initializer = new ConfigFileApplicationListener();
@Rule
public ExpectedException expected = ExpectedException.none();
@Rule
public InternalOutputCapture out = new InternalOutputCapture();
private ConfigurableApplicationContext context;
@After
public void cleanUp() {
if (this.context != null) {
this.context.close();
}
System.clearProperty("the.property");
System.clearProperty("spring.config.location");
}
@Test
public void loadCustomResource() throws Exception {
this.application.setResourceLoader(new ResourceLoader() {
@Override
public Resource getResource(final String location) {
if (location.equals("classpath:/custom.properties")) {
return new ByteArrayResource("the.property: fromcustom".getBytes(),
location) {
@Override
public String getFilename() {
return location;
}
};
}
return null;
}
@Override
public ClassLoader getClassLoader() {
return getClass().getClassLoader();
}
});
this.initializer.setSearchNames("custom");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromcustom");
}
@Test
public void loadPropertiesFile() throws Exception {
this.initializer.setSearchNames("testproperties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void loadDefaultPropertiesFile() throws Exception {
this.environment.setDefaultProfiles("thedefault");
this.initializer.setSearchNames("testprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromdefaultpropertiesfile");
}
@Test
public void loadTwoPropertiesFile() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location="
+ "classpath:application.properties,classpath:testproperties.properties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void loadTwoPropertiesFilesWithProfiles() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location="
+ "classpath:enableprofile.properties,classpath:enableother.properties");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("other");
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromotherpropertiesfile");
}
@Test
public void loadTwoPropertiesFilesWithProfilesAndSwitchOneOff() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=classpath:enabletwoprofiles.properties,"
+ "classpath:enableprofile.properties");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("myprofile");
String property = this.environment.getProperty("the.property");
// The value from the second file wins (no profile-specific configuration is
// actually loaded)
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void loadTwoPropertiesFilesWithProfilesAndSwitchOneOffFromSpecificLocation()
throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.name=enabletwoprofiles",
"spring.config.location=classpath:enableprofile.properties");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("myprofile");
String property = this.environment.getProperty("the.property");
// The value from the second file wins (no profile-specific configuration is
// actually loaded)
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void localFileTakesPrecedenceOverClasspath() throws Exception {
File localFile = new File(new File("."), "application.properties");
assertThat(localFile.exists()).isFalse();
try {
Properties properties = new Properties();
properties.put("the.property", "fromlocalfile");
OutputStream out = new FileOutputStream(localFile);
try {
properties.store(out, "");
}
finally {
out.close();
}
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromlocalfile");
}
finally {
localFile.delete();
}
}
@Test
public void moreSpecificLocationTakesPrecedenceOverRoot() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.name=specific");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("specific");
}
@Test
public void loadTwoOfThreePropertiesFile() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=classpath:application.properties,"
+ "classpath:testproperties.properties,"
+ "classpath:nonexistent.properties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void randomValue() throws Exception {
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("random.value");
assertThat(property).isNotNull();
}
@Test
public void loadTwoPropertiesFiles() throws Exception {
this.initializer.setSearchNames("moreproperties,testproperties");
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).isEqualTo("frompropertiesfile");
}
@Test
public void loadYamlFile() throws Exception {
this.initializer.setSearchNames("testyaml");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromyamlfile");
assertThat(this.environment.getProperty("my.array[0]")).isEqualTo("1");
assertThat(this.environment.getProperty("my.array")).isNull();
}
@Test
public void loadProfileEmptySameAsNotSpecified() throws Exception {
this.initializer.setSearchNames("testprofilesempty");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromemptyprofile");
}
@Test
public void loadDefaultYamlDocument() throws Exception {
this.environment.setDefaultProfiles("thedefault");
this.initializer.setSearchNames("testprofilesdocument");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromdefaultprofile");
}
@Test
public void loadDefaultYamlDocumentNotActivated() throws Exception {
this.environment.setDefaultProfiles("thedefault");
this.environment.setActiveProfiles("other");
this.initializer.setSearchNames("testprofilesdocument");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromotherprofile");
}
@Test
public void commandLineWins() throws Exception {
this.environment.getPropertySources().addFirst(
new SimpleCommandLinePropertySource("--the.property=fromcommandline"));
this.initializer.setSearchNames("testproperties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromcommandline");
}
@Test
public void systemPropertyWins() throws Exception {
System.setProperty("the.property", "fromsystem");
this.initializer.setSearchNames("testproperties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromsystem");
}
@Test
public void defaultPropertyAsFallback() throws Exception {
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).isEqualTo("foo");
}
@Test
public void defaultPropertyAsFallbackDuringFileParsing() throws Exception {
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).isEqualTo("frompropertiesfile");
}
@Test
public void loadPropertiesThenProfilePropertiesActivatedInSpringApplication()
throws Exception {
// This should be the effect of calling
// SpringApplication.setAdditionalProfiles("other")
this.environment.setActiveProfiles("other");
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
assertThat(property).isEqualTo("fromotherpropertiesfile");
}
@Test
public void twoProfilesFromProperties() throws Exception {
// This should be the effect of calling
// SpringApplication.setAdditionalProfiles("other", "dev")
this.environment.setActiveProfiles("other", "dev");
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
assertThat(property).isEqualTo("fromdevpropertiesfile");
}
@Test
public void loadPropertiesThenProfilePropertiesActivatedInFirst() throws Exception {
this.initializer.setSearchNames("enableprofile");
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
assertThat(property).isEqualTo("fromprofilepropertiesfile");
}
@Test
public void loadPropertiesThenProfilePropertiesWithOverride() throws Exception {
this.environment.setActiveProfiles("other");
this.initializer.setSearchNames("enableprofile");
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).isEqualTo("fromotherpropertiesfile");
property = this.environment.getProperty("the.property");
// The "myprofile" profile is activated in enableprofile.properties and "other"
// was not activated by setting spring.profiles.active so "myprofile" should still
// be activated
assertThat(property).isEqualTo("fromprofilepropertiesfile");
}
@Test
public void profilePropertiesUsedInPlaceholders() throws Exception {
this.initializer.setSearchNames("enableprofile");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("one.more");
assertThat(property).isEqualTo("fromprofilepropertiesfile");
}
@Test
public void profilesAddedToEnvironmentAndViaProperty() throws Exception {
// External profile takes precedence over profile added via the environment
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=other");
this.environment.addActiveProfile("dev");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).contains("dev", "other");
assertThat(this.environment.getProperty("my.property"))
.isEqualTo("fromotherpropertiesfile");
validateProfilePrecedence(null, "dev", "other");
}
@Test
public void profilesAddedToEnvironmentAndViaPropertyDuplicate() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=dev,other");
this.environment.addActiveProfile("dev");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).contains("dev", "other");
assertThat(this.environment.getProperty("my.property"))
.isEqualTo("fromotherpropertiesfile");
validateProfilePrecedence(null, "dev", "other");
}
@Test
public void profilesAddedToEnvironmentAndViaPropertyDuplicateEnvironmentWins()
throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=other,dev");
this.environment.addActiveProfile("other");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).contains("dev", "other");
assertThat(this.environment.getProperty("my.property"))
.isEqualTo("fromdevpropertiesfile");
validateProfilePrecedence(null, "other", "dev");
}
@Test
public void postProcessorsAreOrderedCorrectly() {
TestConfigFileApplicationListener testListener = new TestConfigFileApplicationListener();
testListener.onApplicationEvent(new ApplicationEnvironmentPreparedEvent(
this.application, new String[0], this.environment));
}
private void validateProfilePrecedence(String... profiles) {
ApplicationPreparedEvent event = new ApplicationPreparedEvent(
new SpringApplication(), new String[0],
new AnnotationConfigApplicationContext());
withDebugLogging(() -> {
this.initializer.onApplicationEvent(event);
});
String log = this.out.toString();
// First make sure that each profile got processed only once
for (String profile : profiles) {
String reason = "Wrong number of occurrences for profile '" + profile
+ "' --> " + log;
assertThat(StringUtils.countOccurrencesOf(log, createLogForProfile(profile)))
.as(reason).isEqualTo(1);
}
// Make sure the order of loading is the right one
for (String profile : profiles) {
String line = createLogForProfile(profile);
int index = log.indexOf(line);
assertThat(index)
.as("Loading profile '" + profile + "' not found in '" + log + "'")
.isNotEqualTo(-1);
log = log.substring(index + line.length());
}
}
private void withDebugLogging(Runnable runnable) {
LoggerContext loggingContext = (LoggerContext) LogManager.getContext(false);
org.apache.logging.log4j.core.config.Configuration configuration = loggingContext
.getConfiguration();
configuration.addLogger(ConfigFileApplicationListener.class.getName(),
new LoggerConfig(ConfigFileApplicationListener.class.getName(),
Level.DEBUG, true));
loggingContext.updateLoggers();
try {
runnable.run();
}
finally {
configuration.removeLogger(ConfigFileApplicationListener.class.getName());
loggingContext.updateLoggers();
}
}
private String createLogForProfile(String profile) {
String suffix = profile != null ? "-" + profile : "";
String string = ".properties)";
return "Loaded config file '"
+ new File("target/test-classes/application" + suffix + ".properties")
.getAbsoluteFile().toURI().toString()
+ "' (classpath:/application" + suffix + string;
}
@Test
public void yamlProfiles() throws Exception {
this.initializer.setSearchNames("testprofiles");
this.environment.setActiveProfiles("dev");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromdevprofile");
property = this.environment.getProperty("my.other");
assertThat(property).isEqualTo("notempty");
}
@Test
public void yamlTwoProfiles() throws Exception {
this.initializer.setSearchNames("testprofiles");
this.environment.setActiveProfiles("other", "dev");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromdevprofile");
property = this.environment.getProperty("my.other");
assertThat(property).isEqualTo("notempty");
}
@Test
public void yamlSetsProfiles() throws Exception {
this.initializer.setSearchNames("testsetprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
String property = this.environment.getProperty("my.property");
assertThat(this.environment.getActiveProfiles()).contains("dev");
assertThat(property).isEqualTo("fromdevprofile");
List<String> names = StreamSupport
.stream(this.environment.getPropertySources().spliterator(), false)
.map(org.springframework.core.env.PropertySource::getName)
.collect(Collectors.toList());
assertThat(names).contains(
"applicationConfig: [classpath:/testsetprofiles.yml]#dev",
"applicationConfig: [classpath:/testsetprofiles.yml]");
}
@Test
public void yamlSetsMultiProfiles() throws Exception {
this.initializer.setSearchNames("testsetmultiprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev",
"healthcheck");
}
@Test
public void yamlSetsMultiProfilesWhenListProvided() throws Exception {
this.initializer.setSearchNames("testsetmultiprofileslist");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev",
"healthcheck");
}
@Test
public void yamlSetsMultiProfilesWithWhitespace() throws Exception {
this.initializer.setSearchNames("testsetmultiprofileswhitespace");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev",
"healthcheck");
}
@Test
public void yamlProfileCanBeChanged() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=prod");
this.initializer.setSearchNames("testsetprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("prod");
}
@Test
public void specificNameAndProfileFromExistingSource() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=specificprofile",
"spring.config.name=specificfile");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("my.property");
assertThat(property).isEqualTo("fromspecificpropertiesfile");
}
@Test
public void specificResource() throws Exception {
String location = "classpath:specificlocation.properties";
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=" + location);
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("fromspecificlocation");
assertThat(this.environment).has(matchingPropertySource(
"applicationConfig: " + "[classpath:specificlocation.properties]"));
// The default property source is still there
assertThat(this.environment).has(matchingPropertySource(
"applicationConfig: " + "[classpath:/application.properties]"));
assertThat(this.environment.getProperty("foo")).isEqualTo("bucket");
}
@Test
public void specificResourceAsFile() throws Exception {
String location = "file:src/test/resources/specificlocation.properties";
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=" + location);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment)
.has(matchingPropertySource("applicationConfig: [" + location + "]"));
}
@Test
public void specificResourceDefaultsToFile() throws Exception {
String location = "src/test/resources/specificlocation.properties";
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=" + location);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment).has(
matchingPropertySource("applicationConfig: [file:" + location + "]"));
}
@Test
public void absoluteResourceDefaultsToFile() throws Exception {
String location = new File("src/test/resources/specificlocation.properties")
.getAbsolutePath().replace("\\", "/");
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.config.location=" + location);
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment)
.has(matchingPropertySource("applicationConfig: [file:"
+ location.replace(File.separatorChar, '/') + "]"));
}
@Test
public void propertySourceAnnotation() throws Exception {
SpringApplication application = new SpringApplication(WithPropertySource.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("fromspecificlocation");
property = context.getEnvironment().getProperty("my.property");
assertThat(property).isEqualTo("fromapplicationproperties");
assertThat(context.getEnvironment()).has(matchingPropertySource(
"class path resource " + "[specificlocation.properties]"));
context.close();
}
@Test
public void propertySourceAnnotationWithPlaceholder() throws Exception {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"source.location=specificlocation");
SpringApplication application = new SpringApplication(
WithPropertySourcePlaceholders.class);
application.setEnvironment(this.environment);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("fromspecificlocation");
assertThat(context.getEnvironment()).has(matchingPropertySource(
"class path resource " + "[specificlocation.properties]"));
context.close();
}
@Test
public void propertySourceAnnotationWithName() throws Exception {
SpringApplication application = new SpringApplication(
WithPropertySourceAndName.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("fromspecificlocation");
assertThat(context.getEnvironment()).has(matchingPropertySource("foo"));
context.close();
}
@Test
public void propertySourceAnnotationInProfile() throws Exception {
SpringApplication application = new SpringApplication(
WithPropertySourceInProfile.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application
.run("--spring.profiles.active=myprofile");
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("frompropertiesfile");
assertThat(context.getEnvironment()).has(matchingPropertySource(
"class path resource " + "[enableprofile.properties]"));
assertThat(context.getEnvironment()).doesNotHave(matchingPropertySource(
"classpath:/" + "enableprofile-myprofile.properties"));
context.close();
}
@Test
public void propertySourceAnnotationAndNonActiveProfile() throws Exception {
SpringApplication application = new SpringApplication(
WithPropertySourceAndProfile.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("my.property");
assertThat(property).isEqualTo("fromapplicationproperties");
assertThat(context.getEnvironment()).doesNotHave(matchingPropertySource(
"classpath:" + "/enableprofile-myprofile.properties"));
context.close();
}
@Test
public void propertySourceAnnotationMultipleLocations() throws Exception {
SpringApplication application = new SpringApplication(
WithPropertySourceMultipleLocations.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("frommorepropertiesfile");
assertThat(context.getEnvironment()).has(matchingPropertySource(
"class path resource " + "[specificlocation.properties]"));
context.close();
}
@Test
public void propertySourceAnnotationMultipleLocationsAndName() throws Exception {
SpringApplication application = new SpringApplication(
WithPropertySourceMultipleLocationsAndName.class);
application.setWebApplicationType(WebApplicationType.NONE);
ConfigurableApplicationContext context = application.run();
String property = context.getEnvironment().getProperty("the.property");
assertThat(property).isEqualTo("frommorepropertiesfile");
assertThat(context.getEnvironment()).has(matchingPropertySource("foo"));
context.close();
}
@Test
public void activateProfileFromProfileSpecificProperties() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.profiles.active=includeprofile");
ConfigurableEnvironment environment = this.context.getEnvironment();
assertThat(environment).has(matchingProfile("includeprofile"));
assertThat(environment).has(matchingProfile("specific"));
assertThat(environment).has(matchingProfile("morespecific"));
assertThat(environment).has(matchingProfile("yetmorespecific"));
assertThat(environment).doesNotHave(matchingProfile("missing"));
}
@Test
public void profileSubDocumentInSameProfileSpecificFile() throws Exception {
// gh-340
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application
.run("--spring.profiles.active=activeprofilewithsubdoc");
String property = this.context.getEnvironment().getProperty("foobar");
assertThat(property).isEqualTo("baz");
}
@Test
public void profileSubDocumentInDifferentProfileSpecificFile() throws Exception {
// gh-4132
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run(
"--spring.profiles.active=activeprofilewithdifferentsubdoc,activeprofilewithdifferentsubdoc2");
String property = this.context.getEnvironment().getProperty("foobar");
assertThat(property).isEqualTo("baz");
}
@Test
public void addBeforeDefaultProperties() throws Exception {
MapPropertySource defaultSource = new MapPropertySource("defaultProperties",
Collections.<String, Object>singletonMap("the.property",
"fromdefaultproperties"));
this.environment.getPropertySources().addFirst(defaultSource);
this.initializer.setSearchNames("testproperties");
this.initializer.postProcessEnvironment(this.environment, this.application);
String property = this.environment.getProperty("the.property");
assertThat(property).isEqualTo("frompropertiesfile");
}
@Test
public void customDefaultProfile() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.profiles.default=customdefault");
String property = this.context.getEnvironment().getProperty("customdefault");
assertThat(property).isEqualTo("true");
}
@Test
public void customDefaultProfileAndActive() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.profiles.default=customdefault",
"--spring.profiles.active=dev");
String property = this.context.getEnvironment().getProperty("my.property");
assertThat(property).isEqualTo("fromdevpropertiesfile");
assertThat(this.context.getEnvironment().containsProperty("customdefault"))
.isFalse();
}
@Test
public void customDefaultProfileAndActiveFromFile() throws Exception {
// gh-5998
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.config.name=customprofile",
"--spring.profiles.default=customdefault");
ConfigurableEnvironment environment = this.context.getEnvironment();
assertThat(environment.containsProperty("customprofile")).isTrue();
assertThat(environment.containsProperty("customprofile-specific")).isTrue();
assertThat(environment.containsProperty("customprofile-customdefault")).isTrue();
assertThat(environment.acceptsProfiles("customdefault")).isTrue();
}
@Test
public void additionalProfilesCanBeIncludedFromAnyPropertySource() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.profiles.active=myprofile",
"--spring.profiles.include=dev");
String property = this.context.getEnvironment().getProperty("my.property");
assertThat(property).isEqualTo("fromdevpropertiesfile");
assertThat(this.context.getEnvironment().containsProperty("customdefault"))
.isFalse();
}
@Test
public void profileCanBeIncludedWithoutAnyBeingActive() throws Exception {
SpringApplication application = new SpringApplication(Config.class);
application.setWebApplicationType(WebApplicationType.NONE);
this.context = application.run("--spring.profiles.include=dev");
String property = this.context.getEnvironment().getProperty("my.property");
assertThat(property).isEqualTo("fromdevpropertiesfile");
}
@Test
public void activeProfilesCanBeConfiguredUsingPlaceholdersResolvedAgainstTheEnvironment()
throws Exception {
Map<String, Object> source = new HashMap<>();
source.put("activeProfile", "testPropertySource");
org.springframework.core.env.PropertySource<?> propertySource = new MapPropertySource(
"test", source);
this.environment.getPropertySources().addLast(propertySource);
this.initializer.setSearchNames("testactiveprofiles");
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles())
.containsExactly("testPropertySource");
}
private Condition<ConfigurableEnvironment> matchingPropertySource(
final String sourceName) {
return new Condition<ConfigurableEnvironment>(
"environment containing property source " + sourceName) {
@Override
public boolean matches(ConfigurableEnvironment value) {
return value.getPropertySources().contains(sourceName);
}
};
}
private Condition<ConfigurableEnvironment> matchingProfile(final String profile) {
return new Condition<ConfigurableEnvironment>("accepts profile " + profile) {
@Override
public boolean matches(ConfigurableEnvironment value) {
return value.acceptsProfiles(profile);
}
};
}
@Configuration
protected static class Config {
}
@Configuration
@PropertySource("classpath:/specificlocation.properties")
protected static class WithPropertySource {
}
@Configuration
@PropertySource("classpath:/${source.location}.properties")
protected static class WithPropertySourcePlaceholders {
}
@Configuration
@PropertySource(value = "classpath:/specificlocation.properties", name = "foo")
protected static class WithPropertySourceAndName {
}
@Configuration
@PropertySource("classpath:/enableprofile.properties")
protected static class WithPropertySourceInProfile {
}
@Configuration
@PropertySource("classpath:/enableprofile-myprofile.properties")
@Profile("myprofile")
protected static class WithPropertySourceAndProfile {
}
@Configuration
@PropertySource({ "classpath:/specificlocation.properties",
"classpath:/moreproperties.properties" })
protected static class WithPropertySourceMultipleLocations {
}
@Configuration
@PropertySource(value = { "classpath:/specificlocation.properties",
"classpath:/moreproperties.properties" }, name = "foo")
protected static class WithPropertySourceMultipleLocationsAndName {
}
private static class TestConfigFileApplicationListener
extends ConfigFileApplicationListener {
@Override
List<EnvironmentPostProcessor> loadPostProcessors() {
return new ArrayList<>(
Arrays.asList(new LowestPrecedenceEnvironmentPostProcessor()));
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
private static class LowestPrecedenceEnvironmentPostProcessor
implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
assertThat(environment.getPropertySources()).hasSize(4);
}
}
}