How does spring manage ExceptionHandler priority?
Asked Answered
H

1

19

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)

Hoes answered 10/2, 2018 at 20:7 Comment(5)
there is an annotation @Order(Ordered.HIGHEST_PRECEDENCE)Cooley
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...Marinelli
https://mcmap.net/q/173856/-setting-precedence-of-multiple-controlleradvice-exceptionhandlersScientist
@Scientist 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 ExceptionMarinelli
With two classes of @controlleradvice you can guarantee orderScientist
S
17

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.

Skullcap answered 10/2, 2018 at 20:32 Comment(5)
And ExceptionDepthComparator.Unlade
hum I opened the source code of ExceptionHandlerExceptionResolver, I think the alogorithm is in the method getExceptionHandlerMethod but I don't see where is the code responsible for finding the most "specific" exception handler registeredMarinelli
I didn't see the use of ExceptionDepthComparator in the ExceptionHandlerExceptionResolverMarinelli
I don't suppose there is a part of the docs you can link to as well?Adelaadelaida
Olivier, it's used in org.springframework.web.method.annotation.ExceptionHandlerMethodResolver#getMappedMethodWordsworth

© 2022 - 2024 — McMap. All rights reserved.