Rocky Hu
Rocky Hu

Reputation: 1346

Spring MVC : the best way to handle exception for Ajax Request and normal request?

I want to define a common exception manger in my project, so I use @ControllerAdvice to do, the snippet of code is below:

@ExceptionHandler(Exception.class)
public ModelAndView handleAllException(HttpServletRequest request, Exception ex) throws Exception
{
    LOGGER.error(ex.getMessage());

    ModelAndView mav = new ModelAndView();
    mav.addObject("exception", ex);
    mav.addObject("url", request.getRequestURL());
    mav.setViewName(ViewConstants.INTERNAL_ERROR_VIEW);
    return mav;
}

it will return a common error page. That's great for normal exception of request. But if this is a Ajax request, the result is so ugly. so I add the code to judge it. The added code is below:

if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
        // return HTTP Status code and response message
    } else {
        // return error page name
    }

I don't think it is the best way, anybody have a good opinion?

Upvotes: 5

Views: 3167

Answers (4)

Mykhaylo Adamovych
Mykhaylo Adamovych

Reputation: 20966

...
public class Application extends SpringBootServletInitializer {

@Bean(name = "simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
    SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
    r.setDefaultErrorView("forward:/errorController");
    return r;
}

@Controller
public class ErrorController {

    public static final Logger LOG = Logger.getLogger(ErrorController.class);

    @RequestMapping(value = "/errorController")
    public ModelAndView handleError(HttpServletRequest request,
            @RequestAttribute("exception") Throwable th) {

        ModelAndView mv = null;
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            if (isBusinessException(th)) {
                mv = new ModelAndView("appAjaxBadRequest");
                mv.setStatus(BAD_REQUEST);
            } else {
                LOG.error("Internal server error while processing AJAX call.", th);
                mv = new ModelAndView("appAjaxInternalServerError");
                mv.setStatus(INTERNAL_SERVER_ERROR);
            }
            mv.addObject("message", getUserFriendlyErrorMessage(th).replaceAll("\r?\n", "<br/>"));
        } else {
            LOG.error("Cannot process http request.", th);
            mv = new ModelAndView("appErrorPage");
            mv.addObject("exeption", th);
        }

        return mv;
    }
}

Upvotes: 0

kranthi117
kranthi117

Reputation: 628

I have all my controllers in different packages based on whether they serve AJAX requests or not. Then I can set #basePackages element on the ControllerAdvice annotations to handle the exception accordingly

Update: See RequestMapping#params and RequestMapping#headers to separate controllers based on headers and/or params

Upvotes: 1

androberz
androberz

Reputation: 934

If you use jQuery for making requests, you could use the following:

jQuery.ajaxSetup({
    headers: { 'ajax-request': true },
    statusCode: {
        400: function (xhr) {
            ...do something
        },
        500: function (xhr) {
            ...do something
        }
        ...
    }
});

Upvotes: 0

Stan
Stan

Reputation: 1430

I would suggest to set error response code on any request, think this is a good practice to notify client that something goes wrong not depending on type of request. And for ajax request you can return same page and identify problem by error code.

Upvotes: 0

Related Questions