1

I want to set a timeout on the process of sending a POST request via Spring RestTemplate. For example, if request is not finished within X sec for whatever reasons, I want it to throw an exception and stop execution/release resources, if possible.

Initially, I tried to use a HttpComponentsClientHttpRequestFactory, but didn't succeed and degraded to SimpleClientHttpRequestFactory. Now I just want to make it work with SimpleClientHttpRequestFactory in all cases and then try a more complex solution.

I have the following configuration:

@Bean
public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setConnectTimeout(3_000);
    requestFactory.setReadTimeout(30_000);
    return new RestTemplate(requestFactory);
}

The I use it as follows:

HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "text/xml;charset=UTF-8");
HttpEntity<String> requestEntity = new HttpEntity<>(xmlMsgAsString, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);

I have one destination server, which is currently unreachable, and I have a bunch of XML messages that I need to POST to this server. With the code as above, for majority of messages it works as expected, it throws the following exception after 30 sec:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
    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.postForEntity(RestTemplate.java:445)
    ...
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
    ... 18 common frames omitted

However, for one particular message it's stuck for ~955 secs and then throws the following exception:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://X:Y/Z": Unexpected end of file from server; nested exception is java.net.SocketException: Unexpected end of file from server
    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.postForEntity(RestTemplate.java:445)
    ...
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.SocketException: Unexpected end of file from server
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:851)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1593)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
    at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
    at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:55)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:766)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
    ... 26 common frames omitted

The previous successfully thrown after 30 sec messages and the last one are similar XML messages and destination is the same. The only difference I thought of was the size of messages, the last one is ~204KB, while all previous ones are much smaller. Why the last exception occurs and how to set time restriction on this case?

Spring Boot 2.1.10 running on Jetty

chewse
  • 116
  • 7
  • You would want to look at https://stackoverflow.com/questions/13837012/spring-resttemplate-timeout – pratap Mar 23 '21 at 09:49
  • @pratap thx, but I've already read that post and many others before even posting my own question. I set those two timeout configs, but it doesn't help in one of my cases. – chewse Mar 23 '21 at 10:00

0 Answers0