Skip to content

Commit 5ba2234

Browse files
committed
Add additional profiles into environment when legacy processing is used
In post-processing the given environment of ConfigDataEnvironmentPostProcessor, add SpringApplication's additional profiles that are set by programmatically into environment when legacy processing is used. This commit updates the following areas: - Add configureAdditionalProfiles method into ConfigDataEnvironmentPostProcessor, that add the additional profiles into the given environment. - When legacy processing is used, call configureAdditionalProfiles method to add the additional profiles into the given environment. - Remove unnecessary configureAdditionalProfiles method in SpringApplication. - Supplement unit test for SpringApplicationTests. Closes #25704
1 parent 269fc68 commit 5ba2234

File tree

6 files changed

+107
-29
lines changed

6 files changed

+107
-29
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[])
@@ -373,7 +374,6 @@ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners
373374
ConfigurationPropertySources.attach(environment);
374375
listeners.environmentPrepared(bootstrapContext, environment);
375376
DefaultPropertiesPropertySource.moveToEnd(environment);
376-
configureAdditionalProfiles(environment);
377377
Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
378378
"Environment prefix cannot be set via properties.");
379379
bindToSpringApplication(environment);
@@ -558,16 +558,6 @@ protected void configurePropertySources(ConfigurableEnvironment environment, Str
558558
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
559559
}
560560

561-
private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
562-
if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
563-
Set<String> profiles = new LinkedHashSet<>(Arrays.asList(environment.getActiveProfiles()));
564-
if (!profiles.containsAll(this.additionalProfiles)) {
565-
profiles.addAll(this.additionalProfiles);
566-
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
567-
}
568-
}
569-
}
570-
571561
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
572562
if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
573563
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: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616

1717
package org.springframework.boot.context.config;
1818

19-
import java.util.Arrays;
20-
import java.util.Collection;
21-
import java.util.Collections;
19+
import java.util.*;
2220
import java.util.function.Supplier;
2321

2422
import org.apache.commons.logging.Log;
@@ -34,13 +32,16 @@
3432
import org.springframework.core.io.DefaultResourceLoader;
3533
import org.springframework.core.io.ResourceLoader;
3634
import org.springframework.core.log.LogMessage;
35+
import org.springframework.util.CollectionUtils;
36+
import org.springframework.util.StringUtils;
3737

3838
/**
3939
* {@link EnvironmentPostProcessor} that loads and applies {@link ConfigData} to Spring's
4040
* {@link Environment}.
4141
*
4242
* @author Phillip Webb
4343
* @author Madhura Bhave
44+
* @author Nguyen Bao Sach
4445
* @since 2.4.0
4546
*/
4647
public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
@@ -99,6 +100,7 @@ void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader
99100
catch (UseLegacyConfigProcessingException ex) {
100101
this.logger.debug(LogMessage.format("Switching to legacy config file processing [%s]",
101102
ex.getConfigurationProperty()));
103+
configureAdditionalProfiles(environment, additionalProfiles);
102104
postProcessUsingLegacyApplicationListener(environment, resourceLoader);
103105
}
104106
}
@@ -109,6 +111,15 @@ ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environme
109111
additionalProfiles, this.environmentUpdateListener);
110112
}
111113

114+
private void configureAdditionalProfiles(ConfigurableEnvironment environment,
115+
Collection<String> additionalProfiles) {
116+
if (!CollectionUtils.isEmpty(additionalProfiles)) {
117+
Set<String> profiles = new LinkedHashSet<>(additionalProfiles);
118+
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
119+
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
120+
}
121+
}
122+
112123
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
113124
ResourceLoader resourceLoader) {
114125
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: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,6 @@
1616

1717
package org.springframework.boot.context.config;
1818

19-
import java.io.File;
20-
import java.io.FileOutputStream;
21-
import java.io.OutputStream;
22-
import java.util.Collections;
23-
import java.util.HashMap;
24-
import java.util.List;
25-
import java.util.Map;
26-
import java.util.Properties;
27-
import java.util.stream.Collectors;
28-
import java.util.stream.StreamSupport;
29-
3019
import org.apache.commons.logging.Log;
3120
import org.apache.commons.logging.LogFactory;
3221
import org.apache.logging.log4j.Level;
@@ -46,11 +35,8 @@
4635
import org.springframework.context.annotation.Configuration;
4736
import org.springframework.context.annotation.Profile;
4837
import org.springframework.context.annotation.PropertySource;
49-
import org.springframework.core.env.ConfigurableEnvironment;
50-
import org.springframework.core.env.MapPropertySource;
5138
import org.springframework.core.env.Profiles;
52-
import org.springframework.core.env.SimpleCommandLinePropertySource;
53-
import org.springframework.core.env.StandardEnvironment;
39+
import org.springframework.core.env.*;
5440
import org.springframework.core.io.ByteArrayResource;
5541
import org.springframework.core.io.ClassPathResource;
5642
import org.springframework.core.io.Resource;
@@ -59,6 +45,13 @@
5945
import org.springframework.test.util.ReflectionTestUtils;
6046
import org.springframework.util.StringUtils;
6147

48+
import java.io.File;
49+
import java.io.FileOutputStream;
50+
import java.io.OutputStream;
51+
import java.util.*;
52+
import java.util.stream.Collectors;
53+
import java.util.stream.StreamSupport;
54+
6255
import static org.assertj.core.api.Assertions.assertThat;
6356
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
6457

@@ -70,6 +63,7 @@
7063
* @author Eddú Meléndez
7164
* @author Madhura Bhave
7265
* @author Scott Frederick
66+
* @author Nguyen Bao Sach
7367
*/
7468
@Deprecated
7569
@ExtendWith({ OutputCaptureExtension.class, UseLegacyProcessing.class })
@@ -1150,6 +1144,46 @@ void locationsWithWildcardFilesShouldIgnoreHiddenDirectories() {
11501144
assertThat(this.environment.getProperty("fourth.property")).isNull();
11511145
}
11521146

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

0 commit comments

Comments
 (0)