Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ContextStartedEvent not firing in custom listener

I am trying to hook into the creation of the context using a custom application listener like this

@Component
public class ContextStartedListener implements ApplicationListener<ContextStartedEvent> {

    @Override
    public void onApplicationEvent(ContextStartedEvent event) {
        System.out.println("Context started"); // this never happens
    }
}

But the onApplicationEvent method never fires. If I use a different event such as ContextRefreshedEvent then it works just fine, but I need to hook into before it is created. Any advice? Thanks!

like image 613
secondbreakfast Avatar asked Jan 04 '18 16:01

secondbreakfast


1 Answers

[Edit]

Editing answer adding more info because of the downvote.

The reason why you are not getting a callback by the listener is because you are not explicitly calling the LifeCycle start() method (JavaDoc).

This cascades down to your ApplicationContext normally via the AbstractApplicationContext on in Spring Boot case via the ConfigurableApplicationContext.

Example of working code below demonstrating how your callback would work (just explicitly call the start() method)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
        applicationContext.start();
    }

    @Component
    class ContextStartedListener implements ApplicationListener<ContextStartedEvent> {

        @Override
        public void onApplicationEvent(ContextStartedEvent event) {
            System.out.println("Context started");
        }
    }
}

The reason why I suggested below the ContextRefreshedEvent callback instead is because behind the scenes the refresh() code is getting invoked.

If you drill down the SpringApplication#run() method you'll eventually see it.

Again here's a working example of how this would work using the ContextRefreshedEvent:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Component
    class ContextStartedListener implements ApplicationListener<ContextRefreshedEvent> {

        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            System.out.println("Context refreshed");
        }
    }
}

[Before Edit]

Change the Generic type to ContextRefreshedEvent instead and then it should work.

For more details read this article from the Spring Blog. Just to quote the part about the ContextRefreshedEvent:

[..]This allows MyListener to be notified when the context has refreshed and one can use that to run arbitrary code when the application context has fully started.[..]

like image 149
dimitrisli Avatar answered Sep 22 '22 20:09

dimitrisli