does this JSF pattern break dependency injection?
I have a JSF2 project (Mojarra on GlassFish 3.1).
I have a ViewScoped bean that references services through a utility class like so:
@ManagedBean
@ApplicationScoped
public static class ServicesUtil {
@EJB
UserService userService;
@EJB
EmailService emailService;
/** getters/setters **/
}
and
@ManagedBean
@ViewScoped
public class UserHandler {
public String method() {
ServicesUtil.getUserService().doUserStuff();
return "newPage";
}
}
My question is, since the ServicesUtil is ApplicationScoped, does that mean there is only one instance of each service for the entire application? And i开发者_运维技巧s this bad practice? If done correctly, would the CDI in GlassFish actually create new instances as they are needed?
Similarly, if the Services were injected into the UserHandler instead would the application be more scalable?
The reason we added the ServicesUtil layer is one of my coworkers said that he occasionally had problems getting the injection to work in the Handler when it is ViewScope. Should there be any difficulty using @EJB in a ViewScoped bean?
Any help is greatly appreciated!
Rob
The pattern you're using doesn't seem to make a lot of sense. There should be no problem with injecting EJBs into a view scoped bean.
Depending on the type of EJB you are using (stateless, stateful or singleton) different things hold.
If the userService and emailService are stateless (they most likely should be), you gain nothing by using a bean that's injected into an application scoped bean first. Namely, what's injected is not the bean itself but a proxy and every request to that is routed to a different real bean instance anyway (see http://en.wikipedia.org/wiki/Enterprise_JavaBean#Stateless_Session_Beans).
If the userService and emailService are stateful, you do get a single instance here, but I highly doubt you need to share actual between every user in your application. But even if you would want that, only a single user (thread) can access the stateful bean at a time.
If those services are singleton, you can just inject them right away into the view scoped bean. There is absolutely no reason to go via an application scoped bean.
Furthermore, ServicesUtil.getUserService()
is a static method, so using this to get an injected service is brittle. If you want to use this (you shouldn't, but suppose) ServicesUtil
should be injected into UserHandler
.
Then, it seems you are confusing CDI and JSF managed beans. I agree this is confusing, but it's currently the way it is. @ViewScoped
does not work in combination met CDI beans. From your code it's not clear if @ManagedBean
is the JSF variant or the Java EE/CDI one. In this case it should be javax.faces.bean.ManagedBean
if you want to use the view scope.
精彩评论