Spring @EventListener annotation doesn't work
Asked Answered
P

4

12

I want to handle multiple events in one class, here's my example:

@Lazy(false)
@Component
public class EventListenerImpl {

    @EventListener
    public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
        LOGGER.log(event.getSource());
        ...
    }
}

However this method is not being executed when my application starts.

In my applicationContext.xml I have:

<context:annotation-config/>
<context:component-scan base-package="..."/>

which should be enough for @EventListener to work, according to the documentation.

The old way of implementing ApplicationListener<ContextRefreshedEvent> works just fine.

I'm using Spring 4.2.4.RELEASE.

Pincas answered 10/2, 2016 at 11:26 Comment(8)
do you have <context:annotation-driven/> in your XML?Borehole
@Borehole No, but I have <context:component-scan/> instead which should be enough according to docs: docs.spring.io/spring/docs/current/javadoc-api/org/…Pincas
rename you methd to handleContextRefreshed see here: spring.io/blog/2015/02/11/…Borehole
@Borehole That didn't help.Pincas
What means That didn't help.?Borehole
@Borehole The method didn't get called when the event occured.Pincas
You renamed and redeployed your application?Borehole
@Borehole Yes, the method is called handleContextRefresh and I have redeployed the application.Pincas
P
4

Alright, this remains a total mystery for me. I bet it's some kind of wierd maven/ide caching issue, but anyway this worked for me after several restarts :

@Lazy(false)
@Component
public class EventListenerImpl {

    @EventListener
    public void whatever(final ContextRefreshedEvent event) {
        event.getSource();
    }
}
Pincas answered 10/2, 2016 at 12:57 Comment(0)
R
2

What I found might explain what @moonlightcheese observed: If the event is published early in the application's lifecycle, it is not sent to the annotated @EventListener method. If it is published later, it is sent to the method.

My work around was to ensure that the event is not published prior to the ContextRefreshedEvent. I had my publisher class implement ApplicationListener<ContextRefreshedEvent>, and published my event from the onApplicationEvent(ContextRefreshedEvent event) override. Similar strategies could be used where the onApplicationEvent(ContextRefreshedEvent event) override is used to gate publication.

It's possible that anything which changes the timing dynamics of the application startup could affect the behavior one way or the other.

Rendition answered 11/5, 2022 at 5:41 Comment(0)
W
1

I know this is an old question, and the answer is accepted, but I don't think it solves the problem. I had this exact same issue and was able to solve it by moving the event listener @EventListener containing class from the root of the base-scan package to a sub package of that package. For example:

<context:component-scan base-package="com.example"/>

Simply create a sub package (folder) under com.example and place the class in there:

com -> example -> foo (place class here)

This is what worked for me. No idea why it couldn't find the @EventListener in the base-package root, but anyway, it's fixed. This seems to be an undocumented issue in the docs.

Waive answered 7/4, 2021 at 7:39 Comment(0)
C
1

Some events are published before the ApplicationContext is even fully available and therefore the ApplicationListeners may not be registered yet even though they are annotated with @Component and @EventHandler.

For example the ApplicationStartingEvent explicitly states that is is published before the ApplicationContext is available.

The same might be true for your ContextRefreshedEvent, as its first published when the ApplicationContext gets initialized.

Curtis answered 14/3, 2023 at 20:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.