Better Exception Handling in JPA

38,970

Solution 1

The idea of exception handling is doing some logic at a single point in case of any failure. The try catch will be used at the final point where you need to handle exception or you need to convert an exception to another exception

Say your app has many layers namely Action, Facade, Persist

Delegate exception In this case any exception that is thrown on Facade can be thrown to the above action layer. In action the particular exception will be caught and handled with proper error message.

//This is in Facade Layer
public void save(Student student) throws AppException{
    //exceptions delegated to action layer

    //call to Persist Layer
}

Converting General Exception to App exception Say in persistence you get and DBException like sqlException. This exception should not be send as such to Action or Facade layer, so we catch the particular exception and then throw a new exception (a user defined exception for application)

//This is in Persist Layer
public void save(Student student) throws AppException{
        //converting general exception to AppException and delegating to Facade Layer

        try{
            em.persist(student);//call to DB. This is in Persist Layer
        }catch(Exception e){
            throw new AppException("DB exception", e)
        }
    }

In action Layer You will catch your exception in action and then handle exception there

  //This is in Action layer
  public void callSave(Student student){
            try{
                //call Facade layer
            }catch(AppException e){
               //Log error and handle
            }
    }

Solution 2

If you want you method to throw the exception got from em.persistance(...), then don't surround that statement with that try/catch block (cause that will catch every exception that's in that block).

The way you approach this problem depends on the application, whether there already exists some legacy code or not. In the case there is legacy code, I suggest you use the same approach (even in for some cases it's not speed optimal) to maintain consistency.

Otherwise I'd suggest following exceptions' "rule of thumb" - they should be treated in the first place where you have all the information you need about them to take an action, else throw them so someone else can handle. (If you throw them away make sure to throw the most specific form of exception that you could throw (not the general Exception)). Handling exceptions when using JPA is no different then handling Java exceptions in general.

I hope this was simple enough information about exceptions without starting a "religious conversation".

Solution 3

If your combination is ejb with jpa, then all jpa exceptions are runtime exceptions.

ejb handling 2 types of exceptions 1) Application Exception 2) System Exception

Application Exceptions checked exceptions basically we are using business validation and business rules.

System Exceptions are runtime exceptions, so that if any runtime excpetion happend ejb container will interfer and convert the runtime exception as remote exception.

For ex: in dao layer

public void store(Cargo cargo) {
    entityManager.persist(cargo);
}

All jpa exceptions are runtime exceptions only.

in ejb service layer:

public TrackingId bookNewCargo(UnLocode originUnLocode,
        UnLocode destinationUnLocode,
        Date arrivalDeadline) {

    Cargo cargo = new Cargo(trackingId, routeSpecification);
    cargoRepository.store(cargo);
    return cargo.getTrackingId();
}

in the ejb layer if any runtime exception happend, ejb container will interfere and convert into remote exception.

In the interface layer:

 public String register() {

    try {
         String   trackingId = bookingServiceFacade.bookNewCargo(
                    originUnlocode,
                    destinationUnlocode,
                    arrivalDeadline);


    } catch (Exception e) {
        throw new RuntimeException("Error parsing date", e); 
    }

so that like this jpa --> ejb --> interface

Share:
38,970
Mark Estrada
Author by

Mark Estrada

Updated on July 27, 2020

Comments

  • Mark Estrada
    Mark Estrada almost 4 years

    I used EJB3/JPA when persisting my entities and I am happy on how it is able to manage my DB related task. My only concern is on the exception handling. My sample code when saving entity always comes in this flavor. Most of the tutorials that I read on the net comes in this flavor also with no regards to exception handling.

    @Stateless
    public class StudentFacade{
        @PersistenceContext(unitName = "MyDBPU")
        private EntityManager em;
    
        public void save(Student student) {
            em.persist(student);
        }
    }
    

    But I dont know whats the best way of exception handling in an EJB app? What should be the best way when handling exception?

    Is this how others is handling the exception? A try catch block on your session facade?

    @Stateless
    public class StudentFacade{
        @PersistenceContext(unitName = "MyDBPU")
        private EntityManager em;
    
        public void save(Student student) {
            try {
                em.persist(student);
            } catch(Exception e) {
                //log it or do something
            }
        }
    }
    

    or letting the method throw an exception?

    public void save(Student student) throws Exception {
        em.persist(student);
    }
    

    I dont know if my understanding is correct since I am still learning EJB. Thanks

    • Naveen Babu
      Naveen Babu over 12 years
      if you are throwing exception, you don't need to catch it
  • Lii
    Lii over 9 years
    If the persistence layer is a EJB then your approach don't work because many exceptions will happen when committing, after the method returns.