18

Giving this controller

@GetMapping("/test")
@ResponseBody
public String test() {
  if (!false) {
    throw new IllegalArgumentException();
  }

  return "blank";
}

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(Exception.class)
@ResponseBody
public String handleException(Exception e) {
  return "Exception handler";
}

@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public String handleIllegalException(IllegalArgumentException e) {
  return "IllegalArgumentException handler";
}

Both ExceptionHandler match the IllegalArgumentException because it's a child of Exception class.

When I reach /test endpoint, the method handleIllegalException is called. If I throw a NullPointerException, the method handleException is called.

How does spring knows that it should execute the handleIllegalException method and not the handleException method ? How does it manage the priority when multiple ExceptionHandler match an Exception ?

(I thought the order or the ExceptionHandler declarations was important, but even if I declare handleIllegalException before handleException, the result is the same)

Olivier Boissé
  • 15,834
  • 6
  • 38
  • 56
  • there is an annotation `@Order(Ordered.HIGHEST_PRECEDENCE)` – dehasi Feb 10 '18 at 20:24
  • yes but in my example I didn't set any `@Order`, and the `handleIllegalException` method is called, why not the `handleException` method ? Spring seems to manage the order by itself when no Order is specified... – Olivier Boissé Feb 10 '18 at 20:30
  • https://stackoverflow.com/a/19500823/3003337 – surya Feb 11 '18 at 01:27
  • @surya your link doesn't answer to my question, it speaks about the `@Order` annotation. It doesn't give any explanation about the default order when multiple `ExceptionHandler` match an Exception – Olivier Boissé Feb 11 '18 at 11:56
  • With two classes of @controlleradvice you can guarantee order – surya Feb 11 '18 at 12:54

1 Answers1

16

Spring MVC provides many different methods for Exception handling definitions.

In general, it will try to find the most "specific" exception handler registered to handle the exception. If there is no such a handler, it will try to check for the superclass of exception, maybe there is a handler for it, if it's not found as well, it will go one more level up and so on and so forth, from the most specific to the most general.

If you want to see it in the code of Spring, an entry point to learn this topic would be:

org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver

This class resolves the exceptions registered through @ExceptionHandler methods out of the beans registered in the application context. This class, in turn, uses the another class org.springframework.web.method.annotation.ExceptionHandlerMethodResolver which is responsible for mapping all the methods marked with @ExceptionHandler annotation.

halfer
  • 19,824
  • 17
  • 99
  • 186
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97