4

I have a Jersery/JAX-RS client that hits a RESTful API (JSON) that is supposed to return a list of my POJOs:

// Hits: GET localhost:8080/myapp/fizz/widget/{widget_id}
@Override
public List<Widget> getWidgetsByUser(Long id) {
    return webResource.path("fizz").path("widget").path(id.toString()).get(List.class);
}

And a driver to test the client with:

public class Driver {
    public static void main(String[] args) {
        Driver d = new Driver();
        d.run();
    }

    public void run() {
        MyAppService myService = getSomehow();

        List<Widget> widgets = myService.getWidgetResource().getWidgetsByUser(2L);
        for(Widget widget : widgets) {
            System.out.println("\t...and it found Widget #" + widget.getCaseId());
        }
    }
}

When I run this, I get:

Exception in thread "main" java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.me.myapp.Widget
    <stack trace omitted for brevity>

The exception is being thrown from the for-loop:

for(Widget widget : widgets) {

Which tells me the client is sort of working, but that I don't have it configured correctly.

So either Jersey is trying to return pure JSON and isn't attempting to map it back to a list of Widgets, or I am invoking the get(Class<?>) method incorrectly. Any ideas?

IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756
  • 1
    That is quite easy to understand - you are telling Jersey (probably with Jackson under it) to convert response body to `List`. What else can you expect from the framework to do than to just choose whatever the framework wants to use for the list elements. – Pavel Horal Dec 22 '14 at 09:47
  • Thanks @PavelHoral (+1) - so how do I configure Jersey to return a `List`? – IAmYourFaja Dec 22 '14 at 09:51
  • You can workaround the issue by introducting `WidgetCollection` object with the list as its property (that is a common practice I would say). Other from that I would go through Jersey documentation. But you might end up reading Jackson's approach to solving this (`TypeReference`) - however that would probably not play with Jersey's API. – Pavel Horal Dec 22 '14 at 09:56

1 Answers1

8

The comment by Pavel Horal is correct. Without a known type, Jackson (the underlying deserilaizer) will map to LinkedHashMap, so it will return List<LinkedHashMap>

Fix:

For generic types, we should use the other get() method, which takes a GenericType argument. So we should do something like

...get(new GenericType<List<Widget>>(){});
rgommezz
  • 13,536
  • 2
  • 18
  • 23
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720