君主不是你
君主不是你

Reputation: 489

Why is Spring exception handler not working as expected

When I use @ExceptionHandler within Controller, it's not working as expected.

Here is my code:

@Controller
public class PageController {

    @RequestMapping("/page")
    public ModelAndView index(ModelAndView modelAndView){
        String mess = null;
        mess.split(",");
        modelAndView.setViewName("index");
        return modelAndView;
    }

    @ExceptionHandler({Exception.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Bad Request")
    public ModelAndView handleException(Exception ex, HttpServletRequest request,     HttpServletResponse response){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("message", ex.getMessage());
        modelAndView.addObject("url", request.getRequestURL());
        modelAndView.addObject("code", response.getStatus());
        modelAndView.setViewName("exception");
        return modelAndView;
    }
}

After the application starts with debug mode, I visit http://localhost:8080/page, and handleException is running, but the view is below other than the expected excepction view. Why?

enter image description here

Upvotes: 0

Views: 4657

Answers (1)

rieckpil
rieckpil

Reputation: 12051

The problem is with the @ResponseStatus annotation. Have a look at the following article: http://blog.sizovs.net/spring-rest-exception-handler/. In the mid of this article the author says following:

Warning: when using this annotation on an exception class, or when setting the reason attribute of this annotation, the HttpServletResponse.sendError method will be used. With HttpServletResponse.sendError, the response is considered complete and should not be written to any further. Furthermore, the Servlet container will typically write an HTML error page therefore making the use of a reason unsuitable for REST APIs. For such cases it is preferable to use a org.springframework.http.ResponseEntity as a return type and avoid the use of @ResponseStatus altogether.

According to a Spring article: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc, Spring MVC chains the following three resolvers in the order below:

  • ExceptionHandlerExceptionResolver matches uncaught exceptions against for suitable @ExceptionHandler methods on both the handler (controller) and on any controller-advices.
  • ResponseStatusExceptionResolver looks for uncaught exceptions annotated by @ResponseStatus (as described in Section 1)
  • DefaultHandlerExceptionResolver converts standard Spring exceptions and converts them to HTTP Status Codes (I have not mentioned this above as it is internal to Spring MVC).

So the ResponseStatusExceptionResolver is triggered after the ExceptionHanlderExceptionResolver and uses the default and will display Spring's error page.

For a quick fix try to remove @ResponseStatus and you should see your custom error page in your browser.

Upvotes: 5

Related Questions