19

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?

simurg
  • 1,177
  • 6
  • 14
AKIWEB
  • 16,538
  • 58
  • 164
  • 276

4 Answers4

23

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.)

Sotirios Delimanolis
  • 252,278
  • 54
  • 635
  • 683
  • 4
    "Personally, I would create the ..." or use dependency injection ;) +1 –  Jan 15 '14 at 18:46
  • 1
    @Rc Right, that's what I meant, Inversion of control wherever possible. Use a DI container if that is possible as well. – Sotirios Delimanolis Jan 15 '14 at 18:47
  • @SotiriosDelimanolis: Thank you for your suggestions.. Can you provide an example how you create RestTemplate outside the class and then pass it as an argument to Task constructor? – AKIWEB Jan 15 '14 at 18:54
  • @Akiweb Create a `Task` constructor that accepts a `RestTemplate` parameter. Then do `new Task(restTemplate)` where `restTemplate` is a `RestTemplate` reference managed by the caller. – Sotirios Delimanolis Jan 15 '14 at 19:22
  • Thank You.. But what will be the advantage of this? Just trying to understand what is the difference with the way I am doing and you are suggesting? – AKIWEB Jan 15 '14 at 19:35
  • @AKIWEB It's a pattern for moving the dependencies around. You can read more about it [here](http://stackoverflow.com/questions/130794/what-is-dependency-injection). – Sotirios Delimanolis Jan 15 '14 at 19:37
4

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.

Vidya
  • 28,359
  • 6
  • 36
  • 63
  • @Vidya I also have similar question [here](http://stackoverflow.com/questions/29466443/how-to-use-httpcomponentsclienthttprequestfactory-with-resttemplate-efficiently) related to `RestTemplate` which you helped me last time. If possible, can you help me out here as well? Any help is greatly appreciated. – AKIWEB Apr 06 '15 at 19:30
  • I don't see synchronized used anywhere in RestTemplate or the classes implementing request execution logic. How is it thread-safe? –  Jan 29 '18 at 04:28
3

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.
Edwin Dalorzo
  • 70,022
  • 25
  • 131
  • 191
  • 2
    Another use case for having more than one RestTemplate is I have an application that interacts with multiple HTTP servers each with different credentials and authentication types. For each server I have a different RestTemplate. – zztonedefzz Mar 14 '17 at 22:11
  • Regarding point #2, cant you change the timeouts from the requestFactory even after your RestTemplate is initialized? So ServiceA.methodA() can dynamically set the read timeout right before doing the request, and same for ServiceB.methodA(). Correct me if I'm wrong because I'm trying to reach a good design in my project. Thanks – prettyvoid Jan 20 '18 at 21:59
  • Agree, we also having a similar situation. In our application we need to connect to 3/more different HTTP/HTTPS server and for each we have to define timeouts and a customized HTTPClient. So for some we have to use a restTemplate from `HttpComponentsClientHttpRequestFactory` which have a feature of using own configurable client and for few SimpleClientHttpRequestFactory. And thus we end up at having separate RestTemplate (though minimuim for same type same can be utilized). Still, if anyone has any goodway apart from this please do share. – Vivek Jul 06 '18 at 10:02
1

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;
    }
}
Dherik
  • 13,091
  • 10
  • 86
  • 132