I have the following JSF/PrimeFaces EJB architecture:
[JSF/PrimeFaces xhtml view] --> [#ManagedBean JSF bean] --> [#Stateless EJB3 bean] --JPA--> [DB]
That is, the JSF views display entities and collections they access on their backing beans (#ManagedBean) and these collections and entities are in turn fetched by calling stateless EJB3 "facade" beans that have the EntityManager injected and access the database using JPA backed by Hibernate. The stateless EJB3 beans also provide some services but for the most part their role is to provide the Entity objects (JPA-annotated) from the database, as requested by the xhtml views that need to display them.
Now here's the thing: if my understanding is correct, the moment the Entity beans are returned by the stateless EJB3 beans, they become detached as each EJB3 bean method demarcates a transaction. It is then often the case that as the xhtml views and the JSF Managed beans navigate the graphs of the Entity objects so fetched (One-To-Many collections and such), I often get Lazy Initialization exceptions like the following:
javax.el.ELException: ... org.hibernate.LazyInitializationException: failed
to lazily initialize a collection of role: ..., no session or session was closed
The only thing that works is changing collections to be EAGER -ly loaded but that's not a pragmatic solution. What are some good patterns to use when detached JPA entity find their way to the view layer in order to avoid once and for all the lazy initialization exceptions rather than having to treat each case in an ad-hoc manner?
There are two ways of handling lazy associations. The first way is to initialize the entity using:
Hibernate.initialize(proxy)
or set the fetch type to EAGER which will fetch the entire entity when you load it.
The second and the more proper way (in my opinion) is to keep the entity manager as long as you keep the entities. This could be done either using a #Stateful session like this:
#Stateful
public class UserService {
#PersistenceContext(type=EXTENDED)
private EntityManager entityManager;
...... the business method
}
and keep a reference to the ejb as long as you keep the entity. More info about extended persistence context could be found here.
Other way to keep the entity manager is to use CDI modules like seam-persistence or CODI that offer a functionality to create and keep an EntityManager to conversation scope.
Related
I need to modify a user session object (SessionScoped bean - CDI) in a Servlet, so I have to obtain that bean somehow. I used injection in the following way:
#Inject
private UserSession user;
where UserSession is the SessionScoped CDI bean. user methods are called from either doPost or doGet servlet methods.
This works perfectly; every time the #Inject annotation injects the appropriate UserSession bean, but I don't understand how this behavior is achieved.
I assumed that the beans, annotated with #Inject, are injected only once (when the object - Servlet instance in this case - is created), but it is obviously a wrong presumption.
So, when are these beans injected into the servlet? Per request? And how does this approach avoids conflicts (one servlet instance - multiple threads to deal with it) when there are multiple UserSession objects?
The CDI uses the proxy pattern. The injected instance is actually not the real instance, but a proxy which locates the real instance depending on the current context and delegates all methods to it (like as how EJBs work). The autogenerated class of your UserSession bean looks roughly like this:
public UserSessionCDIProxy extends UserSession implements Serializable {
public String getSomeProperty() {
UserSession instance = CDI.resolveItSomehow();
return instance.getSomeProperty();
}
public void setSomeProperty(String someProperty) {
UserSession instance = CDI.resolveItSomehow();
instance.setSomeProperty(someProperty);
}
}
This mechanism allows you to inject instances of a narrower scope in instances of a broader scope and allows you to still get the expected instance in the current context. The standard JSF #ManagedProperty annotation doesn't support it, simply because it does not use a proxy, but injects the desired instance directly. That's why it's not possible to inject something of a narrower scope by #ManagedProperty.
See also:
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Get JSF managed bean by name in any Servlet related class
When using #EJB, does each managed bean get its own #EJB instance?
How to choose the right bean scope?
Your answer lies in the C of CDI, which stands for Contexts.
What happens is that not the actual bean is injected, but a proxy. This proxy is contextual and resolves to the actual session scoped bean depending on the context of the caller on who's behalf the proxy is executed.
It is better to create an application scoped factory or should it be request scoped when using factory pattern to create objects?
Application scoped beans are created once but uses memory space. Request scoped beans are created for each call but using memory space only at lifetime. Request scoped beans could created multiple times.
#Named
#ApplicationScoped
public class SomeObjectFactory {
public SomeObject createObject() {
// do some stuff
}
}
Are there any best practices?
I think you won't find a very definitive answer for this question. The reason is that it really depends on your application:
Should the bean exist only during the lifespan of a request? If so, use #RequestScoped.
Should the bean exist during the lifespan of the application and should the state of the bean be shared between all the requests? If so, use #ApplicationScoped.
I am new to the EJB and hibernate, and the following confuses me because there seems to be contradiction whenever i search for the definite answer.
Question:
Is it thread-safe to inject Entity manager directly into stateless bean in the following way?
#Stateless
public class SomeBean implements SomeInterface {
//..
#Inject
private EntityManager entityManager;
//... non related transaction1()
//... non related transaction2()
Would each stateless bean have its own instance of EntityManager or shared instance could be injected?
According to Hibernate docs:
An EntityManager is an inexpensive, non-thread-safe object that should be used once, for a single business process, a single unit of work, and then discarded.
Does an EJB container make it thread safe?
And according to the EJB docs, stateless session beans are inherently thread safe by not allowing different clients operate on same bean at the same time.
However, I have read examples in which EntityManagerFactory should be injected instead of EntityManager and if EntityManager is injected directly it should be done in Stateful bean.
Would it be safe to always inject EJB directly into Stateless bean like shown above or what would be use case when it wouldn't work?
Would each stateless bean have its own instance of EntityManager or shared instance could be injected ?
None of both. The #Inject (and #PersistenceContext and #EJB) injects a proxy instance, not the actual instance.
The proxy will on every method call delegate to the right available instance in the current thread and context. In other words, the container worries about this all, not you.
See also:
When using #EJB, does each managed bean get its own #EJB instance?
Why Stateless session beans?
I use JSF 2 and EJB 3.1, all of them are deployed on Glassfish 3.1.
When i setup a class named MyInterceptor which is implemented PhaseListener, i can not revoke remote EJB interface inside it.
It notice "NullPointerException ..."
public class MyInterceptor implements PhaseListener {
#EJB(name="AuthorizationEJB",
beanInterface=AuthorizationService.class,
mappedName="corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")
public AuthorizationService authorizationService;
....
}
When I call authorizationService.dosomestuff(), it raise error NullPointerException
How can i do to fix it?
Thank in advance
In JSF 2.1 and earlier, PhaseListeners are unfortunately no injection targets (meaning you can't use injection in them). You can do your lookup programmatically via JNDI instead though.
In JSF 2.2 all JSF artifacts (including PhaseListeners) will be injection targets, but this will probably not help you now.
Unrelated to your question, but I'm not sure what you're trying to achieve by specifying the beanInterface in your annotation. Most likely you'll also don't need the name attribute and if your bean is a local bean you'll also don't need mappedName.
Use a servlet filter instead of a JSF phase listener to do authorization. You can inject an #EJB in a #WebFilter.
Yeah in web filter you could have just used plain #EJB. Maximimum you needed to add beanName if you had two beans implement same AuthorizationService interface.
Servlet filter is per request, I don't think you need to do security stuff at a certain phase from JSF's lifecycle (which is a more granular level than the whole http request).
For normal lookup you can do:
AuthorizationService.class.cast(new InitialContext().lookup("corbaname:iiop:localhost:3700#ejb/AuthorizationEJB")).dosomestuff();
in a try catch javax.naming.NamingException
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 is 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.