1

I have a rest service and is consumed using Spring's RestTemplate with Apache HttpClient as,

    @Autowired
    public ClientImpl(@Value("${base-uri}") final String baseUrl,
                              @Qualifier("restOperations") RestOperations restTemplate) {
        serviceUrl = baseUrl;
        restTemplate = restTemplate;
    }

   private List<ResponseDetails> processRequest(CustomRequest request) throws Exception {
    ResponseEntity<ResponseDetails[]> responseEntity = restTemplate.exchange(serviceUrl, HttpMethod.POST, entity, ResponseDetails[].class);
    if (responseEntity.getStatusCode().value() == 204) {
        return Collections.<ResponseDetails>emptyList();
    }
    ResponseDetails[] response = responseEntity.getBody();
    return response != null ? Lists.newArrayList(response) : Collections.<ResponseDetails>emptyList();
}

When the webservice returns 204 response, then the second service call after 204 response, fails with read timeout.

Spring-web : 4.3.5

I cannot figure out the cause. Any help?

EDIT: From debug logs,

org.apache.http.impl.conn.DefaultHttpResponseParser;Garbage in response: ÿþ{"id":0}HTTP/1.1 204 Could not find

Response in server logs by httpclient:

<204 No Content,{Cache-Control=[no-cache], Pragma=[no-cache], Content-Type=[application/json; charset=utf-16], Expires=[-1], Server=[some], X-AspNet-Version=[someversion], X-Powered-By=[ASP.NET], Date=[somedate]}>

AJJ
  • 3,570
  • 7
  • 43
  • 76
  • have you tried calling responseEntity.getBody() also on 204 response if it makes a difference? – eis Aug 15 '17 at 06:21
  • also, try enabling http wire log to see what the response garbage actually was. – eis Aug 15 '17 at 06:26
  • if getBody() does not help, see [this thread](https://stackoverflow.com/questions/32943192/make-httpclient-consume-garbage-before-next-request) about consuming the garbage. – eis Aug 15 '17 at 06:27
  • @eis there is no content in the response body. added response to the question. Any hint? – AJJ Aug 15 '17 at 08:48
  • @eis there are some text after 204. But these text are not seen in response body. Will that be a cause? and how can these text be consumed? – AJJ Aug 15 '17 at 09:25
  • sounds like it is sending some garbage in response headers. Root cause would be to fix web service in question, as a workaround, see the thread I linked about consuming such garbage. – eis Aug 15 '17 at 09:35
  • also, I was talking about http wire log, which would show all content including garbage. – eis Aug 15 '17 at 09:36
  • The work around the thread that was pointed earlier in comments did not workout for me. – AJJ Aug 15 '17 at 10:15
  • Ok, then add the http wire log with the response to the question. – eis Aug 15 '17 at 10:17
  • @eis why does the httpclient look for response for previous request when opening a connection for new request? Ideally if there is a grabage value in response the particular request should fail and not the next request. Any idea? – AJJ Aug 15 '17 at 14:42
  • it is not expecting anything in the body content of 204 response so does not read it, hence response handler does not see that there is any garbage. However since there is garbage which is not yet consumed the connection stays open until it is -> the next connection gets hit with a read timeout. – eis Aug 15 '17 at 15:32
  • (Ideally there shouldn't be broken web services sending garbage so we wouldn't need any workarounds...) – eis Aug 15 '17 at 15:33
  • Thanks that clears – AJJ Aug 15 '17 at 15:56

1 Answers1

0

HTTP 204 is status code for "No Content", but there seems to be garbage content in the response. This can be seen on your logs:

ÿþ{"id":0}

This is the cause of problems you have.

HTTP client is not expecting anything in the body content of 204 response so does not read it, hence response handler does not see that there is any garbage. However since there is garbage which is not yet consumed the connection stays open until it is read -> the next connection, which tries to reuse the connection, gets hit with a read timeout.

There is a separate thread about a similar problem, where the problem is worked around with a custom HTTP request executor. Using such executor, you could call getBody() to obtain the garbage response body and then next request would not have any issues.

eis
  • 51,991
  • 13
  • 150
  • 199