Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify active profiles and refresh ApplicationContext runtime in a Spring Boot application

I have a Spring boot Web application. The application is configured via java classes using the @Configurable annotation. I have introduced two profiles: 'install', 'normal'. If the install profile is active, none of the Beans that require DB connection is loaded. I want to create a controller where the user can set up the db connection parameters and When it's done I want to switch the active profile from 'install' to 'normal' and refresh the application context, so the Spring can init every bean that needs DB data source.

I can modify the list of active profiles from code, without problems, but when i try to refresh the application context, i get the following exception:

`java.lang.IllegalStateException:
 GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once`

This is how i boot my Spring boot app:

`new SpringApplicationBuilder().sources(MyApp.class)
.profiles("my-profile").build().run(args);` 

Does anybody know how to initiate spring boot app that let's you refresh the app context multiple times ?

like image 364
SaWo Avatar asked Feb 16 '15 12:02

SaWo


People also ask

How do I refresh application context in Spring boot?

You can use: POST to /actuator/env to update the Environment and rebind @ConfigurationProperties and log levels. /actuator/refresh to re-load the boot strap context and refresh the @RefreshScope beans. /actuator/restart to close the ApplicationContext and restart it (disabled by default).

Can I change application properties at runtime Spring boot?

To change properties in a file during runtime, we should place that file somewhere outside the jar. Then we tell Spring where it is with the command-line parameter –spring. config. location=file://{path to file}.

What is the ApplicationContext in Spring boot?

ApplicationContext is a corner stone of a Spring Boot application. It represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata.


1 Answers

You can't just refresh an existing context. You have to close the old one and create a new one. You can see how we do it in Spring Cloud here: https://github.com/spring-cloud/spring-cloud-commons/blob/master/spring-cloud-context/src/main/java/org/springframework/cloud/context/restart/RestartEndpoint.java. If you want to you can include that Endpoint just by adding spring-cloud-context as a dependency, or you can copy the code I guess and use it in your own "endpoint".

Here's the endpoint implementation (some details missing in fields):

@ManagedOperation
public synchronized ConfigurableApplicationContext restart() {
  if (this.context != null) {
    if (this.integrationShutdown != null) {
      this.integrationShutdown.stop(this.timeout);
    }
    this.application.setEnvironment(this.context.getEnvironment());
    this.context.close();
    overrideClassLoaderForRestart();
    this.context = this.application.run(this.args);
  }
  return this.context;
}
like image 143
Dave Syer Avatar answered Sep 30 '22 17:09

Dave Syer