I need that my Springboot application knows when its web server (Tomcat) is up
I tried something using @WebListener
, ServletContextListener
and @ServletComponentScan
@WebListener
public class MyServletContextListener implements ServletContextListener {
private static final Logger LOG = getLogger(MyServletContextListener.class);
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
LOG.info("Starting up!");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
LOG.info("Shutting down!");
}
}
It seems to work: my listener is correctly notified.
However, I realized that if I try to join my Web server from this listener, the call fails
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
URI uri = HttpHelper.newAnyUriBuilder("localhost", 8181, false).path("actuator/health").build();
new RestAPI().GET(uri); /// Throws
LOG.info("Starting up!");
}
meaning that the web server is not completely UP AND READY
If I postpone the call, it succeeds:
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
new Thread(new Runnable() {
@Override
public void run() {
try { Thread.sleep(1000); } catch (InterruptedException e) {} /// dirty but this is just a sample
URI uri = HttpHelper.newAnyUriBuilder("localhost", 8181, false).path("actuator/health").build();
new RestAPI().GET(uri); /// does not throw anymore
LOG.info("Starting up!");
}
}).start();
}
Any idea how can I be notified correctly?
Thanks
CodePudding user response:
If you are using Spring Boot's embedded Tomcat server, you can listen for the WebServerInitializedEvent
:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class WebServerReadyExampleApplication {
@Bean
ApplicationListener<WebServerInitializedEvent> webServerInitializedListener() {
return (event) -> {
System.out.println("Web server ready");
};
}
public static void main(String[] args) {
SpringApplication.run(WebServerReadyExampleApplication.class, args);
}
}
The listener will be called after Tomcat has started accepting connections:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.2)
2022-07-23 10:22:05.295 INFO 6769 --- [ main] c.e.d.WebServerReadyExampleApplication : Starting WebServerReadyExampleApplication using Java 17.0.1 on example-host with PID 6769 (/Users/example/web-server-ready-example/bin/main started by example in /Users/example/web-server-ready-example)
2022-07-23 10:22:05.297 INFO 6769 --- [ main] c.e.d.WebServerReadyExampleApplication : No active profile set, falling back to 1 default profile: "default"
2022-07-23 10:22:05.935 INFO 6769 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2022-07-23 10:22:05.943 INFO 6769 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-07-23 10:22:05.943 INFO 6769 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.65]
2022-07-23 10:22:06.009 INFO 6769 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2022-07-23 10:22:06.009 INFO 6769 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 671 ms
2022-07-23 10:22:06.259 INFO 6769 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
Web server ready
2022-07-23 10:22:06.266 INFO 6769 --- [ main] c.e.d.WebServerReadyExampleApplication : Started WebServerReadyExampleApplication in 1.247 seconds (JVM running for 1.577)
CodePudding user response:
The documentation for contextInitialized() states:
Receives notification that the web application initialization process is starting.
All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized.
It means that, indeed, the web application is still not usable when the method is called.
I don't think there is any way to be notified when the application is ready (at least in pure Java EE).