9

I had the following controller advice set up, to return an APIs contract for error conditions:

@ControllerAdvice
public class ExceptionHandler : ResponseEntityExceptionHandler()
{
    @ExceptionHandler(Throwable::class)
    @ResponseBody
    public fun onException(ex: Throwable): ResponseEntity<ErrorResponse>
    {
        val errorResponse = ErrorResponse(
           response = ResponseHeader(ex.responseCode(), ex.message))
        return ResponseEntity(errorResponse, HttpStatus.UNAUTHORIZED);
    }

}

It was working fine and then stopped working. Now all exceptions are routed to BasicErrorController, which returns the following format:

{
  "timestamp" : 1450495303166,
  "status" : 403,
  "error" : "Forbidden",
  "message" : "Access Denied",
  "path" : "/profile/candidates"
}

The above is a nice opinionated starting point, but now it won't get out of the way.

  • I've tried replacing the error handlers with one instance of ExceptionHandlerExceptionResolver but that didn't work.
  • I've tried making my own CustomErrorHandler, but that also wasn't suitable since the original exception is no longer in the HttpServletRequest by the time it re-routes to the custom error controller. This information is needed in order to return an appropriate response to the client.

How to I:

  • Make SpringBoot not forward exceptions to an exception controller.
  • Restore @ControllerAdvice exception handlers, so that I can just return an appropriate response body and status code.

On startup spring logs:

main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in exceptionHandler
main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in responseEntityExceptionHandler

Edit:

After reading through the Spring Boot docs, I under stand now that the BasicErrorController is only supposed to fire for any exceptions not handled by a @ControllerAdvice. This appears not to be happening. So the question is why?

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185

1 Answers1

3

I also have a Spring Security filter that evaluates API-Key and Access-Token header credentials. @ControllerAdvice doesn't work here - fair enough, given we're not dealing with a controller endpoint!

Use EntryPoint and AcessDeniedHandler to handle exceptions from security filters. There are can be configured inside:

.exceptionHandling()

And configure FailureHandler if you extends AbstractAuthenticationProcessingFilter in your filter.

 setAuthenticationFailureHandler()

Afaik ErrorController will be overwritten if you will deploy your application under application server.

Ruslan
  • 14,229
  • 8
  • 49
  • 67