how to avoid handling `AbortedException` with Spring WebFlux while handling for generic Exceptions?

20 Views Asked by At

all,

we have a large Spring WebFlux code-base that relies on certain @ExceptionHandler / @RestControllerAdvice. and we have a case for Exception.class that basically logs the exception as error and returns a certain model:

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestError handleUnknown(Exception exception) {
        log.error(Optional.ofNullable(exception.getCause())
                          .map(Throwable::getMessage)
                          .orElse(exception.getMessage()),
                  exception);
        return new RestError(exception);
    }

It should only be used occasionally, because we have also extensive coverage for specific exceptions. But still, we would like to keep this fallback option.

Problem, however, happens when a certain type of issue is causing the exception in question - namely, Netty's AbortedException. An exception handler, in this case, tries to write response body, and we see a completely obscure [xxx] Error [java.lang.UnsupportedOperationException] for HTTP GET "/actuator/health/readiness", but ServerHttpResponse already committed (200 OK) in the logs. This has been bugging me for a long while and I figured something needs to be done it.

So, I've added a custom WebFilter with a SignalListener that now logs this UnsupportedOperationexception with it's stacktrace, and I see that the error is actually Connection has been closed BEFORE send operation and the UnsupportedOperationException happens when the response body is written and a Content-Length header is set, and for whatever reason, these Headers are read-only, thus UnsupportedOperationException:

 java.lang.UnsupportedOperationException: null
    at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:108)
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ Exception handler com.company.common.exception.handler.RestExceptionHandler#handleUnknown(Exception), error="Connection has been closed BEFORE send operation" [DispatcherHandler]
    *__checkpoint ⇢ com.company.common.monitoring.logging.raw.LoggingWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ com.breakwater.sitecheckerservice.common.config.ErrorLoggingWebFilter [DefaultWebFilterChain]
    *__checkpoint ⇢ HTTP POST "/v1/some-url" [ExceptionHandlingWebHandler]
Original Stack Trace:
        at org.springframework.http.ReadOnlyHttpHeaders.set(ReadOnlyHttpHeaders.java:108)
        at org.springframework.http.HttpHeaders.setContentLength(HttpHeaders.java:963)
        at org.springframework.http.codec.EncoderHttpMessageWriter.lambda$write$1(EncoderHttpMessageWriter.java:135)

Question: can an @ExceptionHandler be written so, that it

  • either does NOT handle this particular error type (AbortedException)
  • or does NOT return any value
  • or otherwise signals that no response needs to be written in some cases

while being able to handler other Exception.class-type exceptions normally (by returning a body of a particular type)

?

0

There are 0 best solutions below