3

I'm facing a problem with Spring and restTemplate. I want to send an object (ListResponse) that contains a generic array. The defenition is as follow:

public class ListResponse<T> implements Serializable {

private long total;
private int page;
private int pageSize;
private T[] objects;

I send a request whith restTemplate.getForObject(). As a result I get an object of type ListResponse but the objects array contains an array of LinkedHashMaps instead of an array with objects of type T.

It seems like restTemplate can not convert the elements in the array to their correct type.

How can I make sure that I get an array of objects of type T back ?

Avi
  • 21,182
  • 26
  • 82
  • 121
Tom
  • 613
  • 2
  • 6
  • 9

3 Answers3

2

I had this problem today and here is the solution that I came up with (actually, that one of my co-workers suggested). We use it with an interface that returns List<MyDto>.

When you call the RestTemplate, don't pass in the generic type.
Define: public class MyDtoListTemplate extends ListTemplate<MyDto>

Then, call
MyDtoListTemplate template = restTemplate.getForObject("url", MyDtoListTemplate .class, mapOfPathVariables);

It's a bummer that you have to define a concrete class that extends/implements the generic type, but then the generic information is available to the jackson deserializer.

Nathan
  • 1,576
  • 8
  • 18
1

I remember I was able to deserialize generic classes with Jackson 2. I had to add MappingJackson2HttpMessageConverter converter to RestTemplate before making any Http calls with it.

RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
nilesh
  • 14,131
  • 7
  • 65
  • 79
0

Unfortunately there's no easy way of doing it that I know of. The problem is that the RestTemplate is told which object type to expect. As long as all the fields in this object has a corresponding element in the json/xml, everything works fine. In the case of generics, the serializer doesn't know which class to expect so it just turns the map it gets to a java Map.

You will have the same problem if you tried to getForObject for a generic return type.

Avi
  • 21,182
  • 26
  • 82
  • 121
  • I can imagine that the RestTemplate does not know how to parse the array. But you specify that the return type of the call needs to be from the type ListResponse. By specifying this, shouldn't it be able to know what type of objects are stored in the array ? (Since you specify it?) Anyway, what would be the hard way ? I would like to know it, so I can weigh the pro and cons of it. – Tom Apr 11 '13 at 07:39
  • When you declare an expected type you usually do something like (if for example T suppose to be class named MyClass) - `MyClass.class`. You can't do the same for generics, something like `ListResponse.class`. I'm not sure what's the reason. I guess that's because when you create a generic class you create a template for a class which is actually created only on runtime (when the type is set). About how this can be done - you can perform deserialization yourself. I did that once but I can't find the code to paste here. It's not supposed to be extremely hard. – Avi Apr 11 '13 at 07:57