Search code examples
springhibernateexceptiontransactional

Exception handling in spring


I am developing web application with spring + hibernate. As per my knowledge, it is best practice to put @transactional in service layer. Spring throws DataAccessException in case of any exception while updating data into database.

Below is my high level class structure.

@Transactional
class OrderService {
    public void createOrder() {
        try {
           orderDAO.createOrder();
        } catch (DataAccessException e) {
            // convert into business exception and sends back to presentation logic.
        }
    }

}

What happens here is data access exception is thrown only after completion of method. so if any exception occurs, I am not able to convert it into business exception in catch block.

Work around is to flush the hibernate session in dao method but I do not like this approach. Is there any better approach to this?


Solution

  • I presume you are using Spring MVC, although you do not specify. If you are using Spring MVC, then there are a few different options.

    1. You can create a Filter that looks for the DAE exception and recodes it to be a different status or exception that your front end would better understand. You can look at Spring Security's ExceptionTranslationFilter as an example of how this is already done for different exceptions
    2. You can use a SimpleMappingExceptionResolver to map a specific exception to a particular view. This would allow your presentation layer to be agnostic and not need to know anything about the exception thrown.
    3. You can use an @ExceptionHandler within a specific controller to handle the DAE exception in a general manner and appropriately prepare something for the presentation layer.
    4. As an extension to #3, you can use a @ControllerAdvice to manage all DAE exceptions for any controllers in the webapp.

    You can read about Exception Handling in Spring MVC for more details as well.

    Generally speaking, I find that the best solution is to catch transaction exceptions at a much higher level and manipulate the information to present it to the front end in a way that is back-end agnostic. This allows you to set up your own error codes/etc. The only time I try/catch exceptions in my service itself is if I actually want to attempt a retry or modify the logic flow based on some specific exception and don't want the front end to know about it.