1

About Spring Framework 3.x and 4.x (nothing about Spring Boot ) if my memory does not fail me, I remember when the active profiles are declared programmatically then the refresh method must be called, it after of the profiles declaration, otherwise the profiles are not reflected when Spring is running its own Application Context.

It is reflected at:

Code from the shared answer

final AnnotationConfigApplicationContext appContext =  new AnnotationConfigApplicationContext();
appContext.getEnvironment().setActiveProfiles( "myProfile" );
appContext.register( com.initech.ReleaserConfig.class );
appContext.refresh(); <--- must be executed after of the profiles declaration

Now with Spring Framework 6 for academic purposes I tried the following:

    ConfigurableApplicationContext ctx =
            new AnnotationConfigApplicationContext("com.manuel.jordan.config");
    ctx.getEnvironment().setDefaultProfiles("default", "dev");
    ctx.getEnvironment().setActiveProfiles("jdbc", "mysql");

As you can see the refresh method was not executed, it to demonstrate that the active profiles were ignored. But it works, through the following code it was confirmed

for(String activeProfile : ctx.getEnvironment().getActiveProfiles()) {
    System.out.println(" " + activeProfile);
}

and even more, the constructor code with the String parameter of the AnnotationConfigApplicationContext is:

/**
 * Create a new AnnotationConfigApplicationContext, scanning for components
 * in the given packages, registering bean definitions for those components,
 * and automatically refreshing the context.
 * @param basePackages the packages to scan for component classes
 */
public AnnotationConfigApplicationContext(String... basePackages) {
    this();
    scan(basePackages);
    refresh();  <--------------
}

As you can see the refresh method is executed but remember that this constructor execution happens before of the setActiveProfiles execution.

Therefore

Question

  • Why the active profiles declared programmatically are working if the refresh method was not executed?

Even more, like a simple plus, if is executed as:

    ConfigurableApplicationContext ctx =
            new AnnotationConfigApplicationContext("com.manuel.jordan.config");
    ctx.getEnvironment().setDefaultProfiles("default", "dev");
    ctx.getEnvironment().setActiveProfiles("jdbc", "mysql");
    ctx.refresh(); <---

Arises

java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at org.springframework.context.support.GenericApplicationContext.refreshBeanFactory (GenericApplicationContext.java:293)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory (AbstractApplicationContext.java:672)
    at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:554)
    at com.manuel.jordan.main.Main.main (Main.java:28)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:279)
    at java.lang.Thread.run (Thread.java:833)
Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
  • 2
    "But it works, through the following code it was confirmed" - that code actually confirms nothing: you are just modifying internal state of `AbstractEnvironment` and checking it's state has been changed, that doesn't prove profiles have been actually applied. – Andrey B. Panfilov Feb 14 '23 at 02:11
  • @AndreyB.Panfilov agree, one thing is see the profile(s) declared and other is confirm if they were really applied or not. Consider to write and expand your answer to mark it as valid. Thanks – Manuel Jordan Feb 14 '23 at 17:00
  • alternatives: 1. `AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();` 2. `AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(new DefaultListableBeanFactory());` ...`ctx.scan("com.example");ctx.getEnvironment().setActiveProfiles("jdbc", "mysql"); ctx.refresh();//!` – xerx593 Apr 25 '23 at 22:37

0 Answers0