Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

jsf - When using @EJB, does each managed bean get its own @EJB instance?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...