Spring Boot Actuator - how to add custom logic to /shutdown endpoint
I can think of two ways to perform some logic before shutting down the application:
- Registering a
Filter
, it's a web application after all. - Intercepting the
invoke
method using the@Before
advice
Servlet Filter
Since /shutdown
is a Servlet endpoint, you can register a Filter
to run before the /shutdown
endpoint gets called:
public class ShutdownFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
// Put your logic here
filterChain.doFilter(request, response);
}
}
Also don't forget to register it:
@Bean
@ConditionalOnProperty(value = "endpoints.shutdown.enabled", havingValue = "true")
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new ShutdownFilter());
registrationBean.setUrlPatterns(Collections.singleton("/shutdown"));
return registrationBean;
}
Defining an @Aspect
If you send a request to the /shutdown
endpoint, assuming the shutdown endpoint is enabled and security does not block the request, the invoke
method will be called. You can define an @Aspect
to intercept this method call and put your logic there:
@Aspect
@Component
public class ShutdownAspect {
@Before("execution(* org.springframework.boot.actuate.endpoint.ShutdownEndpoint.invoke())")
public void runBeforeShutdownHook() {
// Put your logic here
System.out.println("Going to shutdown...");
}
}
Also don't forget to enable the AspectJAutoProxy
:
@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Application { ... }
And spring-aspects
dependency:
compile 'org.springframework:spring-aspects'
When it's invoked, the shutdown endpoint calls close()
on the application context. This means that all of the usual mechanisms for running some custom logic during close processing are available.
For example, you could add a bean to the application context that implements DisposableBean
or use the destroyMethod
attribute of @Bean
when you declare a bean via Java config:
@Bean(destroyMethod="whateverYouWant")
public void Foo {
return new Foo();
}