persistence@glassfish.java.net

EntityManager DAOs and Exception Flow

From: Oleg Mayevskiy <mayevskiy_at_spendino.de>
Date: Tue, 22 Feb 2011 15:18:49 +0100

Hi.

I want to have some DAOs , that encapsulate the Query, Entitymanager and
JPA Logic.

E.g. i write a simple DAO:

//my dao is an ejb
@Stateless
public class MyDAOBean implements MyDAO {

     //persistence context is handled inside dao, not business logic
     @PersistenceContext
     protected EntityManager em;

     @Override
     public MyEntity findMyEntityBySomething(String something) {
         return em.createNamedQuery(MyEntity.findBySomething,
MyEntity.class).
                 setParameter(MyEntity_.something.getName(), something).
                 getSingleResult();
     }
}

Now i want to use this dao from an business logic EJB:

@Stateless
public class MyLogicBean implements MyLogic {

    @EJB
     private MyDAO myDAO ;

      public void doSomething() {

             try {
                     MyEntity myEntity =
                     myDAO .findMyEntityBySomething(something);
              } catch (NoResultException nre) {
                     //handle nre somehow
              }
       }
}

So I do not want to handle Runtime Exceptions thrown by
getSingleResult() in my DAO, but in the business logic.

The problem here is, that the catch does not work, because instead of
NoResultException javax.ejb.EJBTransactionRolledbackException is thrown.
javax.ejb.EJBTransactionRolledbackException is caused by
javax.ejb.TransactionRolledbackLocalException which is finally thrown by
javax.persistence.NoResultException.

Is there a way to prevent the ejb container from trying to end the
transaction if leaving a method?

I worked around this issue by removing the @Stateless from DAO and
making a simple POJO:

public class MyDAO {


     private EntityManager em;

     public void setEntityManager(EntityManager em) {
         this.em = em;
     }


     public MyEntity findMyEntityBySomething(String something) {
         return em.createNamedQuery(MyEntity.findBySomething,
MyEntity.class).
                 setParameter(MyEntity_.something.getName(), something).
                 getSingleResult();
     }
}

than i call it some differt way from business logic:

@Stateless
public class MyLogicBean implements MyLogic {

    @Inject
     private MyDAO myDAO ;
     //PersistenceContext is inside of logic
    @PersistenceContext
     private EntityManager em;

     @PostConstruct
     public void init() {
         //EntityManager must be provided to dao inside ob logic
         myDAO.setEntityManager(em);
     }

      @Override
      public void doSomething() {

             try {
                     MyEntity myEntity =
                     myDAO .findMyEntityBySomething(something);
              } catch (NoResultException nre) {
                     //handle nre somehow
              }
       }
}

This way i can catch NoResultException a correct way. But there are two
disadvanteges.
PersistenceContext must be inside of logic class and EntityManager must
be provided to dao inside ob logic throw a setter method.

yours sincerely

Oleg Mayevskiy