2

I have a custom Spring Boot AutoConfiguration class in which I’m creating a @RequestScoped bean of a custom class - Foo. In the same AutoConfiguration class, I’m creating a bean of my global exception handler which is a @ControllerAdvice. All these classes are a packaged as a jar and used as a dependency in my other Spring Boot web application. Whenever there’s an exception in a controller method, the appropriate exception handler is invoked in my global exception handler, except whenever there is an exception in Foo, a BeanCreationException is thrown and none of the global exception handlers get invoked. I tried adding @Order(Ordered.HIGHEST_PRECEDENCE) as suggested in some SO answers, but none of them worked. Is it possible to handle such request scoped bean exceptions in the global exception handler - a @ControllerAdvice? Much appreciated.

EDIT This is my AutoConfiguration class. (This is in a different jar)

@Configuration
@ConditionalOnClass({FooContext.class, MyGlobalExceptionHandler.class})
public class AutoConfiguration {

    // This bean is used in a Controller
    @Order
    @RequestScope
    @Bean
    @ConditionalOnMissingBean(FooContext.class)
    public FooContext fooContext() throws IOException {
        // generateFooContext() throws the exception and Spring wraps it with BeanCreationException.
        return FooContextFactory.generateFooContext(); 
    }

    @Bean
    @ConditionalOnMissingBean
    public MyGlobalExceptionHandler globalExceptionHandler(MyErrorHelper errorHelper) {
        return new MyGlobalExceptionHandler (errorHelper);
    }
}

This is MyGlobalExceptionHandler(This is in a different jar)

@ControllerAdvice
@RefreshScope
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MyGlobalExceptionHandler {

    // Never invoked 
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> render(Exception ex) {
        log.error("Exception occurred: ", ex);
        return errorHelper.throwErrorException(DEFAULT_ERROR_CODE, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /// ... 
}
  • A `@ControllerAdvice` only catches exceptions thrown by a controller. It's annoying that's all that is supported but here we are. Not sure of any exception handler that meets your needs of a bean creation exception handler, but what would it do? I assume it already logs it. – DCTID Apr 28 '20 at 03:57
  • @DCTID Thanks for the response. Currently, it just throws the exception and Spring responds with the "Spring" style JSON response of `500 Internal Server Error` (which is actually the Problem Detail Object). I would instead like to return my own custom error message. – cannot_mutably_borrow Apr 28 '20 at 04:15

1 Answers1

0

I managed to solve it by registering an AbstractHandlerExceptionResolver

@Component
public class ResponseExceptionResolver extends AbstractHandlerExceptionResolver {

    @SneakyThrows
    @Override
    protected ModelAndView doResolveException(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            Exception ex
    ) {
        return handleException(request, response);
    }

    private ModelAndView handleException(
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        response.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);

        ErrorResponse errorResponse = ...
        return new ModelAndView(new MappingJackson2JsonView(), this.getErrorResponse(errorResponse));
    }

    private Map<String, String> getErrorResponse(ErrorResponse errorResponse) {
        return new ObjectMapper().convertValue(errorResponse, new TypeReference<Map<String, String>>() {
        });
    }
}