Generics with Spring Resttemplate

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



Leave a reply



Submit