Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

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 RestartEndpoint 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, FileSystemXmlApplicationContextGroovyWebApplicationContext, 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.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
newest oldest most voted
Notify of
Nick
Guest
Nick

I’ve tried the example “Restart by Creating a New Context” but it only work for first time, at the second time I want to restart the program throw a NullPointerException because the context is null.

Nick
Guest
Nick

Instead of that example. We can use Restarter of Spring Devtools like this:
org.springframework.boot.devtools.restart.Restarter.getInstance().restart()
It works for me. Hope this help.

Loredana Crusoveanu
Editor

Hi Nick,

Thanks for adding the info – very helpful.

Cheers.

Comments are closed on this article!