Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the best practices to handle exception at Controller, Service and DAO Layer simultaneously in Spring & Hibernate

I am working on Spring 3.2 & Hibernate 3.6, can any one explain how to handle exception in Sping MVC & Hibernate...i just sharing sample code.

Controller Layer

public Integer saveEployee(HttpServletRequest req, HttpServletResponse res){
    Employee empObj = new Employee();
    empObj.setName(req.getParameter("empName"));
    ......................
    ......................
    Integer empId = materService.saveEmployee(empObj);
    return empId; 
}

Service Layer

public Integer saveEmployee(Employee empObj){
    return masterDao.saveEmployee(empObj);
}

DAO Layer

public Integer saveEmployee(Employee empObj){
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    Integer empId = session.save(empObj);
    tx.commit();
    session.close();
    return empId;
}
  1. Now suppose any exception occurred at DAO layer while saving the empObj like d/b got down or connection failed or any other kind of hibernate exception occurred like ConstraintViolationException or IntegrityConstraintViolationException etc.

  2. If there is chances of java exception like NullPointerException or any user defined exception etc to be handle at Controller layer.

So what are the best practices or how to handle the exception at Controller, Service and DAO Layer simultaneously.

like image 986
Naveen Avatar asked Apr 19 '15 14:04

Naveen


2 Answers

As per my experience during new project,

  1. You should not handle exception at DAO layer. Reason: Normally we place @Transactional annotation at Service Layer. hence we need to rollback transaction at service layer. If you handle exception at DAO then it will not rollback. Follow below link to know why we should place @Transaction at Service Layer.
    Where should "@Transactional" be place Service Layer or DAO
  2. You should not handle exception at Service Layer. Reason: As service layer execute multiple DAO for DB operation and we need to rollback transaction if any DAO fails. If we handle exception in service then we may not rollback transaction. There is manual approach for rollback transaction but it is not recommend. TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

So handle transaction in controller layer.

like image 192
chaitanya dalvi Avatar answered Oct 12 '22 04:10

chaitanya dalvi


You don't handle exceptions at all levels of your application simultaneously; you have to consider their contextual meaning and what the appropriate strategy is for your application. Some errors should be ignored, some should be wrapped, some should be allowed to be raised directly.

One method for dealing with exceptions in a spring-mvc application is to wrap fatal errors from the underlying libraries with your own where appropriate, named for the level at which they are thrown, e.g. ServiceException or RepositoryException. A @ControllerAdvice-annotated class can then handle these errors with @ErrorHandler-annotated methods and return 5XX http errors.

Common application errors, like an entity not being found due to an incorrect id can result in a custom exception, e.g. NotFoundException being raised and subsequently caught in your @ControllerAdvice-annotated class.

The advantage to this technique is that you have less error-handling code in your different application layers and can centralize the conversion of exceptions to responses.

An example @ControllerAdvice-annotated class:

@ControllerAdvice
public class ErrorHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler({NotFoundException.class})
    protected ResponseEntity<Object> handleNotFound(RuntimeException e, WebRequest request) {
        return handleExceptionInternal(e, e.getMessage(),
                null,
                HttpStatus.NOT_FOUND, request);
    }

    @ExceptionHandler({ServiceException.class, RepositoryException.class})
    protected ResponseEntity<Object> handleInternalError(RuntimeException e, WebRequest request) {
        return handleExceptionInternal(e, e.getMessage(),
                null,
                HttpStatus.INTERNAL_SERVER_ERROR, request);
    }
}
like image 33
beerbajay Avatar answered Oct 12 '22 04:10

beerbajay