Skip to content

Commit 97fd9a7

Browse files
nguyensachmbhave
authored andcommitted
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
1 parent c50afc6 commit 97fd9a7

File tree

6 files changed

+100
-11
lines changed

6 files changed

+100
-11
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
* @author Madhura Bhave
155155
* @author Brian Clozel
156156
* @author Ethan Rubinson
157+
* @author Nguyen Bao Sach
157158
* @since 1.0.0
158159
* @see #run(Class, String[])
159160
* @see #run(Class[], String[])
@@ -374,7 +375,6 @@ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners
374375
ConfigurationPropertySources.attach(environment);
375376
listeners.environmentPrepared(bootstrapContext, environment);
376377
DefaultPropertiesPropertySource.moveToEnd(environment);
377-
configureAdditionalProfiles(environment);
378378
bindToSpringApplication(environment);
379379
if (!this.isCustomEnvironment) {
380380
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
@@ -557,16 +557,6 @@ protected void configurePropertySources(ConfigurableEnvironment environment, Str
557557
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
558558
}
559559

560-
private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
561-
if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
562-
Set<String> profiles = new LinkedHashSet<>(Arrays.asList(environment.getActiveProfiles()));
563-
if (!profiles.containsAll(this.additionalProfiles)) {
564-
profiles.addAll(this.additionalProfiles);
565-
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
566-
}
567-
}
568-
}
569-
570560
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
571561
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
572562
Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.util.Arrays;
2020
import java.util.Collection;
2121
import java.util.Collections;
22+
import java.util.LinkedHashSet;
23+
import java.util.Set;
2224
import java.util.function.Supplier;
2325

2426
import org.apache.commons.logging.Log;
@@ -34,13 +36,16 @@
3436
import org.springframework.core.io.DefaultResourceLoader;
3537
import org.springframework.core.io.ResourceLoader;
3638
import org.springframework.core.log.LogMessage;
39+
import org.springframework.util.CollectionUtils;
40+
import org.springframework.util.StringUtils;
3741

3842
/**
3943
* {@link EnvironmentPostProcessor} that loads and applies {@link ConfigData} to Spring's
4044
* {@link Environment}.
4145
*
4246
* @author Phillip Webb
4347
* @author Madhura Bhave
48+
* @author Nguyen Bao Sach
4449
* @since 2.4.0
4550
*/
4651
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@@ -99,6 +104,7 @@ void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader
99104
catch (UseLegacyConfigProcessingException ex) {
100105
this.logger.debug(LogMessage.format("Switching to legacy config file processing [%s]",
101106
ex.getConfigurationProperty()));
107+
configureAdditionalProfiles(environment, additionalProfiles);
102108
postProcessUsingLegacyApplicationListener(environment, resourceLoader);
103109
}
104110
}
@@ -109,6 +115,15 @@ ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environme
109115
additionalProfiles, this.environmentUpdateListener);
110116
}
111117

118+
private void configureAdditionalProfiles(ConfigurableEnvironment environment,
119+
Collection<String> additionalProfiles) {
120+
if (!CollectionUtils.isEmpty(additionalProfiles)) {
121+
Set<String> profiles = new LinkedHashSet<>(additionalProfiles);
122+
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
123+
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
124+
}
125+
}
126+
112127
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
113128
ResourceLoader resourceLoader) {
114129
getLegacyListener().addPropertySources(environment, resourceLoader);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
* @author Brian Clozel
148148
* @author Artsiom Yudovin
149149
* @author Marten Deinum
150+
* @author Nguyen Bao Sach
150151
*/
151152
@ExtendWith(OutputCaptureExtension.class)
152153
class SpringApplicationTests {
@@ -604,6 +605,17 @@ void addProfilesOrder() {
604605
assertThat(environment.getActiveProfiles()).containsExactly("bar", "spam", "foo");
605606
}
606607

608+
@Test
609+
void includeProfilesOrder() {
610+
SpringApplication application = new SpringApplication(ExampleConfig.class);
611+
application.setWebApplicationType(WebApplicationType.NONE);
612+
ConfigurableEnvironment environment = new StandardEnvironment();
613+
application.setEnvironment(environment);
614+
this.context = application.run("--spring.profiles.active=bar,spam", "--spring.profiles.include=foo");
615+
// Since Boot 2.4 included profiles should always be last
616+
assertThat(environment.getActiveProfiles()).containsExactly("bar", "spam", "foo");
617+
}
618+
607619
@Test
608620
void addProfilesOrderWithProperties() {
609621
SpringApplication application = new SpringApplication(ExampleConfig.class);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataEnvironmentPostProcessorTests.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
*
4949
* @author Phillip Webb
5050
* @author Madhura Bhave
51+
* @author Nguyen Bao Sach
5152
*/
5253
@ExtendWith(MockitoExtension.class)
5354
class ConfigDataEnvironmentPostProcessorTests {
@@ -82,6 +83,7 @@ void postProcessEnvironmentWhenNoLoaderCreatesDefaultLoaderInstance() {
8283
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
8384
verify(this.configDataEnvironment).processAndApply();
8485
assertThat(this.resourceLoaderCaptor.getValue()).isInstanceOf(DefaultResourceLoader.class);
86+
assertThat(this.environment.getActiveProfiles()).isEmpty();
8587
}
8688

8789
@Test
@@ -93,6 +95,7 @@ void postProcessEnvironmentWhenCustomLoaderUsesSpecifiedLoaderInstance() {
9395
verify(this.postProcessor).getConfigDataEnvironment(any(), this.resourceLoaderCaptor.capture(), any());
9496
verify(this.configDataEnvironment).processAndApply();
9597
assertThat(this.resourceLoaderCaptor.getValue()).isSameAs(resourceLoader);
98+
assertThat(this.environment.getActiveProfiles()).isEmpty();
9699
}
97100

98101
@Test
@@ -103,6 +106,7 @@ void postProcessEnvironmentWhenHasAdditionalProfilesOnSpringApplicationUsesAddit
103106
verify(this.postProcessor).getConfigDataEnvironment(any(), any(), this.additionalProfilesCaptor.capture());
104107
verify(this.configDataEnvironment).processAndApply();
105108
assertThat(this.additionalProfilesCaptor.getValue()).containsExactly("dev");
109+
assertThat(this.environment.getActiveProfiles()).isEmpty();
106110
}
107111

108112
@Test
@@ -115,6 +119,21 @@ void postProcessEnvironmentWhenUseLegacyProcessingSwitchesToLegacyMethod() {
115119
this.postProcessor.postProcessEnvironment(this.environment, this.application);
116120
verifyNoInteractions(this.configDataEnvironment);
117121
verify(legacyListener).addPropertySources(eq(this.environment), any(DefaultResourceLoader.class));
122+
assertThat(this.environment.getActiveProfiles()).isEmpty();
123+
}
124+
125+
@Test
126+
void postProcessEnvironmentWhenHasAdditionalProfilesViaProgrammaticallySettingAndUseLegacyProcessing() {
127+
this.application.setAdditionalProfiles("dev");
128+
ConfigDataEnvironmentPostProcessor.LegacyConfigFileApplicationListener legacyListener = mock(
129+
ConfigDataEnvironmentPostProcessor.LegacyConfigFileApplicationListener.class);
130+
willThrow(new UseLegacyConfigProcessingException(null)).given(this.postProcessor)
131+
.getConfigDataEnvironment(any(), any(), any());
132+
willReturn(legacyListener).given(this.postProcessor).getLegacyListener();
133+
this.postProcessor.postProcessEnvironment(this.environment, this.application);
134+
verifyNoInteractions(this.configDataEnvironment);
135+
verify(legacyListener).addPropertySources(eq(this.environment), any(DefaultResourceLoader.class));
136+
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
118137
}
119138

120139
@Test

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerLegacyReproTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
*
3434
* @author Phillip Webb
3535
* @author Dave Syer
36+
* @author Nguyen Bao Sach
3637
*/
3738
@ExtendWith(UseLegacyProcessing.class)
3839
class ConfigFileApplicationListenerLegacyReproTests {
@@ -167,6 +168,17 @@ void reverseOrderOfProfilesWithYamlAndNoOverride() {
167168
assertVersionProperty(this.context, "A", "C", "A");
168169
}
169170

171+
@Test
172+
void additionalProfilesViaProgrammaticallySetting() {
173+
// gh-25704
174+
SpringApplication application = new SpringApplication(Config.class);
175+
application.setWebApplicationType(WebApplicationType.NONE);
176+
application.setAdditionalProfiles("dev");
177+
this.context = application.run();
178+
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("dev"))).isTrue();
179+
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
180+
}
181+
170182
private void assertVersionProperty(ConfigurableApplicationContext context, String expectedVersion,
171183
String... expectedActiveProfiles) {
172184
assertThat(context.getEnvironment().getActiveProfiles()).isEqualTo(expectedActiveProfiles);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
* @author Eddú Meléndez
7171
* @author Madhura Bhave
7272
* @author Scott Frederick
73+
* @author Nguyen Bao Sach
7374
*/
7475
@Deprecated
7576
@ExtendWith({ OutputCaptureExtension.class, UseLegacyProcessing.class })
@@ -1150,6 +1151,46 @@ void locationsWithWildcardFilesShouldIgnoreHiddenDirectories() {
11501151
assertThat(this.environment.getProperty("fourth.property")).isNull();
11511152
}
11521153

1154+
@Test
1155+
void additionalProfilesCanBeIncludedFromProgrammaticallySetting() {
1156+
// gh-25704
1157+
SpringApplication application = new SpringApplication(Config.class);
1158+
application.setWebApplicationType(WebApplicationType.NONE);
1159+
application.setAdditionalProfiles("dev");
1160+
this.context = application.run();
1161+
// Active profile should win over default
1162+
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
1163+
}
1164+
1165+
@Test
1166+
void twoAdditionalProfilesCanBeIncludedFromProgrammaticallySetting() {
1167+
// gh-25704
1168+
SpringApplication application = new SpringApplication(Config.class);
1169+
application.setWebApplicationType(WebApplicationType.NONE);
1170+
application.setAdditionalProfiles("other", "dev");
1171+
this.context = application.run();
1172+
assertThat(this.context.getEnvironment().getProperty("my.property")).isEqualTo("fromdevpropertiesfile");
1173+
}
1174+
1175+
@Test
1176+
void includeProfilesOrder() {
1177+
SpringApplication application = new SpringApplication(Config.class);
1178+
application.setWebApplicationType(WebApplicationType.NONE);
1179+
this.context = application.run("--spring.profiles.active=bar,spam", "--spring.profiles.include=foo");
1180+
// Before Boot 2.4 included profiles should always be first
1181+
assertThat(this.context.getEnvironment().getActiveProfiles()).containsExactly("foo", "bar", "spam");
1182+
}
1183+
1184+
@Test
1185+
void addProfilesOrder() {
1186+
SpringApplication application = new SpringApplication(Config.class);
1187+
application.setWebApplicationType(WebApplicationType.NONE);
1188+
application.setAdditionalProfiles("foo");
1189+
this.context = application.run("--spring.profiles.active=bar,spam");
1190+
// Before Boot 2.4 additional profiles should always be first
1191+
assertThat(this.context.getEnvironment().getActiveProfiles()).containsExactly("foo", "bar", "spam");
1192+
}
1193+
11531194
private Condition<ConfigurableEnvironment> matchingPropertySource(final String sourceName) {
11541195
return new Condition<ConfigurableEnvironment>("environment containing property source " + sourceName) {
11551196

0 commit comments

Comments
 (0)