Spring @ComponentScan exclude/include filters

LppEdd :

As a good practice in a Spring MVC application, the Web configuration should pick up only the "front-end" components, such as @Controller or @RestController.
Every other bean should be picked up by the Root application context.

I've defined the Web configuration as follow (keep in mind I don't need the @EnableMvc annotation, as it extends WebMvcConfigurationSupport)

@Configuration
@ComponentScan(
        basePackages = { ... },
        useDefaultFilters = false,
        includeFilters = @Filter({
                Controller.class,
                ControllerAdvice.class}))

And the Root configuration as follows.

@Configuration
@ComponentScan(
        basePackages = { ... },
        excludeFilters = @Filter({
                Controller.class,
                ControllerAdvice.class}))

I've defined two @RestControllerAdvice classes, the first one catches all generic Exception(s), the second one catches a more specific ServiceException.

When throwing a ServiceException, the specific adviser is never called, instead only the generic one is picked. Base packages are the same in both configuration classes.

Do I need to specify also RestControllerAdvice on the exclude and include filters? Or am I missing something else?

Edit:

Both @RestControllerAdvice are without basePackeges or any specific criteria. And the ServiceException one is actually found and registered.

If I move the exception handler to the working handler than it is called. This is how I got it working. If I move the ServiceException handler in a separate class it is no more invoked.

@RestControllerAdvice
public class GlobalRestControllerAdviser extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleBindException(
            final BindException ex,
            final HttpHeaders headers,
            final HttpStatus status,
            final WebRequest request) {
        return new ResponseEntity<Object>(
                buildPresentableError(ex.getAllErrors().get(0)),
                HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(ServiceException.class)
    protected Response<?> handleServiceException(final ServiceException e) {
        ...
    }

    @ExceptionHandler(Exception.class)
    protected ResponseEntity<Object> handleGenericException(final Exception ex) {
        ...
    }
}

Seems like the most generic ExceptionHandler is overriding the more specific one.

LppEdd :

Basically @ControllerAdvice annotated classes are ordered, which means that if Spring internals find an @ExceptionHandler which accepts the thrown exception, it will use that one and stop.

When having multiple classes it is possible to set the bean priority with @Order (for example). Annotating the ServiceException containing class with @Order made it working.

Also, based on this feature request https://jira.spring.io/browse/SPR-8881 we can specify multiple classes on one @Filter annotation, no need to split them in multiple @Filter(s).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=78062&siteId=1