javaspringspring-security

How to manage exceptions thrown in filters in Spring?


I want to use generic way to manage 5xx error codes, let's say specifically the case when the db is down across my whole spring application. I want a pretty error json instead of a stack trace.

For the controllers I have a @ControllerAdvice class for the different exceptions and this is also catching the case that the db is stopping in the middle of the request. But this is not all. I also happen to have a custom CorsFilter extending OncePerRequestFilter and there when i call doFilter i get the CannotGetJdbcConnectionException and it will not be managed by the @ControllerAdvice. I read several things online that only made me more confused.

So I have a lot of questions:

Is there any good way to deal with this? Thanks


Solution

  • So this is what I did:

    I read the basics about filters here and I figured out that I need to create a custom filter that will be first in the filter chain and will have a try catch to catch all runtime exceptions that might occur there. Then i need to create the json manually and put it in the response.

    So here is my custom filter:

    public class ExceptionHandlerFilter extends OncePerRequestFilter {
    
        @Override
        public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            try {
                filterChain.doFilter(request, response);
            } catch (RuntimeException e) {
    
                // custom error response class used across my project
                ErrorResponse errorResponse = new ErrorResponse(e);
    
                response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                response.getWriter().write(convertObjectToJson(errorResponse));
        }
    }
    
        public String convertObjectToJson(Object object) throws JsonProcessingException {
            if (object == null) {
                return null;
            }
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(object);
        }
    }
    

    And then i added it in the web.xml before the CorsFilter. And it works!

    <filter> 
        <filter-name>exceptionHandlerFilter</filter-name> 
        <filter-class>xx.xxxxxx.xxxxx.api.controllers.filters.ExceptionHandlerFilter</filter-class> 
    </filter> 
    
    
    <filter-mapping> 
        <filter-name>exceptionHandlerFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    
    <filter> 
        <filter-name>CorsFilter</filter-name> 
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>