Skip to content

Inconsistent behaviour in AbstractApplicationEventMulticaster listener caching [SPR-7563] #12220

@spring-projects-issues

Description

@spring-projects-issues

Luke Taylor opened SPR-7563 and commented

I noticed recently that the concurrent login detection in the Spring Security "tutorial" sample is broken. On closer inspection, this is because the SessionRegistryImpl bean is not being notified of session-destruction events when a user logs out, so the user cannot log in again. SessionRegistryImpl is an ApplicationListener and stepping though the code in AbstractApplicationEventMulticaster.getApplicationListeners(ApplicationEvent event) seems to show inconsistent behaviour wrt the caching. The first time the method is called, the SessionRegistry bean name is found in defaultRetriever.applicationListenerBeans, is looked up in the BeanFactory and is returned in the collection of listeners. At the same time, a new ListenerRetriever instance is created and the bean name is added:

BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.defaultRetriever.applicationListenerBeans) {
    ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
    if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
        retriever.applicationListenerBeans.add(listenerBeanName);
        allListeners.add(listener);
    }
}

i.e. the bean name is added to the retriever, not the actual listener instance.

However, when the method is called again, the ListenerRetriever is invoked and returns an empty list. This is because the code related to retrieving the listener by name can never be invoked:

if (!this.applicationListenerBeans.isEmpty()) {
    BeanFactory beanFactory = getBeanFactory();
    for (String listenerBeanName : this.applicationListenerBeans) {
        ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
        if (!this.preFiltered && !allListeners.contains(listener)) {
            allListeners.add(listener);
        }
    }
}

preFiltered is always true in this case, so as far as I can see the listeners will never be added list.


Affects: 3.0.3, 3.0.4

Referenced from: commits b7b2a25

1 votes, 4 watchers

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions