0

Recently, I've decided to use EJB in my project. Basically, are Stateless EJBs in order to make the business layer and persist data. I'm also using container managed transactions (CMT) and everything works fine.

I tried to handle the exceptions in EJB service methods in order to get the more specific exceptions and give specific errors messages to the client.

@Stateless
public class EJBService { 

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

    public void save(Animal a) throws AppException
    {
        try
        {
            em.persist(e);
        }
        catch(ConstraintViolationException ex)
        {
            throw new AppException("message");
        }
        catch(Exception ex)
        {
            throw new AppException("message 1");
        }
    } 
}

The AppException extends Exception and is marked with the annotation @ApplicationException(rollback=true)

However, I can't handle the exception before the method commit the transaction. If something goes wrong the transactions are not commited (OK), but I don't have the specific exception, only javax.ejb.EJBTransactionRolledbackException: Transaction rolled back. I could use the flush method after try to persist or merge, but it isn't seems right.

So, I've decided don't try to handle the exceptions in EJB service layer leaving my methods like this:

@Stateless
public class EJBService { 

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

    public void save(Animal a) 
    {
        em.persist(a);
    }

and the client (A managed bean, for example), like this:

    @Named
    @RequestScoped
    public class Bean {

        private Animal animal;
        @Inject
        private EJBService service;

        public void save() {
            try
            {
                service.save(animal);
            }
            catch(Exception e)
            {
                //Unwrapping the exception in order to pass the 
                //appropriate message      
            }
        }
    }

In order to show the right messages, the method who invoked the ejb service must to handle the exception by itself, unwrapping the exception.

The question is: Am I right ? If I'm not, what is the best way to handle exceptions ?

  • "More specific exceptions"? You're throwing an `AppException`, which is far from more specific. In addition to that, you're throwing away the real cause of the exception, losing valuable information. In both your examples, you're using exceptions completely wrong. Take a break from EJB, and read up on how to properly use exceptions first. – Kayaman Sep 25 '17 at 06:24
  • As for "show the right message", you never display the exception's internal message to a client. You log the exception, display "Oops, something went wrong" to the user, then read the real cause of the exception from the logs. – Kayaman Sep 25 '17 at 06:26
  • I don't want to throw away the real cause of the exception. What I was trying to say is: I can't catch an exception like PersistenceException using EJB (CMT) method. I don't want to use the flush method from the EntityManager. My question is: I should leave the client get an "EJBTransactionRolledbackException" and manage itself into a try / catch block unwrapping the real exception or I should verify the things that could be wrong in EJB method like verifying if a field is being duplicated and then throw a verified Exception before the method tries to commit ? – Roberto Coelho Sep 25 '17 at 18:06

0 Answers0