1. Overview
In this tutorial, we’ll show how to programmatically restart a Spring Boot application.
Restarting our application can be very handy in some cases:
- Reloading config files upon changing some parameter
- Changing the currently active profile at runtime
- Re-initializing the application context for any reason
While this article covers the functionality of restarting a Spring Boot application, note that we also have a great tutorial about shutting down Spring Boot applications.
Now, let’s explore different ways we can implement the restart of a Spring Boot application.
2. Restart by Creating a New Context
We can restart our application by closing the application context and creating a new context from scratch. Although this approach is quite simple, there are some delicate details we have to be careful with to make it work.
Let’s see how to implement this in the main method of our Spring Boot app:
@SpringBootApplication
public class Application {
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
public static void restart() {
ApplicationArguments args = context.getBean(ApplicationArguments.class);
Thread thread = new Thread(() -> {
context.close();
context = SpringApplication.run(Application.class, args.getSourceArgs());
});
thread.setDaemon(false);
thread.start();
}
}
As we can see in the above example, it’s important to recreate the context in a separate non-daemon thread — this way we prevent the JVM shutdown, triggered by the close method, from closing our application. Otherwise, our application would stop since the JVM doesn’t wait for daemon threads to finish before terminating them.
Additionally, let’s add a REST endpoint through which we can trigger the restart:
@RestController
public class RestartController {
@PostMapping("/restart")
public void restart() {
Application.restart();
}
}
Here, we’ve added a controller with a mapping method that invokes our restart method.
We can then call our new endpoint to restart the application:
curl -X POST localhost:port/restart
Of course, if we add an endpoint like this in a real-life application, we’ll have to secure it as well.
3. Actuator’s Restart Endpoint
Another way to restart our application is to use the built-in RestartEndpoint from Spring Boot Actuator.
First, let’s add the required Maven dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
Next, we have to enable the built-in restart endpoint in our application.properties file:
management.endpoint.restart.enabled=true
Now that we have set up everything, we can inject the Restart**Endpoint into our service:
@Service
public class RestartService {
@Autowired
private RestartEndpoint restartEndpoint;
public void restartApp() {
restartEndpoint.restart();
}
}
In the above code, we are using the RestartEndpoint bean to restart our application. This is a nice way of restarting because we only have to call one method that does all the work.
As we can see, using the RestartEndpoint is a simple way to restart our application. On the other side, there is a drawback with this approach because it requires us to add the mentioned libraries. If we aren’t using them already, this might be too much overhead for only this functionality. In that case, we can stick to the manual approach from the previous section since it requires only a few more lines of code.
4. Refreshing the Application Context
In some cases, we can reload the application context by calling its refresh method.
Although this method might sound promising, only some application context types support refreshing an already initialized context. For example, FileSystemXmlApplicationContext, GroovyWebApplicationContext, and a few others support it.
Unfortunately, if we try this in a Spring Boot web application, we will get the following error:
java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts:
just call 'refresh' once
Finally, although there are some context types that support multiple refreshes, we should avoid doing this. The reason is that the refresh method is designed as an internal method used by the framework to initialize the application context.
5. Conclusion
In this article, we explored a number of different ways how to restart a Spring Boot application programmatically.
As always, we can find the source code for the examples over on GitHub.