Archie Cobbs opened SPR-9387 and commented

I have some object which need to receive some ApplicationEvents that are sent around in my application.

However, these objects have a lifecycle that does not match with the lifecycle of normal beans in the application context (their lifecycle is shorter).

Therefore, I have these beans marked @Configurable, and they are ApplicationContextAware so they can get a reference to the application context (which is assumed to be a ConfigurableApplicationContext.

Then, when they "start" they register as listeners for application events via ConfigurableApplicationContext.addApplicationListener(). However, when they "stop" there is no way for them to unregister themselves as listeners, because there is no corresponding method ConfigurableApplicationContext.removeApplicationListener().

So this request is simply to add ConfigurableApplicationContext.removeApplicationListener().

If there is some more elegant way to do what I'm trying to do please let me know. But just from the face of it, it seems weirdly asymmetrical to have a public addFooListener() method without a corresponding removeFooListener() method.

Thanks.


Affects: 3.1.1

Issue Links: - #14027 Support DisposableBean on prototype and @Configurable beans using weak references

1 votes, 4 watchers

Comment From: spring-projects-issues

Archie Cobbs commented

Additional info: even though these @Configurable beans implement ApplicationListener, they are not automatically registered with the event multicaster, instead triggering this warning in AbstractApplicationContext.java:

Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
    // singleton bean (top-level or inner): register on the fly
    addApplicationListener((ApplicationListener<?>) bean);
}
else if (flag == null) {
    if (logger.isWarnEnabled() && !containsBean(beanName)) {
        // inner bean with other scope - can't reliably process events
        logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
                "but is not reachable for event multicasting by its containing ApplicationContext " +
                "because it does not have singleton scope. Only top-level listener beans are allowed " +
                "to be of non-singleton scope.");
    }
    this.singletonNames.put(beanName, Boolean.FALSE);
}

That is why they have to be manually registered as listeners.

So this is kind-of a Catch-22 situation.

By the way, this issue relates to #9922, which is marked Resolved, but is it really? It seems like the code above means that it's not really resolved.

Also: I accidentally set the Component to SpringAOP instead of SpringCore, but don't have permission to edit it... sorry.

Comment From: spring-projects-issues

Archie Cobbs commented

Related to this. There is an opportunity for a little API cleanup: * Why not let ConfigurableApplicationContext extend ApplicationEventMulticaster? Right now there are two separate interfaces declaring an addApplicationListener() method. * ApplicationEventMulticaster still needs some genericization, i.e., methods should take parameters of type ApplicationListener<?> instead of ApplicationListener * We have both ApplicationEventPublisher.publishEvent() and ApplicationEventMulticaster.multicastEvent(), both doing the same thing. Seems like these methods should have the same name, and ApplicationEventMulticaster should just extend ApplicationEventPublisher.

Comment From: spring-projects-issues

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

Comment From: archiecobbs

Bulk closing outdated, unresolved issues. Please, reopen if still relevant.

... except Github won't let me reopen it...

Comment From: sbrannen

This feature was also considered in conjunction with the initial implementation for #25616.

Comment From: rstoyanchev

Scheduling for 6.0 with a chance to explore a backport to 5.3.x.

Comment From: archiecobbs

Woo-hoo! Just in time for it's 10th birthday on Sunday :)

Seriously, this is why I love Spring - most projects would never bother to fix a 10 year old minor feature request.