Openfeign ErrorDecoder caused java.io.IOException: stream is closed
Asked Answered
A

2

10

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));
    }
}
Atlantes answered 28/4, 2020 at 3:30 Comment(0)
S
27

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.

Steffens answered 4/6, 2020 at 18:2 Comment(4)
Man, you save me a lot of time!!! Thank you very much!!!!Communicate
you deserve a medalChurr
Man you seriously deserve a medalBerglund
Thank you!! I wish I know this a month ago.Clathrate
D
9

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.

Dunk answered 22/9, 2020 at 11:31 Comment(1)
This answer is more correct than above solution because now indicates what is the problem and proposes a coherent code solutionEndogamy

© 2022 - 2024 — McMap. All rights reserved.