Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA with EJB with separated DAO and Service Layers

Tags:

java

jpa

ejb

This is more an architecture problem I currently have. I need help regarding the best practices of integrating EJB and JPA on a project. I want to have EJBs which will do the job of the service layer, containing the business logic of my application. Right under that, I would like to have a DAO layer which my EJBs will have a handle using a DAO factory to separate those two layers as much as possible. Knowing that, I obviously cannot make my DAO as EJBs also because I don't want them injected automatically, as I want them to be created through the factory. That leads me to create the entitymanager manually using

Persistence.createEntityManagerFactory("PortalEJB").createEntityManager();

Now... this call is located in my abstract JPA DAO:

public abstract class JPADataAccessorObject<K, E> implements DataAccessorObject<K, E> {
    protected Class<E> entityClass;

    protected EntityManager entityManager;

    protected JPADataAccessorObject(Class<E> pEntityClass) {
        this.entityManager = Persistence.createEntityManagerFactory("PortalEJB").createEntityManager();
        this.entityClass = pEntityClass;
    }

    /* Other DAO functions (update, delete, create) */
}

I think this is bad, isn't it? All my concrete extents of this class will have a brand new copy of the persistence context and I will get strange behaviour. Moreover, when I do that, I think I have to manage the transactions myself in the service layer. I was about to create Aspects for that, something like:

  • Create transaction before any service layer's function/procedure
  • (rollback the transaction if any exception occurs)
  • Commit the transaction after any service layer's function/procedure

So here are my questions:

  • How should I manage the EntityManager?
  • Should I have some kind of JPA utility class which will manage it to have one copy protected from multithreading?
  • If I'm making a horrible mistake, please provide best practices.
like image 539
Sylvain Cloutier Avatar asked Jul 03 '13 13:07

Sylvain Cloutier


1 Answers

Have you seen the post of Adam Bien JPA/EJB3 KILLED THE DAO and DAOS AREN'T DEAD - BUT THEY EITHER COLLAPSED OR DISAPPEARED?

In another hand, you can consider an abstract class for the service layer:

public abstract class AbstractFacade<E extends Serializable, 
                                     PK extends Serializable> {

    private final transient Class<E> entityClass;

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

    protected abstract EntityManager getEntityManager();

    public void create(final E entity) {
        final EntityManager entityManager = getEntityManager();
        entityManager.persist(entity);
    }

    public final E find(final PK id) {
        return getEntityManager().find(entityClass, id);
    }

    // Other common operations

}

And a particular service:

@Stateless
public class UserFacade extends AbstractFacade<User, String> {

    @PersistenceContext(unitName = "MyPU")
    private EntityManager em;

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

    public UserFacade() {
        super(User.class);
    }

    // Other methods of this service

}

See more in Java EE 6/7: The Lean Parts from JavaOne 2012 in San Francisco.

like image 124
Paul Vargas Avatar answered Oct 05 '22 00:10

Paul Vargas