Programmatically shut down Spring Boot application
Solution 1:
Closing a SpringApplication
basically means closing the underlying ApplicationContext
. The SpringApplication#run(String...)
method gives you that ApplicationContext
as a ConfigurableApplicationContext
. You can then close()
it yourself.
For example,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to shut down...
ctx.close();
}
}
Alternatively, you can use the static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
helper method to do it for you. For example,
@SpringBootApplication
public class Example {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
// ...determine it's time to stop...
int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
// no errors
return 0;
}
});
// or shortened to
// int exitCode = SpringApplication.exit(ctx, () -> 0);
System.exit(exitCode);
}
}
Solution 2:
The simplest way would be to inject the following object where you need to initiate the shutdown
ShutdownManager.java
import org.springframework.context.ApplicationContext;
import org.springframework.boot.SpringApplication;
@Component
class ShutdownManager {
@Autowired
private ApplicationContext appContext;
/*
* Invoke with `0` to indicate no error or different code to indicate
* abnormal exit. es: shutdownManager.initiateShutdown(0);
**/
public void initiateShutdown(int returnCode){
SpringApplication.exit(appContext, () -> returnCode);
}
}
Solution 3:
This works, even done is printed.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
So adding .close()
after run()
Explanation:
public ConfigurableApplicationContext run(String... args)
Run the Spring application, creating and refreshing a new ApplicationContext. Parameters:
args
- the application arguments (usually passed from a Java main method)Returns: a running ApplicationContext
and:
void close()
Close this application context, releasing all resources and locks that the implementation might hold. This includes destroying all cached singleton beans. Note: Does not invoke close on a parent context; parent contexts have their own, independent lifecycle.This method can be called multiple times without side effects: Subsequent close calls on an already closed context will be ignored.
So basically, it will not close the parent context, that's why the VM doesn't quit.
Solution 4:
This will make sure that the SpringBoot application is closed properly and the resources are released back to the operating system,
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}