DefaultProperties profiles shouldn't take precedence over config files

Fixes gh-15445
pull/16203/head
Madhura Bhave 6 years ago
parent 404f5d33f3
commit d92c2f7023

@ -56,6 +56,7 @@ import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.Profiles; import org.springframework.core.env.Profiles;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
@ -323,6 +324,9 @@ public class ConfigFileApplicationListener
this.processedProfiles = new LinkedList<>(); this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false; this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>(); this.loaded = new LinkedHashMap<>();
MapPropertySource defaultProperties = (MapPropertySource) this.environment
.getPropertySources().get(DEFAULT_PROPERTIES);
replaceDefaultPropertySourceIfNecessary(defaultProperties);
initializeProfiles(); initializeProfiles();
while (!this.profiles.isEmpty()) { while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll(); Profile profile = this.profiles.poll();
@ -333,10 +337,19 @@ public class ConfigFileApplicationListener
addToLoaded(MutablePropertySources::addLast, false)); addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile); this.processedProfiles.add(profile);
} }
resetEnvironmentProfiles(this.processedProfiles);
load(null, this::getNegativeProfileFilter, load(null, this::getNegativeProfileFilter,
addToLoaded(MutablePropertySources::addFirst, true)); addToLoaded(MutablePropertySources::addFirst, true));
addLoadedPropertySources(); addLoadedPropertySources();
resetEnvironment(defaultProperties);
}
private void replaceDefaultPropertySourceIfNecessary(
MapPropertySource defaultProperties) {
if (defaultProperties != null) {
this.environment.getPropertySources().replace(DEFAULT_PROPERTIES,
new FilteredDefaultPropertySource(DEFAULT_PROPERTIES,
defaultProperties.getSource()));
}
} }
/** /**
@ -729,6 +742,76 @@ public class ConfigFileApplicationListener
} }
} }
private void resetEnvironment(MapPropertySource defaultProperties) {
List<String> activeProfiles = new ArrayList<>();
handleDefaultPropertySource(defaultProperties, activeProfiles);
activeProfiles.addAll(this.processedProfiles.stream()
.filter((profile) -> profile != null && !profile.isDefaultProfile())
.map(Profile::getName).collect(Collectors.toList()));
this.environment.setActiveProfiles(activeProfiles.toArray(new String[0]));
}
private void handleDefaultPropertySource(MapPropertySource defaultProperties,
List<String> activeProfiles) {
if (defaultProperties != null) {
Binder binder = new Binder(
ConfigurationPropertySources.from(defaultProperties),
new PropertySourcesPlaceholdersResolver(this.environment));
List<String> includes = getDefaultProfiles(binder,
"spring.profiles.include");
activeProfiles.addAll(includes);
if (!this.activatedProfiles) {
List<String> active = getDefaultProfiles(binder,
"spring.profiles.active");
activeProfiles.addAll(active);
}
this.environment.getPropertySources().replace(DEFAULT_PROPERTIES,
defaultProperties);
}
}
private List<String> getDefaultProfiles(Binder binder, String property) {
return Arrays
.asList(binder.bind(property, STRING_ARRAY).orElse(new String[] {}));
}
}
private static class FilteredDefaultPropertySource extends MapPropertySource {
private static final List<String> FILTERED_PROPERTY = Arrays
.asList("spring.profiles.active", "spring.profiles.include");
FilteredDefaultPropertySource(String name, Map<String, Object> source) {
super(name, source);
}
@Override
public Object getProperty(String name) {
if (isFilteredProperty(name)) {
return null;
}
return super.getProperty(name);
}
@Override
public boolean containsProperty(String name) {
if (isFilteredProperty(name)) {
return false;
}
return super.containsProperty(name);
}
@Override
public String[] getPropertyNames() {
return Arrays.stream(super.getPropertyNames())
.filter((name) -> !isFilteredProperty(name)).toArray(String[]::new);
}
protected boolean isFilteredProperty(String name) {
return FILTERED_PROPERTY.contains(name);
}
} }
/** /**

@ -329,6 +329,51 @@ public class ConfigFileApplicationListenerTests {
assertThat(property).isEqualTo("frompropertiesfile"); assertThat(property).isEqualTo("frompropertiesfile");
} }
@Test
public void activeProfilesFromDefaultPropertiesShouldNotTakePrecedence() {
this.initializer.setSearchNames("enableprofile");
this.environment.getPropertySources()
.addLast(new MapPropertySource("defaultProperties",
Collections.singletonMap("spring.profiles.active", "dev")));
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("myprofile");
}
@Test
public void includedProfilesFromDefaultPropertiesShouldNotTakePrecedence() {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=morespecific");
this.environment.getPropertySources()
.addLast(new MapPropertySource("defaultProperties",
Collections.singletonMap("spring.profiles.include", "dev")));
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("dev",
"morespecific", "yetmorespecific");
}
@Test
public void activeAndIncludedProfilesFromDefaultProperties() {
Map<String, Object> source = new HashMap<>();
source.put("spring.profiles.include", "other");
source.put("spring.profiles.active", "dev");
this.environment.getPropertySources()
.addLast(new MapPropertySource("defaultProperties", source));
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("other", "dev");
}
@Test
public void activeFromDefaultPropertiesShouldNotApplyIfProfilesHaveBeenActivatedBefore() {
Map<String, Object> source = new HashMap<>();
source.put("spring.profiles.active", "dev");
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment,
"spring.profiles.active=other");
this.environment.getPropertySources()
.addLast(new MapPropertySource("defaultProperties", source));
this.initializer.postProcessEnvironment(this.environment, this.application);
assertThat(this.environment.getActiveProfiles()).containsExactly("other");
}
@Test @Test
public void loadPropertiesThenProfilePropertiesActivatedInSpringApplication() { public void loadPropertiesThenProfilePropertiesActivatedInSpringApplication() {
// This should be the effect of calling // This should be the effect of calling

Loading…
Cancel
Save