When using @EJB, does each managed bean get its own @EJB instance?
Asked Answered
W

1

11

I am using JSF 2.2 for a web project and I am implementing the login page now.

I have a login.xhtml that serves as the view, and a backing bean called UserLoginView.
This bean has an EJB property bean private UserService userService (as shown here).

Does this mean that each new UserLoginView gets a new instance of UserService?

Is OK to implement it like this in a production environment?

Whispering answered 26/8, 2014 at 20:8 Comment(0)
H
17

Does this mean that each new UserLoginView gets a new instance of UserService?

Nope. The given UserService is a @Stateless EJB. @Stateless EJBs are pooled and injected as serializable proxies autogenerated by the container. Among others the stack trace when an exception occurs from an EJB is evidence for this. You see extra layers between the backing bean method and the EJB method.

The autogenerated proxy class for a @Stateless EJB looks roughly like this (in reality it's more complex, e.g. DB transaction also needs to be obtained, started and committed here depending on the @TransactionAttribute of the EJB class and/or method):

public class UserServiceProxy extends UserService implements Serializable {

    public User find(Long id) {
        UserService instance = getAnAvailableInstanceFromPool();
        User result = instance.find(id);
        releaseInstanceToPool(instance);
        return result;
    }

    public Long save(User user) {
        UserService instance = getAnAvailableInstanceFromPool();
        Long result = instance.save(user);
        releaseInstanceToPool(instance);
        return result;
    }

    // ...
}

Do you see it? It just grabs an available instance from the EJB pool and then delegates the method call to it and finally releases it to the pool for future reuse. It's exactly this proxy instance which is actually being injected in your JSF managed bean.

CDI works also this way by the way. That's exactly why it's with CDI possible to inject a bean of a narrower scope in a bean of a wider scope and still get it to work as intented. JSF's @ManagedBean injects the actual instance and therefore it doesn't work that way. It would have worked if JSF also used proxies which actually grabbed the current bean instance via FacesContext and delegated to it.

Only @Stateful EJBs are actually tied to the lifetime of the client. In case of managed bean as client, it would indeed get "its own" instance. See also JSF request scoped bean keeps recreating new Stateful session beans on every request?

And @Singleton EJBs have basically a maximum of one instance in the pool. So each client will always get the same instance.


Is ok to implement it like this in a production environment?

Absolutely. Otherwise they didn't exist.

Hoiden answered 26/8, 2014 at 20:20 Comment(1)
Thanks for showing the inner workings of the proxy classes (being really new to Java development as well, these all seem really informative) :)Whispering

© 2022 - 2024 — McMap. All rights reserved.