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;
}
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.
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.
As per my experience during new project,
- 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
- 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.
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);
}
}