Home » Java » Spring Boot Actuator – how to add custom logic to /shutdown endpoint

Spring Boot Actuator – how to add custom logic to /shutdown endpoint

Posted by: admin December 28, 2021 Leave a comment

Questions:

In my project I started using Spring Boot Actuator. I use /shutdown endpoint to gracefully stop the embedded Tomcat (this works well), but I also need to do some custom logic during shutdown. Is there any way, how to do it?

Answers:

I can think of two ways to perform some logic before shutting down the application:

  1. Registering a Filter, it’s a web application after all.
  2. 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();
}

###

If you make custom ShutdownEndpoint bean, You can add custom logic.

@Component
public class CustomShutdownEndpoint extends ShutdownEndpoint {
    @Override
    public Map<String, Object> invoke() {
        // Add your custom logic here            

        return super.invoke();
    }
}

In this way, you can change any logic spring-boot-actuator Endpoints.