Home > Software design >  Notify SpringBoot application that its web server is up
Notify SpringBoot application that its web server is up

Time:07-23

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).

  • Related