Question

I am using Java Callable Future in my code. Below is my main code which uses the future and callables -

public class TimeoutThread {

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newFixedThreadPool(5);
        Future<String> future = executor.submit(new Task());

        try {
            System.out.println("Started..");
            System.out.println(future.get(3, TimeUnit.SECONDS));
            System.out.println("Finished!");
        } catch (TimeoutException e) {
            System.out.println("Terminated!");
        }

        executor.shutdownNow();
    }
}

Below is my Task class which implements the Callable interface and I need to generate URL depending on the hostname we have and then make a call to SERVERS using RestTemplate. If there is any exception in the first hostname, then I will generate URL for another hostname and I will try making a call.

class Task implements Callable<String> {
    private static RestTemplate restTemplate = new RestTemplate();

    @Override
    public String call() throws Exception {

    //.. some code

    for(String hostname : hostnames)  {
            if(hostname == null) {
                continue;
            }
            try {
                String url = generateURL(hostname);         
                response = restTemplate.getForObject(url, String.class);

                // make a response and then break
                break;

            } catch (Exception ex) {
                ex.printStackTrace(); // use logger
            }
        }
    }
}

So my question should I declare RestTemplate as static global variable? Or it should not be static in this scenario?

Was it helpful?

Solution

It doesn't matter either way, static or instance.

RestTemplate's methods for making HTTP requests are thread safe so whether you have a RestTemplate instance per Task instance or a shared instance for all Task instances is irrelevant (except for garbage collection).

Personally, I would create the RestTemplate outside the Task class and pass it as an argument to a Task constructor. (Use Inversion of Control whenever possible.)

OTHER TIPS

From a concurrency standpoint, it doesn't matter. RestTemplate is thread safe, so a single instance or multiple instances is irrelevant to proper functioning of the program.

But you might want to consider AsyncRestTemplate instead as shown here.

Also, as others mention, you should consider an IoC approach to separate the creation of your REST client from its use. This article by Martin Fowler is the seminal discussion on the topic.

In my particular case I have found some reasons why one might want to have more than one instance of RestTemplate.

The RestTemplate is a way to invoke a remote endpoint, but HTTP integration looks deceivingly simple and when you start finding special scenarios that do not apply to all your API calls is when you realize you need a way to define some settings in a case by case basis.

Examples of such scenarios are the following:

  • We have different teams in the company, and by mistake we didn't agree on the time format we wanted to use in our our models. Now, different APIs from different teams use different time formats which forced us to define different JSON mapper settings for those cases. This may also happen if you have to invoke third party services.
  • Not all the APIs we call have the same service level agreements or behave the same all over the year. In high season some APIs may have to support more traffic, etc. This means that the connection timeout settings may be different for different APIs and sometimes even depending on the requirements. So, settings like connection timeout, read timeout and write timeout may be configured differently depending on the service you're invoking.
  • Perhaps circuit breaker setting, like those of Hytrix, may need to be configured per service, and so having a RestTemplate instance per service allows more ability to configure settings in a case by case basis.

As already said, RestTemplate is thread safe.

But, for unit test, use a static variable will bring to you some problems to mock his calls. So, consider to inject the RestTemplate using the class constructor:

@Service
class LoginService {

    private final RestTemplate restTemplate;

    public LoginService(final RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top