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…
LieGrue,
strub