Fire CDI event AFTER bean creation via producer - events

I have a CDI producer method which creates an UserBean. The producer fires an UserBeanEvent. Other beans rely on that user bean and those beans may be used in the observer methods.
CDI again tries to create the user bean, the producer is invoked, the event is fired and so on - endless loop.
Is there any neat way to fire the event AFTER the producer completed and the bean was fully added to the bean store? I looked through the sources but I was not able to find anything.
I'm using WELD 2.3.5.final on WildFly 10.1

You need to detail several things, and one of the most important one is scope, and at what point is the bean needed?
Obviously if there is an observer method that listens to this bean event, and also needs a reference to this bean in the observer parameter, then you are definitely creating a cyclic dependency, which you cannot resolve, as the events in CDI are synchronous by default (And even if you use the fireAsync, there is no guarantee that by the time the event arrive, CDI has put the bean into proper context)
I would solve this problem by doing a method injection on an eargerly loaded bean such as ejbs Singleton or #ApplicationScoped with some kind of earger loading, and then fire the event from there.
Assuming that the bean is eargerly loaded:
public class EargerBean {
#Inject
private Event<BeanEvent> event;
#Inject
public void onInjected(Bean bean){
BeanEvent beanEvent ...;
event.fire(beanEvent);
}
}

Related

Correct way to find if spring context was started

In my spring bean I want to use send spring event functionality. The problem is event can't be sent if spring context was not initialized and my bean by some reasons can send events before that happen.
I used the following:
implement ApplicationContextAware and use ConfigurableApplicationContext.isActive() - this becomes true in the beginning of the context initialization phase
use ConfigurableApplicationContext.isRunning() - this throws exception IllegalStateException("LifecycleProcessor not initialized...
listen for ContextRefreshedEvent - this doesn't work because this is inner bean and is used as a property for the bean that implements BeanFactoryPostProcessor
implementing SmartLifecycle also doesn't work because for inner beans
So what is the EASY and correct way to determine if context is running and event can be sent?
Hopefully this is already fixed SPR-13667 in spring 4.1.7.

destroy-method not invoked on beans registered as prototype

I have a bean registered as singleton and init-method and destroy-method defined on it. I am accessing the bean and can see the calls being made to both the methods. However, on changing the scope to prototype the destroy-method is not invoked.
I am not getting the rationale behind this.
Read the documentation:
In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called.
And that's quite logical: your application could ask for new instances of prototype beans every 10 milliseconds, do something with the bean, and then let it go out of scope. If Spring had to destroy() them when the application shuts down, it would have to keep a reference to every created prototype bean, preventing them to be garbage-collected, and thus causing a memory leak.

Spring register ApplicationListener bean at runtime

I am using
applicationContext.getAutowireCapableBeanFactory().initializeBean(bean, name);
to register a bean at runtime. This bean could actually be considered a child bean of an existing singleton.
If the bean implements ApplicationListener, I get a warning in the log, since there is no underlying bean definition to indicate that this bean should be considered a singleton. And of course it doesn't receive application events, like the warning says.
Inner bean 'name' 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.
How can I register the bean as singleton at runtime, so I avoid the bean post processor warning, as well as have application events work?
(See AbstractApplicationContext:1413)

Spring calling 'destroy' method on session/request scoped beans

How does Spring know when to call 'destory' method on a session/request scoped bean (in other words, how does it detect that the concerned bean is going out of scope)?
I read somewhere that it uses request/session listeners to be notified of these events. But these listners need to be defined in web.xml, and there's no mention of defining such listeners in Spring literature. So how does this work?
The org.springframework.web.servlet.DispatcherServlet does it. It uses own code, e.g. the org.springframework.web.context.request.RequestAttributes#registerDestructionCallback callback list functionality to register all these scoped beans.
and there's no mention of defining such listeners in Spring literature
Oh, there is:
To support the scoping of beans at the request, session, and global session levels (web-scoped beans), some minor initial configuration is required before you define your beans.[...]
If you use a Servlet 2.4+ web container, [...] you need to add the following javax.servlet.ServletRequestListener to the declarations in your web applications web.xml file[...]
From: 4.5.4.1 Initial web configuration.
Also note that Spring does not call destroy on prototype-scoped beans.
You can implement the interface DisposableBean and InitializingBean for session scoped bean.
The org.springframework.beans.factory.InitializingBean interface allows a bean to perform initialization work after all necessary properties on the bean have been set by the container. The InitializingBean interface specifies a single method afterPropertiesSet().
Implementing the org.springframework.beans.factory.DisposableBean interface allows a bean to get a callback when the container containing it is destroyed. The DisposableBean interface specifies a single method destroy().
Read more about it here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature

Lazy ApplicationListener

When I add ApplicationListener to a class, Spring instantiates the bean eagerly (probably to make sure that the bean gets all the events).
In my case, I have a bean which listens for "CacheFlush" events (i.e. I don't really care how many I might miss).
How do I implement a lazy ApplicationEvent listener in Spring 3.0?
I am not sure if what you want to do is possible directly, but one potential solution is to have a separate Observable bean listen for the cache flush events and notify its Observers when one comes in. Have your lazy bean register with the Observable when it is initialized.

Resources