Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot - Wait for web server to start

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.

like image 760
sourcedelica Avatar asked Jan 30 '15 16:01

sourcedelica


1 Answers

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) { }
like image 51
Andy Wilkinson Avatar answered Oct 15 '22 13:10

Andy Wilkinson