javax.persistence.NoResultException is a RunTimeException and is handled
as a system exception by ejb container (See Ch 14.2.2 of EJB 3.1 spec)
resulting in the behavior you described. You can catch it inside your
DAO and rethrow as an application exception to achieve the behavior you
desire.
-Mitesh
On 2/22/2011 6:18 AM, Oleg Mayevskiy wrote:
> 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
>
>