When configuring RestTemplate timeout, there're two settings that need to be considered, Connection and Read timeout. They can be configured by using RestTemplateBuilder
in Spring Boot applications or SimpleClientHttpRequestFactory
in Spring applications
Apart from that, you can connect to a non-routable IP address or an existing host with a blocked port to test a RestTemplate Connect timeout. As MockRestServiceServer overwrites RestTemplate Request factory settings, to test Read timeout, you can simulate a delayed backend controller with Thread.sleep
and write an integration test in Spring Boot with @SpringBootTest
Let's walk through this tutorial to explore in more detail
Connection vs Read Timeout
Connection timeout is used when opening a communications link to the remote resource. A java.net.SocketTimeoutException
is thrown if the timeout expires before the connection can be established
Read timeout is used when reading from Input Stream when a connection is established to a remote resource. A java.net.SocketTimeoutException
is also thrown if the timeout expires before there is data available for reading
Configure RestTemplate timeout
In Spring Boot, the connection and read timeout can be configured via RestTemplateBuilder
static final int TIMEOUT = 500;
@Bean
RestTemplate restTemplateWithConnectReadTimeout() {
return new RestTemplateBuilder()
.setConnectTimeout(Duration.ofMillis(TIMEOUT))
.setReadTimeout(Duration.ofMillis(TIMEOUT))
.build();
}
If your project doesn't use Spring Boot, you can configure them via SimpleClientHttpRequestFactory
static final int TIMEOUT = 500;
@Bean
RestTemplate restTemplateTimeoutConfigWithRequestFactory() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(TIMEOUT);
requestFactory.setReadTimeout(TIMEOUT);
return new RestTemplate(requestFactory);
}
The default value of Connect and Read timeout is 0 specifies an infinite timeout
You can find the full configuration code as below
Test a Connect timeout
You can test a RestTemplate Connect timeout setting by requesting to a non-routable IP address such as 10.255.255.255
or to an existing host but with a blocked port such as http://example.com:81
Test a Read timeout
To test the RestTemplate
Read timeout, you can create a test application to simulate a delayed backend API and use @SpringBootTest
to create an integration test
@GetMapping("/test/delay")
public ResponseEntity delay(int millis) throws InterruptedException {
Thread.sleep(millis);
return ResponseEntity.ok().build();
}
Any requests to /test/delay
will be delayed by Thread.sleep(millis)
pauses the execution of the API. Full application file can be found as the following
To create an integration test, use @SpringBootTest
in conjunction with WebEnvironment.RANDOM_PORT
and @LocalServerPort
injected field to create a web test application context servlet based
@SpringBootTest(
webEnvironment = WebEnvironment.RANDOM_PORT,
classes = {RestTemplateWithTimeoutConfig.class, RestTemplateWithTimeoutTestApplication.class}
)
classes
indicates the component classes to use for loading a Spring ApplicationContext
Run the tests
You can run the test cases with your IDE or Maven
$ mvn -Dtest=RestTemplate*TimeoutTest test
RestTemplate*TimeoutTest
with a wildcard character represents for both test classes RestTemplateConnectTimeoutTest
and RestTemplateReadTimeoutTest
All test cases should be passed except testReadTimeout2
as it is using restTemplateWithConnectTimeout
which only Connect timeout is configured
The execution time of RestTemplate requests in the test cases should be greater than the timeout configuration value
Conclusion
In this tutorial, we learned to configure RestTemplate connection and read timeout in Spring and Spring Boot applications
We also learned to test Connect timeout by connecting a RestTemplate to a non-routable IP address or an existing host with a blocked port, and learn to test Read timeout by simulating a delayed backend controller by using Thread.sleep
and write an integration test in Spring Boot by using @SpringBootTest
You can find the full source code on GitHub