Process additional profiles before config files processing
Additional profiles were being processed after config file processing when legacy processing was used. This commit also restores the order in which additional profiles are added when legacy processing is used. Active profiles take precedence over additional profiles. See gh-25817
This commit is contained in:
parent
269fc68c1d
commit
6f266145c7
|
@ -154,6 +154,7 @@ import org.springframework.web.context.support.StandardServletEnvironment;
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @author Ethan Rubinson
|
* @author Ethan Rubinson
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
* @since 1.0.0
|
* @since 1.0.0
|
||||||
* @see #run(Class, String[])
|
* @see #run(Class, String[])
|
||||||
* @see #run(Class[], String[])
|
* @see #run(Class[], String[])
|
||||||
|
@ -373,7 +374,6 @@ public class SpringApplication {
|
||||||
ConfigurationPropertySources.attach(environment);
|
ConfigurationPropertySources.attach(environment);
|
||||||
listeners.environmentPrepared(bootstrapContext, environment);
|
listeners.environmentPrepared(bootstrapContext, environment);
|
||||||
DefaultPropertiesPropertySource.moveToEnd(environment);
|
DefaultPropertiesPropertySource.moveToEnd(environment);
|
||||||
configureAdditionalProfiles(environment);
|
|
||||||
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
|
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
|
||||||
"Environment prefix cannot be set via properties.");
|
"Environment prefix cannot be set via properties.");
|
||||||
bindToSpringApplication(environment);
|
bindToSpringApplication(environment);
|
||||||
|
@ -558,16 +558,6 @@ public class SpringApplication {
|
||||||
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
|
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
|
|
||||||
if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
|
|
||||||
Set<String> profiles = new LinkedHashSet<>(Arrays.asList(environment.getActiveProfiles()));
|
|
||||||
if (!profiles.containsAll(this.additionalProfiles)) {
|
|
||||||
profiles.addAll(this.additionalProfiles);
|
|
||||||
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
|
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
|
||||||
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
|
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
|
||||||
Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
|
Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
|
||||||
|
|
|
@ -19,6 +19,8 @@ package org.springframework.boot.context.config;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -34,6 +36,8 @@ import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnvironmentPostProcessor} that loads and applies {@link ConfigData} to Spring's
|
* {@link EnvironmentPostProcessor} that loads and applies {@link ConfigData} to Spring's
|
||||||
|
@ -41,6 +45,7 @@ import org.springframework.core.log.LogMessage;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
*/
|
*/
|
||||||
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||||
|
@ -99,6 +104,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||||
catch (UseLegacyConfigProcessingException ex) {
|
catch (UseLegacyConfigProcessingException ex) {
|
||||||
this.logger.debug(LogMessage.format("Switching to legacy config file processing [%s]",
|
this.logger.debug(LogMessage.format("Switching to legacy config file processing [%s]",
|
||||||
ex.getConfigurationProperty()));
|
ex.getConfigurationProperty()));
|
||||||
|
configureAdditionalProfiles(environment, additionalProfiles);
|
||||||
postProcessUsingLegacyApplicationListener(environment, resourceLoader);
|
postProcessUsingLegacyApplicationListener(environment, resourceLoader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +115,15 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||||
additionalProfiles, this.environmentUpdateListener);
|
additionalProfiles, this.environmentUpdateListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void configureAdditionalProfiles(ConfigurableEnvironment environment,
|
||||||
|
Collection<String> additionalProfiles) {
|
||||||
|
if (!CollectionUtils.isEmpty(additionalProfiles)) {
|
||||||
|
Set<String> profiles = new LinkedHashSet<>(additionalProfiles);
|
||||||
|
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
|
||||||
|
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
|
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
|
||||||
ResourceLoader resourceLoader) {
|
ResourceLoader resourceLoader) {
|
||||||
getLegacyListener().addPropertySources(environment, resourceLoader);
|
getLegacyListener().addPropertySources(environment, resourceLoader);
|
||||||
|
|
|
@ -147,6 +147,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @author Artsiom Yudovin
|
* @author Artsiom Yudovin
|
||||||
* @author Marten Deinum
|
* @author Marten Deinum
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
*/
|
*/
|
||||||
@ExtendWith(OutputCaptureExtension.class)
|
@ExtendWith(OutputCaptureExtension.class)
|
||||||
class SpringApplicationTests {
|
class SpringApplicationTests {
|
||||||
|
@ -604,6 +605,17 @@ class SpringApplicationTests {
|
||||||
assertThat(environment.getActiveProfiles()).containsExactly("bar", "spam", "foo");
|
assertThat(environment.getActiveProfiles()).containsExactly("bar", "spam", "foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void includeProfilesOrder() {
|
||||||
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||||
|
application.setEnvironment(environment);
|
||||||
|
this.context = application.run("--spring.profiles.active=bar,spam", "--spring.profiles.include=foo");
|
||||||
|
// Since Boot 2.4 included profiles should always be last
|
||||||
|
assertThat(environment.getActiveProfiles()).containsExactly("bar", "spam", "foo");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void addProfilesOrderWithProperties() {
|
void addProfilesOrderWithProperties() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
|
|
|
@ -48,6 +48,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class ConfigDataEnvironmentPostProcessorTests {
|
class ConfigDataEnvironmentPostProcessorTests {
|
||||||
|
@ -82,6 +83,7 @@ class ConfigDataEnvironmentPostProcessorTests {
|
||||||
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
|
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
|
||||||
verify(this.configDataEnvironment).processAndApply();
|
verify(this.configDataEnvironment).processAndApply();
|
||||||
assertThat(this.resourceLoaderCaptor.getValue()).isInstanceOf(DefaultResourceLoader.class);
|
assertThat(this.resourceLoaderCaptor.getValue()).isInstanceOf(DefaultResourceLoader.class);
|
||||||
|
assertThat(this.environment.getActiveProfiles()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -93,6 +95,7 @@ class ConfigDataEnvironmentPostProcessorTests {
|
||||||
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
|
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
|
||||||
verify(this.configDataEnvironment).processAndApply();
|
verify(this.configDataEnvironment).processAndApply();
|
||||||
assertThat(this.resourceLoaderCaptor.getValue()).isSameAs(resourceLoader);
|
assertThat(this.resourceLoaderCaptor.getValue()).isSameAs(resourceLoader);
|
||||||
|
assertThat(this.environment.getActiveProfiles()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -103,6 +106,7 @@ class ConfigDataEnvironmentPostProcessorTests {
|
||||||
verify(this.postProcessor).getConfigDataEnvironment(any(), any(), this.additionalProfilesCaptor.capture());
|
verify(this.postProcessor).getConfigDataEnvironment(any(), any(), this.additionalProfilesCaptor.capture());
|
||||||
verify(this.configDataEnvironment).processAndApply();
|
verify(this.configDataEnvironment).processAndApply();
|
||||||
assertThat(this.additionalProfilesCaptor.getValue()).containsExactly("dev");
|
assertThat(this.additionalProfilesCaptor.getValue()).containsExactly("dev");
|
||||||
|
assertThat(this.environment.getActiveProfiles()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -115,6 +119,21 @@ class ConfigDataEnvironmentPostProcessorTests {
|
||||||
this.postProcessor.postProcessEnvironment(this.environment, this.application);
|
this.postProcessor.postProcessEnvironment(this.environment, this.application);
|
||||||
verifyNoInteractions(this.configDataEnvironment);
|
verifyNoInteractions(this.configDataEnvironment);
|
||||||
verify(legacyListener).addPropertySources(eq(this.environment), any(DefaultResourceLoader.class));
|
verify(legacyListener).addPropertySources(eq(this.environment), any(DefaultResourceLoader.class));
|
||||||
|
assertThat(this.environment.getActiveProfiles()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void postProcessEnvironmentWhenHasAdditionalProfilesViaProgrammaticallySettingAndUseLegacyProcessing() {
|
||||||
|
this.application.setAdditionalProfiles("dev");
|
||||||
|
ConfigDataEnvironmentPostProcessor.LegacyConfigFileApplicationListener legacyListener = mock(
|
||||||
|
ConfigDataEnvironmentPostProcessor.LegacyConfigFileApplicationListener.class);
|
||||||
|
willThrow(new UseLegacyConfigProcessingException(null)).given(this.postProcessor)
|
||||||
|
.getConfigDataEnvironment(any(), any(), any());
|
||||||
|
willReturn(legacyListener).given(this.postProcessor).getLegacyListener();
|
||||||
|
this.postProcessor.postProcessEnvironment(this.environment, this.application);
|
||||||
|
verifyNoInteractions(this.configDataEnvironment);
|
||||||
|
verify(legacyListener).addPropertySources(eq(this.environment), any(DefaultResourceLoader.class));
|
||||||
|
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
*/
|
*/
|
||||||
@ExtendWith(UseLegacyProcessing.class)
|
@ExtendWith(UseLegacyProcessing.class)
|
||||||
class ConfigFileApplicationListenerLegacyReproTests {
|
class ConfigFileApplicationListenerLegacyReproTests {
|
||||||
|
@ -167,6 +168,17 @@ class ConfigFileApplicationListenerLegacyReproTests {
|
||||||
assertVersionProperty(this.context, "A", "C", "A");
|
assertVersionProperty(this.context, "A", "C", "A");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void additionalProfilesViaProgrammaticallySetting() {
|
||||||
|
// gh-25704
|
||||||
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
application.setAdditionalProfiles("dev");
|
||||||
|
this.context = application.run();
|
||||||
|
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("dev"))).isTrue();
|
||||||
|
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
|
||||||
|
}
|
||||||
|
|
||||||
private void assertVersionProperty(ConfigurableApplicationContext context, String expectedVersion,
|
private void assertVersionProperty(ConfigurableApplicationContext context, String expectedVersion,
|
||||||
String... expectedActiveProfiles) {
|
String... expectedActiveProfiles) {
|
||||||
assertThat(context.getEnvironment().getActiveProfiles()).isEqualTo(expectedActiveProfiles);
|
assertThat(context.getEnvironment().getActiveProfiles()).isEqualTo(expectedActiveProfiles);
|
||||||
|
|
|
@ -70,6 +70,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
* @author Scott Frederick
|
* @author Scott Frederick
|
||||||
|
* @author Nguyen Bao Sach
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ExtendWith({ OutputCaptureExtension.class, UseLegacyProcessing.class })
|
@ExtendWith({ OutputCaptureExtension.class, UseLegacyProcessing.class })
|
||||||
|
@ -1150,6 +1151,46 @@ class ConfigFileApplicationListenerTests {
|
||||||
assertThat(this.environment.getProperty("fourth.property")).isNull();
|
assertThat(this.environment.getProperty("fourth.property")).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void additionalProfilesCanBeIncludedFromProgrammaticallySetting() {
|
||||||
|
// gh-25704
|
||||||
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
application.setAdditionalProfiles("dev");
|
||||||
|
this.context = application.run();
|
||||||
|
// Active profile should win over default
|
||||||
|
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void twoAdditionalProfilesCanBeIncludedFromProgrammaticallySetting() {
|
||||||
|
// gh-25704
|
||||||
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
application.setAdditionalProfiles("other", "dev");
|
||||||
|
this.context = application.run();
|
||||||
|
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void includeProfilesOrder() {
|
||||||
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
this.context = application.run("--spring.profiles.active=bar,spam", "--spring.profiles.include=foo");
|
||||||
|
// Before Boot 2.4 included profiles should always be first
|
||||||
|
assertThat(this.context.getEnvironment().getActiveProfiles()).containsExactly("foo", "bar", "spam");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addProfilesOrder() {
|
||||||
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
application.setAdditionalProfiles("foo");
|
||||||
|
this.context = application.run("--spring.profiles.active=bar,spam");
|
||||||
|
// Before Boot 2.4 additional profiles should always be first
|
||||||
|
assertThat(this.context.getEnvironment().getActiveProfiles()).containsExactly("foo", "bar", "spam");
|
||||||
|
}
|
||||||
|
|
||||||
private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
|
private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
|
||||||
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {
|
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue