SpringBoot EventListener don't receive events
Asked Answered
F

3

10

my EventListener annotation don't receive any Spring Event. Here is my code:

@Component
public class ProxyConfig {

    public ProxyConfig() {
        System.out.println("I can see this in the console");
    }

    @EventListener
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        System.out.println("WON'T WORK :-(");  // FIXME
    }

    @EventListener
    public void test(ApplicationStartedEvent event) {
        System.out.println("WON'T WORK :-(");  // FIXME
    }
}

And here is my Application class:

@SpringBootApplication
public class Application {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(MyApp.class, args);
    }
}

According to https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2 and https://solidsoft.wordpress.com/2015/09/29/annotation-driven-event-listeners-in-spring-4-2/ it must be working, but it still not print my "WON'T WORK :-(" String :(

Any idea?

Thanks!

Frontolysis answered 20/7, 2016 at 17:51 Comment(4)
What packages are Application and ProxyConfig in?Jonson
Application is in package com.mycompany.app. And ProxyConfig is in a subpacke: com.mycompany.app.configuration.implFrontolysis
By creating a META-INF/spring.factoriesfile (see docs.spring.io/spring-boot/docs/current/reference/html/…) it works without the Annotations, but not with... :(Frontolysis
I've just noticed the events that you're listening for. That's expected behaviour. I've tried to explain what's going on in my answer below.Jonson
J
12

The two events that you are listening for are both published very early in an application's lifecycle.

ApplicationStartedEvent is sent "as early as conceivably possible as soon as a SpringApplication has been started - before the Environment or ApplicationContext is available, but after the ApplicationListeners have been registered".

ApplicationEnvironmentPreparedEvent is published "when a SpringApplication is starting up and the Environment is first available for inspection and modification."

In both cases, the event is published too early for a listener to be found via annotations and the application context. As you've observed you can use spring.factories to register your listener. Alternatively, you can use the setter method on SpringApplication.

Jonson answered 20/7, 2016 at 21:37 Comment(2)
How to achieve it via SpringApplication setter?Hyades
Can try with ApplicationReadyEvent.Payne
L
2

This is an old question, but anyway, to anyone having the same issue...

I've just wasted a few hours with the exact same problem, I've searched the internet and did countless tests to no avail, I've tried annotating with @EventListener(ApplicationReadyEvent.class) and @PostConstruct, nothing worked.

My philosophy is that when something simple doesn't work and the internet doesn't help, it means you messed up something. So I started reviewing my code and I see you've made the same mistake as me.

You've copied the example from somewhere else or changed the original configuration class from MyApp to Application, and you've forgotten to change the line:

SpringApplication.run(MyApp.class, args);

to

SpringApplication.run(Application.class, args);

The first line will do nothing, unless MyApp also has @SpringBootApplication or other configuration annotations, the second one will find the @SpringBootApplication annotation and will properly start the Spring Boot application.

By the way, both @EventListener(ApplicationReadyEvent.class) and @PostConstruct work just fine, tested on Java 17.

Legalize answered 1/11, 2022 at 5:50 Comment(0)
A
0

Since spring boot hasn't completed annotation processing at the point of your interested events, it is unable to deliver the events to the annotated event listeners. Instead you have to manually register the listeners at application startup.

public class ApplicationStartingListener implements ApplicationListener<ApplicationStartingEvent> {
    @Override
    public void onApplicationEvent(ApplicationStartingEvent event) {
        System.out.println("Application is starting");
    }
}

@SpringBootApplication
public class MyApplication {
   public static void main(String[] args) {
      SpringApplication app = new SpringApplication(MyApplication.class);
      app.addListeners(new ApplicationStartingListener());
      app.run(args);
   }
} 
Airstrip answered 13/9 at 11:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.