Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
spring-projects-issues opened this issue Sep 15, 2010 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

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

@spring-projects-issues
Copy link
Collaborator Author

Luke Taylor commented

This appears to have been broken after 3.0.2, which did not have the preFiltered flag on the ListenerRetriever and thus successfully finds the listener as a named bean.

@spring-projects-issues
Copy link
Collaborator Author

James Roper commented

I've noticed this behaviour too, and have verified this behaviour in a debugger.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

This was caused by a silly mistake in the preFiltered condition check. Fixed for 3.0.5; will be available in tonight's 3.0.5 snapshot.

Juergen

@spring-projects-issues spring-projects-issues added type: bug A general bug in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
@spring-projects-issues spring-projects-issues added this to the 3.0.5 milestone Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants