Pages

Tuesday, September 20, 2011

Exceptions Handling in Spring

Java Servlet Specification comes up with basic exception and HTTP response code mapping. It allows to define customized, user friendly web pages in case of Java exception or HTTP server error response. User never sees exception stacktrace or ugly 404 Not Found server page. This can be simply achieved through configuring deployment description web.xml, e.g.: by adding following entries:
    
        404
        /error/notFound
    
    
    
        403
        /error/denied
    
    
    
        java.lang.Throwable
        /error/generic
    

This is very straightforward solution and can be add to any application very quickly. However there are at least two main drawbacks of such solutions:
  1. Error page customization: Error page cannot be customized (custom error message, displaying error id helpful for the support) depending on for example exception that has been thrown. Servlet container immediately redirects user to the error page.
  2. Invoking application logic: There is no way to perform any additional application logic before redirecting user to the error page like logging, etc.
Spring Framework provides solution that overcomes both these drawbacks. All magic is done by class implementing following interface:
org.springframework.web.servlet.HandlerExceptionResolver
There is attached below sample implementation of the Spring exception resolver (it extends AbstractHandlerExceptionResolver class which adds some additional functionality to the resolver e.g.: allows defining what exceptions this particular resolver should handle: error response statuses, java exceptions, etc; default is all)
package uk.ac.ncl.cs.smart.am2.web.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;

import net.smartam.commons.util.http.UrlUtils;
import uk.ac.ncl.cs.smart.am2.core.exception.SharingSettingUnauthorizedAccess;

/**
 * @author Lukasz Moren
 */
@Component
public class CustomExceptionResolver extends AbstractHandlerExceptionResolver {

    private static Logger logger = LoggerFactory.getLogger(CustomExceptionResolver.class);

    @Override
    protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
                                              Object handler, Exception ex) {

       // log exception
        logger.error("Error:", ex);

        if (ex instanceof SharingSettingUnauthorizedAccess) {

            //this is special type of exception, do not show error but redirect to other page
            final ModelAndView view = new ModelAndView("unauthorized_switch_users");
            final String redirectTo = UrlUtils.buildFullRequestUrl(request);
            view.addObject("redirect_to", redirectTo);
            return view;
            
        } else {      

            //show error page with short explanation
            final ModelAndView error = new ModelAndView("error");
            error.addObject("error_msg", ex.getMessage());
            return error; 
        }
    }
}
This implementation does three main things:
  1. Logs an error
  2. For exception type SharingSettingUnauthorizedAccess it redirects user to some authorization page
  3. By default it adds error message to be displayed and redirects to the error page

No comments:

Post a Comment