6

I'm using @ControllerAdvice to implement a global exception handler but I got some issues with the use of HttpServletResponse#sendError() method. @ExceptionHandler can catch all kinds of exception, but not HttpServletResponse#sendError() invocations. I understand that HttpServletResponse#sendError() is not an exception, but I need to process it, and then redirect to a generic error page.

I'm using Spring Security for authentication, and in the failed handler, I set status 401 to the response:

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

    String contentType = request.getContentType();
    logger.info(contentType);
    response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );      
}

Then in the @ControllerAdvice, I tried to use @ExceptionHandler and @ResponseStatus to catch 401 but it does not work:

@ResponseStatus (value=HttpStatus.UNAUTHORIZED, reason="You don't have access right on this page")//401
@ResponseBody
@ExceptionHandler(DataIntegrityViolationException.class)
public String handleHttpStatus(DataIntegrityViolationException e){
    return "genericerror";
}

Can @ExceptionHandler methods process HttpServletResponse#sendError() invocations?

Alexey
  • 2,542
  • 4
  • 31
  • 53
user44858
  • 135
  • 1
  • 2
  • 9
  • is this of any use http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc – Ankur Singhal Jul 14 '14 at 16:45
  • yes I referred that post, try to use @ResponseStatus and DataIntegrityViolationException.class but cannot catch the ResponeStatus. Any idea why? – user44858 Jul 15 '14 at 03:52

1 Answers1

1

Spring Security is a separate framework from Spring MVC. Spring Security is a Servlet filter (have a look in your web.xml) which intercepts requests before they reach Spring MVC. You cannot process exceptions that happen at the Spring Security level in @ControllerAdvice (as @ControllerAdvice is part of Spring MVC).

As you said it yourself, HttpServletResponse#sendError() does not throw an exception. According to this document, it sends an error response to the client using the specified status code and clears the buffer.

In your web.xml file you can define static web pages (1) for error response codes and (2) for exceptions. For example:

<error-page>
    <error-code>401</error-code>
    <location>/errors/genericerror</location>
</error-page>
Alexey
  • 2,542
  • 4
  • 31
  • 53
  • Thanks for your answer. Actually I want to catch HttpServletResponse.sendError(). The method in Spring security is just an example. Thanks to you I understand that ControllerAdvice cannot catch exception thrown by Spring security. However If in some controller, I use HttpServletResponse.sendError() to set error status, can ControllerAdvice catch this? I don't want to use configuration in web.xml because we have a lot of HTTP status, we cannot add configuration for all of them – user44858 Jul 15 '14 at 03:55
  • @user44858 If you want to process errors that happen in your controllers with `@ExceptionHandler` methods, you have to throw exceptions instead of calling `HttpServletResponse#sendError()`. See the [Spring Reference](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers) for details on exception handling with `@ExceptionHandler` methods. – Alexey Jul 15 '14 at 06:22