Generics with Spring RESTTemplate
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.
Spring RestTemplate and generic types ParameterizedTypeReference collections like ListT
I worked around this using the following generic method:
public <T> List<T> exchangeAsList(String uri, ParameterizedTypeReference<List<T>> responseType) {
return restTemplate.exchange(uri, HttpMethod.GET, null, responseType).getBody();
}
Then I could call:
List<MyDto> dtoList = this.exchangeAsList("http://my/url", new ParameterizedTypeReference<List<MyDto>>() {});
This did burden my callers with having to specify the ParameterizedTypeReference
when calling, but meant that I did not have to keep a static mapping of types like in vels4j's answer
Using Spring RestTemplate in generic method with generic parameter
No, it is not a bug. It is a result of how the ParameterizedTypeReference
hack works.
If you look at its implementation, it uses Class#getGenericSuperclass()
which states
Returns the Type representing the direct superclass of the entity
(class, interface, primitive type or void) represented by this Class.If the superclass is a parameterized type, the
Type
object returned
must accurately reflect the actual type parameters used in the source
code.
So, if you use
new ParameterizedTypeReference<ResponseWrapper<MyClass>>() {}
it will accurately return a Type
for ResponseWrapper<MyClass>
.
If you use
new ParameterizedTypeReference<ResponseWrapper<T>>() {}
it will accurately return a Type
for ResponseWrapper<T>
because that is how it appears in the source code.
When Spring sees T
, which is actually a TypeVariable
object, it doesn't know the type to use, so it uses its default.
You cannot use ParameterizedTypeReference
the way you are proposing, making it generic in the sense of accepting any type. Consider writing a Map
with key Class
mapped to a predefined ParameterizedTypeReference
for that class.
You can subclass ParameterizedTypeReference
and override its getType
method to return an appropriately created ParameterizedType
, as suggested by IonSpin.
Generic restTemplateExchange with generic responseType
I found this answer, and it was working for me:
Unable to get a generic ResponseEntity<T> where T is a generic class "SomeClass<SomeGenericType>"
RestTemplate restTemplate = new RestTemplate();
restTemplate.exchange(pUrl, HttpMethod.POST, pEntity, new ParameterizedTypeReference<ResultListPage<MyObject>>() {});
How to use java generics with restTemplate
Here is what you could try as signature of your method:
public static <T> ResponseEntity<T> execute(String url, RestTemplate restTemplate,
Class<T> generic) {
Spring RestTemplate: how to define the parameter type in a generic class
So I found a solution, which is to override the getType
method of ParameterizedTypeReference
returning a custom made ParameterizedType
like this:
public abstract class GenericClient<DTO> {
private final Class<DTO> dtoClass;
... ctor which sets dtoClass ...
public List<DTO> findAll() {
...
URI uri = ...
ResponseEntity<List<DTO>> exchange = getRestTemplate()
.exchange(uri, HttpMethod.GET, entity, new ParameterizedTypeReference<List<DTO>() {
@Override
public Type getType() {
return new ParameterizedType() {
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[]{dtoClass};
}
};
});
return exchange.getBody(); // OK
}
}
RestTemplate use with a generic response type
can use String
ResponseEntity<String> result = getRestTemplate().exchange(uri, HttpMethod.POST, httpEntity,
new ParameterizedTypeReference<String>() {
}, userId);
Related Topics
Spring - How to Use Multiple Transaction Managers in the Same Application
Using Spring Resttemplate in Generic Method with Generic Parameter
How to Find the Index of an Element in an Int Array
How to Use Bufferedreader in Java
How to Load Files into My Java Application
Differencebetween a Synchronized Method and Synchronized Block in Java
Error 415 Unsupported Media Type: Post Not Reaching Rest If JSON, But It Does If Xml
What Is the Java Equivalent of Sscanf for Parsing Values from a String Using a Known Pattern
Random Number with Probabilities
Scanner Class Skips Over Whitespace
What Are the Date Formats Available in Simpledateformat Class
Differencebetween String and Stringbuffer in Java
Eclipse Autocomplete (Content Assist) with Facelets (Jsf) and Xhtml
Difference Between an Unbound Wildcard and a Raw Type