Spring Boot version: 2.4
After upgrading to Spring Boot 2.4 from Spring Boot 2.3 I noticed that the ordering has changed of how SpringApplication.additionalProfiles
are merged with the ConfigurableEnvironment.getActiveProfiles()
.
With Spring Boot 2.3 the ordering is: additional profiles, active profiles With Spring Boot 2.4 the ordering is: active profiles, additional profiles
When running the test application below with Spring Boot 2.3
and Spring Boot 2.4
you can see this easily in the logging:
Spring Boot 2.3.10.RELEASE profiles ordering: additional, active
Spring Boot 2.4.5 profiles ordering: active, additional
This ordering change also affects the @ActiveProfiles
test annotation. The profiles activated via the annotation now also have a lesser priority then the additional profiles (if you are wondering how we are setting additional profiles in combination with running tests, this is because we are actually using a ApplicationStartingEvent
ApplicationListener
, registered via the spring.factories
to call the SpringApplication.setAdditionalProfiles()
with an environment specific profile).
This change has the effect that our application-{profile}.yml
property sources are now getting different precedence, which caused issues for us when running tests, because property values where not being overridden in the expected order anymore.
I wonder if this change in ordering was an intentional one or that it is a mistake. I couldn't find any remarks regarding the change in the changelog. I have also read the https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide but I couldn't distill this information from that document as well. If the ordering change is intentional then I recommend adding a note in the migration guide.
Test code:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.Environment;
@SpringBootApplication
public class AdditionalProfilesReproductionApplication implements CommandLineRunner {
public static void main(String[] args) {
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "active");
SpringApplication app = new SpringApplication(AdditionalProfilesReproductionApplication.class);
app.setAdditionalProfiles("additional");
app.run(args);
}
@Autowired
Environment environment;
@Override
public void run(String... args) throws Exception {
System.out.println("Profiles: " + String.join(", ", environment.getActiveProfiles()));
}
}
Comment From: nguyensach
@mzeijen When I did this PR, I realized this issue like you. But I don't know whether this ordering change was an intentional one or that it is a mistake.
You can fix this issue by using legacy processing
@wilkinsona I think that this ordering change is due to bellow.
- With Spring Boot 2.4 without using legacy processing
https://github.com/spring-projects/spring-boot/blob/0c8f4e5ab3661f84227148ce83d91c083242deeb/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/Profiles.java#L83
- With Spring Boot 2.3 or Spring Boot 2.4 using legacy processing
https://github.com/spring-projects/spring-boot/blob/0c8f4e5ab3661f84227148ce83d91c083242deeb/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java#L356-L363
How would you think about this issue?
Comment From: mzeijen
@nguyensach
I tried activating legacy processing (by setting spring.config.use-legacy-processing
to true
in the application.properties
or via the System properties before starting the application) but that didn't restore the old behaviour.
From what I can see the ordering of the additional profiles and the active profiles happens in the SpringApplication, and I don't see that the legacy processing has any influence on it.
In Spring Boot 2.3 it is done in the configureProfiles
method:
https://github.com/spring-projects/spring-boot/blob/32e846da2f60ad1da9a67f3ed5bcdab61a6027f6/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L519-L523
In Spring Boot 2.4 it is done in the configureAdditionalProfiles
method:
https://github.com/spring-projects/spring-boot/blob/7caf238a90fbb67a23666ba6ed3384011af01378/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java#L560-L568
The difference is that in Spring Boot 2.3 the list of profiles is created with this.additionalProfiles
as initial fill where in Spring Boot 2.4 the environment.getActiveProfiles()
is used as initial fill.
Comment From: nguyensach
@mzeijen I'm so sorry!
According to the below test case, it seems this ordering change was an intentional one.
https://github.com/spring-projects/spring-boot/blob/a65438055222518931c52501402931b6274aaaff/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java#L594-L604
Comment From: nguyensach
@mzeijen
Although since Spring Boot 2.4 this ordering change was an intentional one, it needs to restore the old behavior when using legacy processing.
If my PR https://github.com/spring-projects/spring-boot/pull/25817 is merged, it will restore the old behavior when using legacy processing as the bellow test case.
https://github.com/spring-projects/spring-boot/pull/25817/files#diff-82a4d071283a2194fc5c0e8cffbdddbeda4e53d4e5676138f93b46fcaa16e516R1184-R1193
Comment From: mzeijen
@nguyensach Thanks for clearing that up. Can you also make sure the intentional ordering change is documented in the changelog so that it doesn't surprise others like me? Thanks.