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