In this blog, we will how to shutdown a Spring Boot Application
programmatically.
There are several methods available to programmatically shut down a Spring Boot application.
There are several methods available to programmatically shut down a Spring Boot application.
Close the application context
We can release all resources and locks by using the close() method of the
ApplicationContext.
Let's create a controller and GET endpoint /close which simply calls close() and closes down the application. Here we are using the autowire approach to get the ApplicationContext.
This method takes two parameters, ApplicationContext and ExitCodeGenerator. We can autowire the ApplicationContext and convert it to a ConfigurableApplicationContext.
The ExitCodeGenerator class returns the exit code which can be passed to the System.exit() method to shut down the application programmatically.
Using java 8 lambda expression, we can update the ExitCodeGenerator class logic like below.
If you are not using the spring actuator library in pom.xml, add the below Mavan dependency.
By default, the shutdown endpoint is disabled due to security concerns. You need to explicitly enable it. To enable, add the following to your application.properties or application.yml file.
Now do a Maven update and run the project. Once your application is started, make a POST request to /actuator/shutdown to shut down the application.
((ConfigurableApplicationContext) context).close();
Use the @PreDestroy annotation
We can use the @PreDestroy annotation which gets called when a bean gets destroyed. Mostly the logic to release/close the resource or connection is written inside the @PreDestory method.Get the current ApplicationContext
We can get the current ApplicationContext by autowrie or by implementing applicationcontextaware.Let's create a controller and GET endpoint /close which simply calls close() and closes down the application. Here we are using the autowire approach to get the ApplicationContext.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
@Controller
public class EventController {
@Autowired
private ApplicationContext context;
@GetMapping("/close")
public void shutdownContext() {
((ConfigurableApplicationContext) context).close();
}
}
SpringApplication exit
SpringApplication class, which runs our main class of spring boot application provides a static exit() method for shutting down the application.This method takes two parameters, ApplicationContext and ExitCodeGenerator. We can autowire the ApplicationContext and convert it to a ConfigurableApplicationContext.
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
@Controller
public class EventController {
@Autowired
private ApplicationContext context;
@GetMapping("/close")
public void closeTheApplication() {
ConfigurableApplicationContext ctx = ((ConfigurableApplicationContext) context);
int exitCode = SpringApplication.exit(context, new ExitCodeGenerator() {
@Override
public int getExitCode() {
return 0;
}
});
System.out.println("Shutting-down the application with exit code " +
exitCode);
System.exit(exitCode);
}
}
The ExitCodeGenerator class returns the exit code which can be passed to the System.exit() method to shut down the application programmatically.
Using java 8 lambda expression, we can update the ExitCodeGenerator class logic like below.
//using java8
@GetMapping("/close")
public void closeTheApplication() {
ConfigurableApplicationContext ctx = ((ConfigurableApplicationContext) context);
int exitCode = SpringApplication.exit(ctx, () - > 0);
System.out.println("Shutting-down the application with exit code " + exitCode);
System.exit(exitCode);
}
What is a shutdown hook?
A shutdown hook is a piece of code that is run when a program is shutting down. This can be used to clean up any resources that were opened, or to save any data that needs to be saved.How to add a shutdown hook to a Spring Boot application?
Adding a shutdown hook to a Spring Boot application is easy. You just need to add a class that implements the org.springframework.boot.ExitCodeGenerator interface. The ExitCodeGenerator interface has a single method, generateExitCode(), that returns the exit code that the application should generate. You can then add the Shutdown Hook Runner to your application's run configuration.Using Spring Actuator
Till now we have created a controller and added an endpoint which closes the application context or exits using System.exit() but the spring actuator provides a shutdown endpoint to do the same in a graceful manner.If you are not using the spring actuator library in pom.xml, add the below Mavan dependency.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
By default, the shutdown endpoint is disabled due to security concerns. You need to explicitly enable it. To enable, add the following to your application.properties or application.yml file.
management.endpoints.web.exposure.include=shutdown
management.endpoint.shutdown.enabled=true
management.endpoint.shutdown.enabled=true
management.endpoint.shutdown.sensitive=true
Now do a Maven update and run the project. Once your application is started, make a POST request to /actuator/shutdown to shut down the application.
curl -X POST http://localhost:8080/actuator/shutdown
How to secure the endpoint
All the controller exposed urls must be secured properly to avoid or prevent the risk in production which is very important.Add the spring security dependency to pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>