javaspringnetworkingresttemplatespring-webclient

I/O error on POST request for "https://some-service/" Stream is closed; nested exception is java.io.IOException: Stream is closed


I am trying to upload a file to an external service using post method.

//final InputStream data = .... some imput stream;

 HttpHeaders headers = new HttpHeaders();
      headers.add(AUTHORIZATION_HEADER, String.format(AUTH_TOKEN_HEADER, "my-service-token"));
      headers.setContentType(MediaType.MULTIPART_FORM_DATA);

      LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
      map.add("data", new MultipartInputStreamFileResource(data, fileName));

      HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
      return getRestTemplate().postForObject("https://external-service/", requestEntity, MyResponse.class);

However, I am getting the following error, and honestly I could not find anything for it.

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://external-service/": Stream is closed; nested exception is java.io.IOException: Stream is closed
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:744)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:414)

Note:

Spring-web:5.1.6.RELEASE


Solution

  • Is it possible that your application is wrapped by some monitoring service which intercepts outgoing requests and somehow changes them? An exception may occur in the wrapping service and it may be ignored by the RestTemplate code which simply fails because the Stream is closed.

    By chance :) ,I encountered this at work today and the monitoring service for our application is https://newrelic.com/

    The problem was that we deployed with a newer version of new relic which turned out to be incompatible with the java version of our application. With the new 'new relic' we had an IOException 'insufficient data written' and the stack contained some new relic classes

    sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.close(HttpURLConnection.java:3621)
    sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1529)
    sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1500)
    sun.net.www.protocol.http.HttpURLConnection.getHeaderField(HttpURLConnection.java:3063)
    com.nr.agent.instrumentation.httpurlconnection.InboundWrapper.getHeader(InboundWrapper.java:26)
    com.newrelic.agent.HeadersUtil.getAppDataHeader(HeadersUtil.java:122)
    com.newrelic.agent.CrossProcessTransactionStateImpl.processInboundResponseHeaders(CrossProcessTransactionStateImpl.java:330)
    com.newrelic.agent.tracers.DefaultTracer.recordInboundResponseHeaders(DefaultTracer.java:685)
    com.newrelic.agent.tracers.DefaultTracer.recordExternalMetricsHttp(DefaultTracer.java:722)
    com.newrelic.agent.tracers.DefaultTracer.recordExternalMetrics(DefaultTracer.java:664)
    com.newrelic.agent.tracers.DefaultTracer.recordMetrics(DefaultTracer.java:469)
    com.newrelic.agent.tracers.DefaultTracer.performFinishWork(DefaultTracer.java:284)
    com.newrelic.agent.tracers.DefaultTracer.finish(DefaultTracer.java:236)
    com.newrelic.agent.Transaction.finishTracer(Transaction.java:2370)
    com.newrelic.agent.Transaction.finishSegment(Transaction.java:2365)
    com.newrelic.agent.Segment$1.run(Segment.java:202)
    com.newrelic.agent.ExpirationService.expireSegmentInline(ExpirationService.java:47)
    com.newrelic.agent.Segment.finish(Segment.java:214)
    com.newrelic.agent.Segment.end(Segment.java:144)
    com.nr.agent.instrumentation.httpurlconnection.MetricState.reportExternalCall(MetricState.java:255)
    com.nr.agent.instrumentation.httpurlconnection.MetricState.nonNetworkPreamble(MetricState.java:144)
    

    We disabled the new relic service to see if the requests worked and indeed they did! In the end we reverted to the older version which was updated by mistake. Now I know it is far fetched for this to be your case as well but just maybe...

    I hope this helps... Cheers :)