Reputation: 21
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
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
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