Am I using EJB correctly?

I am using JEE6 stack including JPA 2.0, JSF 2.0, EJB 3.1, etc.

The way to set up my architecture is as follows:

I have annotated JPA DAOs using hibernate as my JPA provider. I have JSF Managed beans that matches my facelet / xhtml pages. I have an EJB that handles all of my database requests.

My XHTML pages have JSF ELs that call my Managed beans. My managed beans contain references to my DAO entities that are managed by the EJB. For example, I have a custom object that maps to a db table. I have an EJB user that handles all CRUD operations that return users. I have a page that edits a user. The top level workflow will: go to user edit page -> EL calls a method located in the managed bean that loads the user. The method calls userEJB.loadUser (user) from the EJB to get the user from the database. User edits and submits -> the function is called in the managed bean, which calls the function in the EJB to persist the user. and etc.

I am having problems accessing my data in my JSF pages using EJB. I have a lot of problems with lazy initialization errors which I think are related to the way I set things up.

For example, I have a Client object that has a list of users that are lazy loaded. To get the client, I call a method on my EJB that goes to the database, finds the client, and returns it. Later I want to access this list of users, for that I need to go back to the EJB by calling some method to load those users (since they are lazy loaded). This means that I need to create a method like

public List<User> getUserListByClient(Client c)
{
    c = em.merge(c); return c.getUserList();
}

      

The sole purpose of this method is to load users (and I'm not even sure if this approach is good or works). If I was doing the session management myself, I would just leave the session open for the whole request and access the property directly, that would be good since the session would be open anyway, it looks like this extra layer of indirection in the EJB is making it harder for me ...

I like EJBs as I like that they are container controlled, pooled, offer free transaction management, etc. However, I get the feeling that I am using them incorrectly, or I have installed the JSF application incorrectly.

Any feedback is greatly appreciated.

thanks,

+2


a source to share


2 answers


Your usage seems good. Just remember that em.merge (c) can save changes made by client c to the database. If you just want to get the UserList of client c without saving the changes made to client c, you can do this:

public List<User> getUserListByClient(Client c)
{

     Client client = em.find(Client.class, c.clientId);
     return client.getUserList();

}

      



Or better, just send the client id to getUserListByClient instead of passing the complete client object, just to save a bit of winsy bit of memory :)

+1


a source


If I was into session management I would like to just leave the session open for the entire request and access the property directly, that would be fine as the session would be open anyway

Indeed that's open session in view pattern (also called open EntityManager in view). It can also be used with EJBs. Ideally, transactions should be managed in the business layer / EJB so that slight deviation from the pure layer architecture can be seen. But it solves the problem of lazy loading in the view and is simple.

Otherwise, you should make sure to upload the information to be used after the transaction is completed. Or you can rely on DTOs, but then it starts to get cumbersome.



Here are two more links that cover the topic and discuss the pros and cons and alternatives:

+2


a source







All Articles