What's the point of using @Scoped with EJBs?
Asked Answered
O

1

14

Usually I'm using @RequestScoped or @SessionScoped (from javax.enterprise.context) to inject objects (for instance in faces beans) using @Inject. I am also using EJBs. As I understood, a set of stateless EJB copies (pool) is used to be injected to objects. The reason there are many copies is to ensure one instance of EJB isn't accessed concurrently. When speaking about stateful EJBs (again as I understood), one instance of such is bound to concrete injection point. And they are injected using @EJB (the stateless ones too).

Frequently I can see on the web examples of using @Stateless or @Stateful in conjunction with @Scoped. What is the meaning of them?

Edit: (trying to clarify as no one responded to this moment):

I'm especially interested whether such scoped annotations change anyhow (and if they - how) moment of creation of EJB's instance. For my understanding: if I have, @EJB annotated field, object of proper class is injected there. If such EJB is stateless, container simply take free instance from the pool of pre-created instances. Pool can be resized if necessary. It is stateless, because object isn't guaranteed to be preserved across method calls of our class (i.e. class which has field containing reference to EJB).

We can also use stateful EJB and in that case one instance is preserved during method calls. As I think, it will be simply injected once per object creation. (There is also singleton EJB, which is shared between all objects).

I can't find the purpose of @Scoped annotations for EJB here.

Edit 2:

One can use such combination of annotations if class is to be injected via EJB and DI (by @Inject) mechanisms. This is rather, however, special case and not elegant. I am asking if you know any other reasons.

Edit 3: Please see my comment under arjan's answer.

Octane answered 16/5, 2011 at 14:8 Comment(0)
A
8

A @Stateless or @Singleton bean may be explicitly scoped to prevent its scope being automatically modified to a scope that may be illegal. E.g. both these bean types are not allowed to be @RequestScoped. See this link for some more info: http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html/CDI.html

@Stateful makes a lot of sense to be (explicitly) scoped. Namely, without a scope you as a programmer have to take care to call the @Remove annotated method. This can be troublesome to guarantee, since such a bean is typically not used in a single method where you can call the @Remove method in a finally block. With a scope, the bean is exactly removed when the scope ends.

Furthermore, without a scope you can't always use injection to obtain a reference to a stateful bean's stub. Namely, every time the injection happens, you'll get a new instance. This is particularly troublesome when injecting a stateful bean in a request scoped (JSF) backing bean, where you have the intent to preserve the stateful bean across a couple of requests.

Then, in combination with @Named, you can also use a session bean directly as a backing bean to flatten your application layers (see e.g. http://jaxenter.com/java-ee-6-overview-35987-2.html). Obviously you want an explicit scope in that case. Now flattening your layers may not be a best practice in larger applications, but for smaller applications and/or people just beginning with Java EE there is definitely a wish to put business logic directly into the backing bean. It's then required that backing beans have access to the same kind of services (mainly transactions) that 'business beans' normally have.

Finally, Gavin King (CDI spec lead) has suggested to always use @Inject instead of @EJB. The only exception concerns remote EJBs, where @EJB is still used.

Part of the confusion around EJB and CDI is that CDI is a new component model in Java EE and still relatively new. Although they integrate fairly well with each other, they are still two different component models and not all best practices have been thought out yet. Reza Rahman (EG member, EJB book writer, and author of CDI implementation CanDI) has suggested that the EJB model could possibly be retrofitted in the future as a set of CDI services. Indeed, in Java EE 7 a step is being made by separating the transactional services from EJB and making them available via (CDI) annotations.

Athapaskan answered 17/5, 2011 at 10:59 Comment(8)
I do not fully understand. @Scoped annotations are used by CDI to decide which instance to inject (the one used before or a new one). When we use @EJB, I think that some kind of proxy object is injected. When we call a method on that proxy object, it calls the method on available object from pool - if it is stateless. If it is stateful, such proxy assures that we are always dealing with the very same object injected in this injection point before. Such a scope can be understood as an "injection point scope" IMO. How do @Scoped annotations apply here?Octane
If the bean is stateful, then a scope annotation is indeed used to select which stub-that-points-to-an-instance to inject. Without a scope, you will get a new stub to a stateful bean every time which kinda defeats the purpose of a stateful bean. The alternative to using scopes is requesting the stateful bean from JNDI and assigning it to an instance variable of a managed bean, storing it in the HTTP session, etc.Athapaskan
Does that implies that if I have @EJB injected ejb in (for example) request scoped faces bean and such ejb is also annotated @SessionScoped, same instance will be injected to all faces beans in one session? (It would be like that, if I used @Inject to inject it)Octane
I just checked on my project and it did not work like that. I used @ApplicationScoped, so one instance of ejb should be put to all instances of bean. However it was not but it was if @Inject used. So as I understood, I should have compatible scope and same injection point. Is that correct?Octane
@EJB is the EJB specific injection annotation. I think it will not take the scope into consideration, but I've to test this too really.Athapaskan
Indeed, as the previous comment said (which appeared before your latest comment), @EJB probably does not take the scope into consideration. @Inject does.Athapaskan
Thank you. That was what I was asking in the first place, i.e. the point of using @Scoped with ejbs when they are injected using @EJB. During tests I had same results regardless of type and presence of @Scoped annotations. Edit: you have commented before I finished my comment :)Octane
Okay, glad to hear it's clearer now. These are not always trivial issues, which is a shame given the ease of development theme of Java EE 6. Now if you also put JAX-RS resources into the mix (which also has its own component model and injection annotations) things get really interesting :PAthapaskan

© 2022 - 2024 — McMap. All rights reserved.