Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Openfeign ErrorDecoder caused java.io.IOException: stream is closed

When i try to implements ErrorDecoder to decode the feign exception, i found the stream in response.body() is closed, so when i try to read the stream and trans to string, it throw java.io.IOException: stream is closed. It's really confused because before the decoder, i didn't do anything to closed the stream advanced.

public class FeignClientErrorDecoder implements ErrorDecoder {
    @Override
    public Exception decode(String methodKey, Response response) {
        log.info("feign client response: {}", response);
        String body = null;
        try {
            body = Util.toString(response.body().asReader(Charset.defaultCharset()));
        } catch (IOException e) {
            log.error("feign.IOException", e);
        }
        return new ServiceException(MessageCode.builder(ExceptionCodeEnum.ERROR));
    }
}
like image 765
bjwzds Avatar asked Apr 28 '20 03:04

bjwzds


2 Answers

I went through this nightmare and it was all the IDE's fault.

The breakpoint in the debug mode was over/before the response.body().asReader causing the stream to close.

Simply started debugging after reading the body and everything went fine.

like image 200
arkadio Avatar answered Oct 04 '22 01:10

arkadio


Logger / System.out.println / IDE Debug mode

Don't use any of the above feature before get the response.body()

If you use any of the above feature to print / log / view your response object then it will process the response.body() internally and close the InputStream. So in this case you will get Stream is closed error.

To fix this issue process the response.body() before the logger. Now you can check this by running your application but not in debug mode.

Sample code:

@Override
  public Exception decode(final String methodKey, final Response response) {
    final String error = getResponseBodyAsString(response.body());
    LOGGER.error("{} failed with response {}", methodKey, response);
    return new ServiceException("Request failed with status: " + response.status()
                                                         + " and error: " + error);
  }

  private String getResponseBodyAsString(final Response.Body body) {
    try {
      return IOUtils.toString(body.asReader(StandardCharsets.UTF_8));
    } catch (final IOException e) {
      LOGGER.error("Failed to read the response body with error: ", e);
    }
    return null;
  }

Note: If you are in debug mode then your IDEA will process this response so even that case also you will get same error. So please don't check this in debug mode.

like image 24
Udhayakumar Baskaran Avatar answered Oct 04 '22 00:10

Udhayakumar Baskaran