user12026310
user12026310

Reputation: 21

RestTemplate Multitheading issue

I am facing issue with restTemplate, in a multithreaded environment. I am calling a Rest api with url http://localhost:8080/search, its a post request and I pass a object which have search parameters. I use this to search user,dept etc. This returns a response search object which has such structure, First one is for user and second is for dept

{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"username":"a", userid:"1}, {"username":"b", userid:"2"}, {"username":"c", userid:"3"} ]}
{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"deptname":"a", deptid:"1"}, {"deptid":"b", deptid:"2"} ]}

Sometimes if api is slow the response return is overridden, like for dept and user the same response will be returned like

{{"totalCount":2,"startIndex":0,"endIndex":1,"resultList":[{"username":"a", userid:"1}, {"username":"b", userid:"2"}, {"username":"c", userid:"3"} ]}

I am autowiring a single instance of restTemplate. Also I have tried creating a new instance of restTemplate for each request but that didnt helped.

I am autowiring a single instance of restTemplate. Also I have tried creating a new instance of restTemplate for each request but that didnt helped.

------------Update-------------

Controller Code is something like:

            @RequestMapping("search")
    public @ResponseBody Map<String, Object> search(String type,
        String start, Integer count) {

    Map<String, Object> responseJson = new HashMap<>();

    Criteria criteria = new Criteria();
    criteria.setCount(count);
    criteria.setStartCount(start);
    criteria.setType(type);

    Result<?> result;
    String url = "http://localhost:8080/search";
    HttpEntity<Object> httpEntity = new HttpEntity<>();
    ResponseEntity<? extends Object> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, Result.class);

    if (response.getStatusCode() == HttpStatus.OK) {
        responseJson = (Result<?>) response.getBody();
    }

    return responseJson;
}

I have also checked the API code and seen that they are sending correct response when I received the overridden response. So looks like the request parameters are passing correctly and the response what API is sending is correct.

Upvotes: 0

Views: 502

Answers (2)

Vishal Pawar
Vishal Pawar

Reputation: 788

RestTemplate is not a thread-safe class, so the use of it in a multithreaded environment would get into a weird situation. To avoid that, you create an instance on each request by simply using the new operator:

RestTemplate restTemplate = new RestTemplate();

Upvotes: 0

Edward Aung
Edward Aung

Reputation: 3522

If my memory serves me well, RestTemplate's exchange method is not thread-safe. That is why Spring does not create RestTemplate as a bean. (RestTemplate thread-safety question)

Autowire and use RestTemplateBuilder to get a new RestTemplate. It will solve your problem.

@Autowired RestTemplateBuilder restTemplateBuilder; 

@RequestMapping("search")
public @ResponseBody Map<String, Object> search(String type,
        String start, Integer count) {

    Map<String, Object> responseJson = new HashMap<>();

    Criteria criteria = new Criteria();
    criteria.setCount(count);
    criteria.setStartCount(start);
    criteria.setType(type);

    Result<?> result;
    String url = "http://localhost:8080/search";
    HttpEntity<Object> httpEntity = new HttpEntity<>();
    RestTemplate restTemplate = restTemplateBuilder.build(); // <-- here here
    ResponseEntity<? extends Object> response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, Result.class);

    if (response.getStatusCode() == HttpStatus.OK) {
        responseJson = (Result<?>) response.getBody();
    }

    return responseJson;
}

Upvotes: 0

Related Questions