I have multiple @ControllerAdvice classes configured in my project.

One has a configuration limited to a specific package:

@ControllerAdvice("xyz.configuration")
public class ExceptionMapper

A second one has a more broad configuration:

@ControllerAdvice
public class GlobalExceptionHandler

With this setup, the ExceptionHandlerExceptionResolver picks the GlobalExceptionHandler over the ExceptionMapper.

My expectation was for the more narrowly configured class to be picked before the broader one.

Do you share this view, or do you think using @Order is the correct approach here?

Comment From: bclozel

It depends on the exception handler methods signature and other aspects.

Maybe you can share a minimal sample application to demonstrate the problem?

Comment From: kgonia

Here is sample app: https://github.com/kgonia/ControllerAdviceExample

It depends on the exception handler methods signature and other aspects.

And also based on name of beans. In the app is

AExceptionHandler and ExceptionHandler

AExceptionHandler is configured to handle all exceptions ExceptionHandler is configured to handle specific package and specific exception

If you call http://localhost:8081/test/endpoint AExceptionHandler will fire If you rename AExceptionHandler to GlobalExceptionHandle then ExceptionHandler will fire

ExceptionHandlerExceptionResolver in initExceptionHandlerAdviceCache puts all adviceBeans in exceptionHandlerAdviceCache map.

Later when exception is thrown getExceptionHandlerMethod picks ControllerAdviceBean. It checks all adviceBeans in for loop, when AExceptionHandler is first isApplicableToBeanType method returns true because it has no selectors

    private boolean hasSelectors() {
        return (!this.basePackages.isEmpty() || !this.assignableTypes.isEmpty() || !this.annotations.isEmpty());
    }

If AExceptionHandler is renamed to GlobalExceptionHandler then ExceptionHandler is first on exceptionHandlerAdviceCache map and it's picked.

Comment From: SuganthiThomas

To ensure ExceptionHandlerExceptionResolver prioritizes a specific ControllerAdvice for a narrower set of exceptions, particularly those within a defined package, you can leverage the @Order annotation and the assignableTypes or basePackages attributes of @ControllerAdvice.

You can assign any integer value to @Order

@Order(1) has a higher priority than @Order(2). @Order(-10) has a higher priority than @Order(1)