Generics with Spring RESTTemplate
JavaSpringGenericsJacksonResttemplateJava Problem Overview
I have a class like that:
public class Wrapper<T> {
private String message;
private T data;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
and I use resttemplate as follows:
...
Wrapper<Model> response = restTemplate.getForObject(URL, Wrapper.class, myMap);
Model model = response.getData();
...
However it throws a:
ClassCastException
I read that: https://stackoverflow.com/questions/4392326/problem-when-trying-to-use-jackson-in-java but didn't help. There are some topics related to my problem etc.: https://jira.springsource.org/browse/SPR-7002 and https://jira.springsource.org/browse/SPR-7023
Any ideas?
PS: My error is that:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to a.b.c.d.Model
I think resttemplate can not understand my generic variable and maybe it accepts it as an Object instead of generic T. So it becomes a LinkedHashMap. You can read from it here It says that when explaining from what it marshalls to:
> JSON Type | Java Type
>
> object | LinkedHashMap
Java Solutions
Solution 1 - Java
ParameterizedTypeReference has been introduced in 3.2 M2 to workaround this issue.
Wrapper<Model> response = restClient.exchange(loginUrl,
HttpMethod.GET,
null,
new ParameterizedTypeReference<Wrapper<Model>>() {}).getBody();
However, the postForObject/getForObject variant was not introduced.
Solution 2 - Java
The only thing I think you could do is creating a new class that extends Wrapper and uses model as a generic.
class WrapperWithModel extends Wrapper<Model>{};
WrapperWithModel response = restTemplate.getForObject(URL, WrapperWithModel.class);
It's not the best solution, but at least you won't have to unmarshall manually the response.
Solution 3 - Java
Do not use generics with RestTemplate. Wrap request and response object with wrapper object that will hide the generics.