188

I would like to set the connection timeouts for a rest service used by my web application. I'm using Spring's RestTemplate to talk to my service. I've done some research and I've found and used the xml below (in my application xml) which I believe is meant to set the timeout. I'm using Spring 3.0.

I've also seen the same problem here Timeout configuration for spring webservices with RestTemplate but the solutions don't seem that clean, I'd prefer to set the timeout values via Spring config

<bean id="RestOperations" class="org.springframework.web.client.RestTemplate"> <constructor-arg> <bean class="org.springframework.http.client.CommonsClientHttpRequestFactory"> <property name="readTimeout" value="${restURL.connectionTimeout}" /> </bean> </constructor-arg> </bean> 

It seems whatever I set the readTimeout to be I get the following:

Network cable disconnected: Waits about 20 seconds and reports following exception:

org.springframework.web.client.ResourceAccessException: I/O error: No route to host: connect; nested exception is java.net.NoRouteToHostException: No route to host: connect

Url incorrect so 404 returned by rest service: Waits about 10 seconds and reports following exception:

org.springframework.web.client.HttpClientErrorException: 404 Not Found

My requirements require shorter timeouts so I need to be able to change these. Any ideas as to what I'm doing wrong?

Many thanks.

13 Answers 13

247

For Spring Boot >= 1.4

@Configuration public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(...) .setReadTimeout(...) .build(); } } 

For Spring Boot <= 1.3

@Configuration public class AppConfig { @Bean @ConfigurationProperties(prefix = "custom.rest.connection") public HttpComponentsClientHttpRequestFactory customHttpRequestFactory() { return new HttpComponentsClientHttpRequestFactory(); } @Bean public RestTemplate customRestTemplate() { return new RestTemplate(customHttpRequestFactory()); } } 

then in your application.properties

custom.rest.connection.connection-request-timeout=... custom.rest.connection.connect-timeout=... custom.rest.connection.read-timeout=... 

This works because HttpComponentsClientHttpRequestFactory has public setters connectionRequestTimeout, connectTimeout, and readTimeout and @ConfigurationProperties sets them for you.


For Spring 4.1 or Spring 5 without Spring Boot using @Configuration instead of XML

@Configuration public class AppConfig { @Bean public RestTemplate customRestTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setConnectionRequestTimeout(...); httpRequestFactory.setConnectTimeout(...); httpRequestFactory.setReadTimeout(...); return new RestTemplate(httpRequestFactory); } } 
Sign up to request clarification or add additional context in comments.

6 Comments

Nice example! Please, remove odd new statement in Spring Boot example
Note that after this configuration, RestTemplate will use apache http client (to set timeout). Apache http client connection pool's default maxPerRoute threads is 5, and max total threads is 10 (httpClient-4.5.2). We need set this ourselves in some situations(such as we need connect to many hosts and need more connections).
Please note connectionRequestTimeout attribute isn't available before 4.1.4.RELEASE
I tried the configuration For Spring Boot >= 1.4 on Spring Boot >= 2.1.8 and I didn't have success. I followed this post (zetcode.com/springboot/resttemplate) to make that configuration.
@ÂngeloPolotto the link you posted gives the same advice as this solution. The article says: "Alternatively, we can use the RestTemplateBuilder to do the job."
|
83

I finally got this working.

I think the fact that our project had two different versions of the commons-httpclient jar wasn't helping. Once I sorted that out I found you can do two things...

In code you can put the following:

HttpComponentsClientHttpRequestFactory rf = (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory(); rf.setReadTimeout(1 * 1000); rf.setConnectTimeout(1 * 1000); 

The first time this code is called it will set the timeout for the HttpComponentsClientHttpRequestFactory class used by the RestTemplate. Therefore, all subsequent calls made by RestTemplate will use the timeout settings defined above.

Or the better option is to do this:

<bean id="RestOperations" class="org.springframework.web.client.RestTemplate"> <constructor-arg> <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <property name="readTimeout" value="${application.urlReadTimeout}" /> <property name="connectTimeout" value="${application.urlConnectionTimeout}" /> </bean> </constructor-arg> </bean> 

Where I use the RestOperations interface in my code and get the timeout values from a properties file.

5 Comments

So this sets the timeouts for all calls through this rest template (which is a singleton). Do you know if it is possible to control the timeouts per request? (eg: 10 sec for a post call and 5 sec for a get call etc)
@ sardo. Where I use the RestOperations interface in my code. we need to create any explicit interface for this?
You said that you are using Spring 3.0 - which I'm also stuck with - but in 3.0 there's is no HttpComponentsClientHttpRequestFactory! Did you update Spring?
The above code doesn't work in latest Spring. It gives ClassCastException java.lang.ClassCastException: org.springframework.http.client.InterceptingClientHttpRequestFactory cannot be cast to org.springframework.http.client.HttpComponentsClientHttpRequestFactory
setReadTimeout is deprecated in Spring 6+
72

This question is the first link for a Spring Boot search, therefore, would be great to put here the solution recommended in the official documentation. Spring Boot has its own convenience bean RestTemplateBuilder:

@Bean public RestTemplate restTemplate( RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(Duration.ofSeconds(500)) .setReadTimeout(Duration.ofSeconds(500)) .build(); } 

Manual creation of RestTemplate instances is a potentially troublesome approach because other auto-configured beans are not being injected in manually created instances.

4 Comments

A note to Spring newcomers like myself: just sticking this in an @Configuration won't do anything. This method requires that you have this RestTemplate injected somwhere that uses it as the argument to the constructor of RestTemplateXhrTransport which you will in turn add to your List of Transports that you pass to your SocksJSClient.
setConnectTimeout and some implementations of setReadTimeout are deprecated
Duration.ofSeconds() is required when you upgrade spring-boot to higher version (v2.6.9 in my case)
Duration.ofSeconds -as its name implies- set duration in terms of "seconds". So in this example, it sets timeouts to 500 seconds (in other words, approximately 8 minutes. It is generally too much for an integration. (Defaults are 30 seconds) So use it wisely.
34

Here are my 2 cents. Nothing new, but some explanations, improvements and newer code.

By default, RestTemplate has infinite timeout. There are two kinds of timeouts: connection timeout and read time out. For instance, I could connect to the server but I could not read data. The application was hanging and you have no clue what's going on.

I am going to use annotations, which these days are preferred over XML.

@Configuration public class AppConfig { @Bean public RestTemplate restTemplate() { var factory = new SimpleClientHttpRequestFactory(); factory.setConnectTimeout(3000); factory.setReadTimeout(3000); return new RestTemplate(factory); } } 

Here we use SimpleClientHttpRequestFactory to set the connection and read time outs. It is then passed to the constructor of RestTemplate.

@Configuration public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder .setConnectTimeout(Duration.ofMillis(3000)) .setReadTimeout(Duration.ofMillis(3000)) .build(); } } 

In the second solution, we use the RestTemplateBuilder. Also notice the parameters of the two methods: they take Duration. The overloaded methods that take directly milliseconds are now deprecated.

Edit Tested with Spring Boot 2.1.0 and Java 11.

Comments

18

Here is a really simple way to set the timeout:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setConnectTimeout(timeout); return clientHttpRequestFactory; } 

Comments

7
  1. RestTemplate timeout with SimpleClientHttpRequestFactory To programmatically override the timeout properties, we can customize the SimpleClientHttpRequestFactory class as below.

Override timeout with SimpleClientHttpRequestFactory

//Create resttemplate RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); //Override timeouts in request factory private SimpleClientHttpRequestFactory getClientHttpRequestFactory() { SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory(); //Connect timeout clientHttpRequestFactory.setConnectTimeout(10_000); //Read timeout clientHttpRequestFactory.setReadTimeout(10_000); return clientHttpRequestFactory; } 
  1. RestTemplate timeout with HttpComponentsClientHttpRequestFactory SimpleClientHttpRequestFactory helps in setting timeout but it is very limited in functionality and may not prove sufficient in realtime applications. In production code, we may want to use HttpComponentsClientHttpRequestFactory which support HTTP Client library along with resttemplate.

HTTPClient provides other useful features such as connection pool, idle connection management etc.

Read More : Spring RestTemplate + HttpClient configuration example

Override timeout with HttpComponentsClientHttpRequestFactory

//Create resttemplate RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); //Override timeouts in request factory private SimpleClientHttpRequestFactory getClientHttpRequestFactory() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); //Connect timeout clientHttpRequestFactory.setConnectTimeout(10_000); //Read timeout clientHttpRequestFactory.setReadTimeout(10_000); return clientHttpRequestFactory; } 

reference: Spring RestTemplate timeout configuration example

Comments

7

SpringBoot version >2

Simple timeout for restTemplate.I have set the read and write timeout for 3 seconds.

@Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){ RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(Duration.ofMillis(3000)).setReadTimeout(Duration.ofMillis(3000)).build(); return restTemplate; } 

If you want to set dynamic timeout values. Kindly refer below.

 //basic imports @SpringBootApplication public class DemoApplication{ //the below values are injected from application.properties file @Value($"{connection.timeout.value}") private String connectionTimeoutValue; @Value("${read.timeout.value}") private String readTimeOutValue; public static void main(String args[]){ SpringApplication.run(DemoApplication.class, args) } @Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){ RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(Duration.ofMillis(connectionTimeoutValue)).setReadTimeout(Duration.ofMillis(readTimeOutValue)).build(); return restTemplate; } } 

Inside the application.properties file:

#change the numerical values according to your need. connection.timeout.value=3000 read.timeout.value=3000 

NOTE:Timeout values are in milliseconds.

for SpringBoot version<2: kindly remove the Duration.ofMillis and provide the values directly like below...

RestTemplate restTemplate= restTemplateBuilder.setConnectTimeout(3000).setReadTimeout(3000).build(); 

2 Comments

how can I set durations dynamically per call in this case?@Santh
@Bilgehan Updated the answer kindly refer it......
3

The current version of Springboot (3.0.X), using org.apache.hc.client5.http.CloseableHttpClient should look something like this

 private CloseableHttpClient httpClient() { Timeout connectionRequestTimeout = Timeout.ofSeconds(WHATEVER_YOU_NEED); Timeout responseTimeout = Timeout.ofSeconds(YET_AGAIN_WHATEVER_YOU_NEED); RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(connectionRequestTimeout) .setResponseTimeout(responseTimeout) .build(); return HttpClients.custom() .setDefaultRequestConfig(requestConfig) .build(); } 

Your CloseableHttpClient should then be used to create a request factory, which in turn should be used to create a rest template.

In the snipet above:

  • The connectionRequestTimeout is a configuration setting that specifies the maximum amount of time to wait for a connection from the connection manager
  • This is different from responseTimeout (or socketTimeout in the older versions of HttpClient), which sets the maximum inactivity period between two consecutive data packets when waiting for the server's response.

Please note that this example is simplistic. If you're using this kind of Appache HttpClient, it's probably because you want to add more stuff to it and not just the timeout.

Comments

1

Setting the timeout only in RestTemplateBuilder didn't work for me when i was using Apache's httpcomponents. I had to set the timeout in the RequestFactory as well.

Here's the entire code:

public RestTemplate templateBuilder() { RestTemplate restTemplate = this.restTemplateBuilder .setConnectTimeout(Duration.ofSeconds(connectTimeout)) .setReadTimeout(Duration.ofSeconds(readTimeout)) .build(); HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setConnectTimeout((int) connectTimeout * 1000); requestFactory.setReadTimeout((int) readTimeout * 1000); requestFactory.setConnectionRequestTimeout((int) connectTimeout * 1000); restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(requestFactory)); return restTemplate; } 

Comments

0

I had a similar scenario, but was also required to set a Proxy. The simplest way I could see to do this was to extend the SimpleClientHttpRequestFactory for the ease of setting the proxy (different proxies for non-prod vs prod). This should still work even if you don't require the proxy though. Then in my extended class I override the openConnection(URL url, Proxy proxy) method, using the same as the source, but just setting the timeouts before returning.

@Override protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException { URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection(); Assert.isInstanceOf(HttpURLConnection.class, urlConnection); urlConnection.setConnectTimeout(5000); urlConnection.setReadTimeout(5000); return (HttpURLConnection) urlConnection; } 

Comments

0

To expand on benscabbia's answer:

private RestTemplate restCaller = new RestTemplate(getClientHttpRequestFactory()); private ClientHttpRequestFactory getClientHttpRequestFactory() { int connectionTimeout = 5000; // milliseconds int socketTimeout = 10000; // milliseconds RequestConfig config = RequestConfig.custom() .setConnectTimeout(connectionTimeout) .setConnectionRequestTimeout(connectionTimeout) .setSocketTimeout(socketTimeout) .build(); CloseableHttpClient client = HttpClientBuilder .create() .setDefaultRequestConfig(config) .build(); return new HttpComponentsClientHttpRequestFactory(client); } 

Comments

0
private static RestTemplate restTemplate; static { HttpComponentsClientHttpRequestFactory rf = new HttpComponentsClientHttpRequestFactory(); rf.setReadTimeout(3 * 1000); rf.setConnectTimeout(2 * 1000); restTemplate = new RestTemplate(rf); restTemplate.getMessageConverters() .add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); } 

Comments

0

By default, RestTemplate uses SimpleClientHttpRequestFactory which depends on the default configuration of HttpURLConnection. Look inside the class source, and you will find this

private int connectTimeout = -1; private int readTimeout = -1; 

By default, RestTemplate uses the timeout property from JDK installed on the machine which is always infinite if not overridden. To override the default JVM timeout, we can pass these properties during the JVM start. The time unit is in milliseconds.

Override default timeout in JVM

-Dsun.net.client.defaultConnectTimeout=5000 -Dsun.net.client.defaultReadTimeout=5000 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.