1
votes

I am creating a Java EE web application which will operate on a database using JPA 2 EclipseLink. I am also using the application-managed Entity Managers so I could manually setup transactions, although I am not sure about a few things.

Initial information (for purpose of this post only because there are details/design parts) I have JPA Entities: UserEntity and UserDetailsEntity While creating a new user I have to create instances of both entities which are linked together.

While using a wizard to create JSF Pages from Entity classes I noticed that NetBeans created an AbstractFacade and an Enterprise Java Bean implementing that Facade: UserFacade and UserDetailsFacade. These EJBs are basic wrappers around JPA CRUD operations.

Questions:

  1. Is the Facade pattern really useful, especially in my situation when I want to combine few JPA operations in a specific transaction? Is this pattern good/bad for my design and why?

  2. Will the transaction mechanism work if I have "transaction process in UserManagement", but instead of executing .persist directly from within a transaction block I am executing wrapper methods:

        utx.begin();
        userFacade.create(userEntity);
        userDetailsFacade.create(userDetailsEntity);
        utx.commit();
    
  3. I am not sure about the EntityManager, should I have more than one instance of it? Apart from user authentication (to know the currently logged in user) I don't see a reason for keeping one instance of EntityManager. I think I could just use EntityManagerFactory to obtain instances every time I need them. But what concerns me is the performance here and good/bad design practices. Or should I keep one EntityManager (obtained somewhere in a config class and shared through Singleton or CDI?)

  4. Would it be good design to have a structure like: JSF Pages with Forms -> ManagementBean gathering information and passing it accordingly to the right EJB Beans -> EJB beans would do business methods and pass information to Facade EJBs responsible for CRUD -> FacadeEJBs would persist information.

Code for AbstractFacade:(Draft)

public abstract class AbstractFacade<T> {
private Class<T> entityClass;

public AbstractFacade(Class<T> entityClass) {
    this.entityClass = entityClass;
}

protected abstract EntityManager getEntityManager();

public void create(T entity) {
    getEntityManager().persist(entity);
}

public void edit(T entity) {
    getEntityManager().merge(entity);
}

public void remove(T entity) {
    getEntityManager().remove(getEntityManager().merge(entity));
}

public T find(Object id) {
    return getEntityManager().find(entityClass, id);
}

public List<T> findAll() {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    return getEntityManager().createQuery(cq).getResultList();
}

public List<T> findRange(int[] range) {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    javax.persistence.Query q = getEntityManager().createQuery(cq);
    q.setMaxResults(range[1] - range[0]);
    q.setFirstResult(range[0]);
    return q.getResultList();
}

public int count() {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
    cq.select(getEntityManager().getCriteriaBuilder().count(rt));
    javax.persistence.Query q = getEntityManager().createQuery(cq);
    return ((Long) q.getSingleResult()).intValue();
}

}

Code for UserFacade(Draft, because I will modify this class to retreive EntityManagers from the Factory rather than using CDI):

@Stateless
public class UserEntityFacade extends AbstractFacade<UserEntityEntity> {
@PersistenceContext(unitName = "FMSBetaPU")
private EntityManager em;

@Override
protected EntityManager getEntityManager() {
    return em;
}

public TestEntityFacade() {
    super(TestEntity.class);
}

}

Code for UserManagement EJB (Draft)

@Stateless
public class UserManagement {

@Resource
private UserTransaction utx;
@EJB
private UserEntityFacade userFacade;
@EJB
private UserDetailsEntityFacade userDetailsFacade;

public void createUser(int id, String name)
{
    UserEntity userEntity = new UserEntity(id);
    UserDetailsEntity userDetailsEntity = new UserDetailsEntity(name);
    try {
            utx.begin();
            userFacade.create(userEntity);
            userDetailsFacade.create(userDetailsEntity);
            utx.commit();
        } 
    catch (Exception e) {
            try {
                utx.rollback();
            } catch (IllegalStateException ex) {
                Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SecurityException ex) {
                Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SystemException ex) {
                Logger.getLogger(UserManagement.class.getName()).log(Level.SEVERE, null, ex);
            }
        } 
}


}
1

1 Answers

3
votes

EntityManager, should I have more than one instance of it?

The entityManager is like your current database session. So using a singleton for it is really really bad design. It's not thread safe. It holds references (thanks it's associated persistenceContext) to all objects fetched from the DB, so it is supposed to be a short-time-living object.

Regarding performance : creating an entityManager from the entityManagerFactory is really fast. (on the other hand creating an entityManagerFactory cost a lot... so it is good practice to have a singleton for the entityManagerFactory)