4
votes

I have a server that exposes data with the spring-data-rest project and now I am writing services to consume those data and I started with a generic service that will suit all the common needs, one of which is getting the Page object.

I configured my RestTemplate to use the Jackson2HalModule as suggested here.

I've tried a lot of combinations and I was only able to use consume it properly in a non-generic way like this:

PagedResources<Resource<Company>> response2 = restTemplate.exchange(getUrl(), HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<PagedResources<Resource<Company>>>(){}).getBody();

But trying the same code with T didn't work (Resource links were deserialized but content of Resource object was null)

PagedResources<Resource<T>> response3 = restTemplate.exchange(getUrl(), HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<PagedResources<Resource<T>>>(){}).getBody();

Generically I am only able to deserialize the Company data using the following code:

PagedResources<T> response1 = restTemplate.exchange(getUrl(), HttpMethod.GET, HttpEntity.EMPTY, PagedResources.class).getBody();

But this one doesn't deserialize the Resource object so the Company&Links data of what should be the Resource object are stored in a LinkedHashMap instead.

I also tried using the object mapper on the LinkedHashMap with data but I was unsuccessful. It's been a long day so I might be too close to see the correct way of doing this. I'll appreciate any help with this. Thank you.

The question: Is there a way of getting proper generics working in this case?

No. This doesn't work because of type erasure. You have to inject a non-generic instance of ParameterizedTypeReference (by which I mean without referencing any type variables). I answered a very similar question yesterday. - Andy Turner
@AndyTurner Thank you for your answer, actually I already thought about supplying the non-generic instance from concrete implementation when I made it work, but thought that I'll find a way around it. So it's good to know that there isn't one :) I read about type erasure and understand the concept and the simple examples, but I am not 100% sure what type erasure actually does in this case. Would you be able to describe what is happening under the hood here? I would like to fully understand it . - JIMI
Erasure simply means that it replaces T with Object when compiling (or Bound in the case of T extends Bound). Try doing this explicitly, and compare the results (should be the same). - Andy Turner