[cdi-dev] On @Observes for async events

Mark Struberg struberg at yahoo.de
Fri Mar 20 03:31:42 EDT 2015

Arjan, answers inside.

> I don't really agree.
> @RequestScoped will give you the same bean as long as the same request scope is active for the caller. Every call is guaranteed to go to the same bean.

That’s why I wrote ~ (means ‚roughly equals‚). What I meant by that is that @RequestScoped also gives you the same guarantees regarding concurrency like @Stateless. Means you can be sure that you only get accessed from max 1 Thread at the same time.

> For @Stateless the situation is actually reversed. There is no scope that the caller is in. Every call the caller makes on a bean may go to a difference instance. Conceptually it's like a method call results in a package containing the call details being put on a queue, then a *random* bean is chosen from a pool or created on the spot to process that package. Then when it finishes processing the result is returned to the caller and that random bean is put back into the pool or is immediately destroyed. That’s IMHO really nothing like @RequestScoped. 
> @PoolScoped is tempting, but not possible the way the EJB spec is defined now. The reason is simply that there’s nothing in the spec that mandates stateless beans to be pooled.

No, the guarantees are at least like RequestScoped in regards of concurrency. Sometimes even less. Trust me, I know a bit about this as I’ve implemented such containers ;)
You are right that it is not mandated by the spec and each EJB container is perfectly free to destroy a @Stateless bean whenever he likes (except in the middle of a method call on it, but not even that is specified). 
But in practice all EJB containers I do know only destroy them at the end of a request IF they don’t put them back to the pool. The usual lifespan for a @Stateless bean is from 30 mins to 12h (depending on a container and your configuration). Some do not destroy them at all. After a request they just put the instance back to the pool cache. You can easily check this yourself by logging out some info in @PostConstruct and let the app (EAR, WAR) run on various containers.

Anyway. The real point is that the NormalScoped CDI proxies DO call Context#get(Bean<T>) for EACH AND EVERY method invocation. So however you like your @Stateless beans to behave we could do it!

The real blocker is somewhere totally different. 
E.g. CDI does not allow final non-private/non-static methods. Nor do we allow public fields. In those cases we say the bean is ‚unproxyable‘. See CDI spec 3.15. EJB NIV does allow this - or better: it does not explicitly disallow it. With the effect that those method will get called on the proxy instance (which is usually created with sun.misc.Unsafe#allocateInstance and thus have no <init> called nor any field initialized) and NOT on your contextual instance. 

> At any length, @PoolScoped would define the life-time of a bean (when it’s constructed and when it's destroyed) indeed, but it would mean nothing for the caller. 

No, the Context implementation of any scope can freely decide IF and WHEN he likes to destroy it’s contextual instances…


More information about the cdi-dev mailing list