How to set read time out for calling REST services using Spring REST template ?

Photo by Jordan Benton on Pexels.com

Let’s say you are invoking a REST service using Spring’s REST template.

And you want to set the read time out to a certain value. You don’t want the invoked service to take too much time to send data.

You can do this in two ways:

  1. Set the time out locally
  2. Set the time out at the application level

Setting the read time out locally:

Let’s assume you are calling a GET service deployed at localhost:8080 which just returns a string message.

To invoke this using Spring REST template you can do this :

RestTemplate template = new RestTemplate();
  
String response =  template.getForObject("http://localhost:8080/getData",String.class);

The variable response will have the value returned by the GET service.

If you want to wait only for half a second before the GET service returns data , you can set the read time out using SimpleClientRequestFactory like this:

 RestTemplate template = new RestTemplate();

 SimpleClientHttpRequestFactory rf =
                (SimpleClientHttpRequestFactory)template.getRequestFactory();
 rf.setReadTimeout(500);

String response =  template.getForObject("http://localhost:8080/getData",String.class);

An instance of SimpleClientHttpRequestFactory is obtained from the rest template instance. And the time out value is set on it.

That’s it. Now if the GET service takes more than half a second to return data the service throws an exception like this :

java.net.SocketTimeoutException: Read timed out
	at java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:283) ~[na:na]
	at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:309) ~[na:na]
	at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350) ~[na:na]
	at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803) ~[na:na]
	at java.base/java.net.Socket$SocketInputStream.read(Socket.java:982) ~[na:na]

Notice that read time out is different from connection time out . Connection time is the time taken to establish connection with the consumed REST service .Read time is the time taken to read the data returned by the REST service.

Setting the read time out at the application level:

If you want the above read time out configuration for all of the REST services consumed by the application you can add a configuration file and create a custom REST Template inside the file like this:

package com.resttemplate.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestConfig {


    @Bean
    public RestTemplate myRestTemplate(){

        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

        requestFactory.setReadTimeout(500);

        return new RestTemplate(requestFactory);
    }
}

The above configuration creates a customized Spring Bean (RestTemplate bean).

To use this bean, autowire it in the class where you are consuming the third party REST service.

package com.resttemplate.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.client.RestTemplate;



public class RestClient {


    @Autowired
    private RestTemplate restTemplate;


    public String getDataFromService() {

        String response = restTemplate.getForObject("http://localhost:8080/getData", String.class);

        return response;
    }
}

If you invoke the service now and it again takes more than half a second to return data , the same read time out exception is thrown.

Connection time out can be set out the same way as read time out using setConnectTimeOut() method of SimpleClientRequestFactory class.

This design approach followed by Spring is less intuitive though. Why not add a method setReadTimeOut() on the class RestTemplate itself? Why does the developer need to know about SimpleClientRequestFactory? .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s