4

I'd like to have an @ControllerAdvice that is called for all HTTP requests on all controllers. Unfortunately it only triggers if there is a HTTP body in the request. If not, it's completely ignored. Isn't spring supposed to call handleEmptyBody() in this case?

Edit All controllers are annotated with @RestController.

Any ideas?

@ControllerAdvice
public class CatchAllRequestsAdvice implements RequestBodyAdvice {

    private static final Logger LOGGER = LoggerFactory.getLogger(CatchAllRequestsAdvice.class);

    @Override
    public boolean supports(
        MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType
    ) {
        LOGGER.info("");
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(
        HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType
    ) throws IOException {
        LOGGER.info("");
        return inputMessage;
    }

    @Override
    public Object afterBodyRead(
        Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType
    ) {
        LOGGER.info("");
        return body;
    }

    @Override
    public Object handleEmptyBody(
        Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType
    ) {
        LOGGER.info("");
        return body;
    }
}
BetaRide
  • 16,207
  • 29
  • 99
  • 177
  • 1
    What do you want to achieve with this advice? – M. Deinum Jun 29 '20 at 09:09
  • Logging. And yes, I'm aware of the problems with the InputStream that can onyl be read once. – BetaRide Jun 29 '20 at 09:11
  • 2
    If you want to run before every request you are probably better of writing a filter or use one of the already exising request logging filters available in Spring (instead of rolling your own). Also your approach will only work for `@RestControllers` or `@RequestBody` annotated classes not for other requests (like regular `@Controller` without request-body). – M. Deinum Jun 29 '20 at 09:13
  • M. Deinum is right, you could use a `OncePerRequestFilter` – Airy Jun 29 '20 at 09:19
  • All our controllers are annotated with `@RestController`. So the advice should be called for all requests on this controllers, right? But it isn't. It's only called if there's a request body. – BetaRide Jun 29 '20 at 10:04
  • In case the request body is empty, we can implement our custom logic into the `handleEmptyBody` method. We must return a value to use, either the provided object or an entirely new object. – Amit kumar Jun 29 '20 at 10:47
  • Well, that's the probelm, `handleEmptyBody()` is never called if the request body is empty. – BetaRide Jun 29 '20 at 10:53
  • If you have decompiler, you can put a debugger at its invoke function and see what is stopping this. (RequestResponseBodyAdviceChain#handleEmptyBody) – Bala Jun 29 '20 at 14:37
  • Bala is right - whether the method will be called or not depends on several variables. I'd download source code of your Spring's dependencies and debug. – Tomas Zezula Jul 06 '20 at 16:42

0 Answers0