In my Spring Boot application I need to wait until the (default Tomcat) web server is fully initialized and ready to take traffic before I send messages to other applications telling them to send HTTP requests to me (specifically a monitoring system that hits my /health
).
I've tried putting the logic that sends messages to other applications in a ApplicationListener<ContextRefreshedEvent>
but it's still too early. The other applications try to make requests to me and fail. Right now I've put a delay in the onApplicationEvent
and that works but it's hacky and racy.
I've also tried adding a ServletContextInitializer
but that fired even earlier.
I'm assuming that I'll need to use a Tomcat API but I wanted to see if there was something in the Boot API for this.
The simplest thing to do is to send the message once SpringApplication.run()
has returned. This method won't return until Tomcat (or any other supported embedded container) is fully started and listening on the configured port(s). However, while this is simple, it's not a very neat approach as it mixes the concerns of your main configuration class and some of your application's runtime logic.
Instead, you can use a SpringApplicationRunListener
. finished()
will not be called until Tomcat is fully started and listening on the configured port.
Create a file named src/main/resources/META-INF/spring.factories
listing your run listener. For example:
org.springframework.boot.SpringApplicationRunListener=com.example.MyRunListener
Create your run listener with the required constructor and implement SpringApplicationRunListener
. For example:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class MyRunListener implements SpringApplicationRunListener {
public MyRunListener(SpringApplication application, String[] args) { }
@Override
public void starting() { }
@Override
public void environmentPrepared(ConfigurableEnvironment environment) { }
@Override
public void contextPrepared(ConfigurableApplicationContext context) { }
@Override
public void contextLoaded(ConfigurableApplicationContext context) { }
@Override
public void started(ConfigurableApplicationContext context) {
// Send message; Tomcat is running and listening on the configured port(s)
}
@Override
public void running(ConfigurableApplicationContext context) { }
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) { }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With