How to create spring @bean of type RestControllerAdvice in spring configuration class

Tarun Bharti :

I am trying a write RestControllerAdvice which is part of a common library that I want to be available on a present of a certain property. As per our common library, we define all bean via configuration but not with annotation so that we can import that configuration class on demand instead of creating those beans always. But I am finding it difficult to mention that bean is actually of type RestControllerAdvice type in a spring configuration class.

Below is my RestControllerAdvice. I remove the @RestControllerAdvice from this ExceptionHandler otherwise this bean will be created anyways and in my configuration class I added @AliasFor(annotation = RestControllerAdvice.class) but I am not sure if its a correct way and it didn't work either.

@Order(Ordered.HIGHEST_PRECEDENCE)
public class ExceptionHandler {


    @ExceptionHandler(CustomException.class)
    @ResponseBody
    public ResponseEntity<Void> handleMyException(CustomException e) {
        return new ResponseEntity(new UnauthorizedResponse().withMessage(e.getMessage()).withStatus(HttpStatus.UNAUTHORIZED.value()), null, HttpStatus.UNAUTHORIZED);
    }

}


@Configuration
public class ServiceCommonConfiguration {

    @Bean
    @AliasFor(annotation = RestControllerAdvice.class)
    @ConditionalOnProperty(name = PROPERTY, havingValue = "enable")
    public ExceptionHandler serviceCommonExceptionHandler() {
        return new ExceptionHandler();
    }
}
Tomoki Sato :

Please try this:

@Configuration
public class ServiceCommonConfiguration {

    @RestControllerAdvice
    @ConditionalOnProperty(name = PROPERTY, havingValue = "enable")
    private class SpecificExceptionHandler extends ExceptionHandler {
      // Extends 'ExceptionHandler' class in your question.
    }
}

Spring can create beans from inner classes and as far as I tested, instances of even private and non-static classes are successfully created.

Of course, you can use this configuration class by using @Import like below.

@Configuration
@Import(ServiceCommonConfiguration.class)
public class SomeUserOfLibraryConfiguration {.... 

When you neither import the configuration class nor make Spring component-scan the package of the class, the bean of the exception handler is not created.

NOTE

  • You can use @RestControllerAdvice/@ControllerAdvice annotations only on the class level and can't use them on the method level. So you need to declare a class and annotate the class with one of them.

  • @AliasFor annotation, as its javadoc says, 'is used to declare aliases for annotation attributes'(@RestControllerAdvice's source code is a good example). So, I think @AliasFor(annotation = RestControllerAdvice.class) does nothing in your source code above.

See Also

Spring Framework Documentation Core Technologies - 1.3.2. Instantiating Beans

Guess you like

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