Is there a clean way to detect when a spring-boot application is stopped and perform some action before? Kind of CommandLineRunner for stopping a service
Thanks in advance
Is there a clean way to detect when a spring-boot application is stopped and perform some action before? Kind of CommandLineRunner for stopping a service
Thanks in advance
Similar to ApplicationReadyEvent
you can use ContextClosedEvent
:
@Component
public class ContextClosedEventListener {
@EventListener(ContextClosedEvent.class)
public void onContextClosedEvent(ContextClosedEvent contextClosedEvent) {
System.out.println("ContextClosedEvent occurred at millis: " + contextClosedEvent.getTimestamp());
}
}
I've come up with this solution. If you have better one, feel free to share
@Component
public class PortalServiceLifeCycle implements CommandLineRunner {
static final Logger LOGGER = LoggerFactory.getLogger(PortalServiceLifeCycle.class);
@Override
public void run(String... arg0) throws Exception {
LOGGER.info("###START FROM THE LIFECYCLE###");
}
@PreDestroy
public void onExit() {
LOGGER.info("###STOP FROM THE LIFECYCLE###");
}
}
Don't know if you have resolve this problem perfectly. I meet this issue recently, and have got a solution that a little different.
Firstly, my Spring boot Application is a Tomcat embedded one. (The second method of this issue doesn't depends on the web structure. don't mad, my friend.) In this case, it's naturally to get the idea of catch the stop event by register a listener. I do it like this,
@WebListener
public class HelloListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("HelloListener contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("HelloListener contextDestroyed");
}
}
and, at the same time, add the annotation @ServletComponentScan on your Application class.
Surely, there are some other ways to register a ServletContextListener, and once you registered it, you can get the stop event in the contextDestroyed function.
BUT, that don't match my issue very much. I must catch the stop event BEFORE the Spring Beans being destroyed. And here comes the second solution.
modify your application main method like the follow:
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addListeners(new MyListener());
application.run(args);
and provide the defination of class MyListener:
class MyListener implements ApplicationListener<ContextClosedEvent>{
@Override
public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
// your code here
}
}
NOTE: the second solution has nothing to do with Tomcat or other web container. The ContextClosedEvent isn't introduced in the Spring document, but I found it in the source, it's very useful i think.
I will be very glad if this can help some one.
It depends what you want to do but one thing you could do is have a bean that implements SmartLifecycle
and implement the stop
method. Whenever the context is being stopped, you'd get a callback. Note that it does not necessarily means that the process is shutting down. If you want to invoke some code when that happens, I'd register a shutdown hook as Sven wrote in a comment.