NagyI
NagyI

Reputation: 5997

Fetching REST resource as List<T> with Jersey

I'm trying to write a generic function in Jersey which can be used to fetch a List of objects of the same type through REST. I based it on the informations found in this forum: link

@Override
public <T> List<T> fetchResourceAsList(String url) {
  ClientConfig cc = new DefaultClientConfig();
  Client c = Client.create(cc);
  if (userName!=null && password!=null) {
    c.addFilter(new HTTPBasicAuthFilter(userName, password)); 
  }
  WebResource resource = c.resource(url);
  return resource.get(new GenericType<List<T>>() {});
}

However this is not working. If i try to execute it, i get the following error: SEVERE: A message body reader for Java class java.util.List, and Java type java.util.List<T>, and MIME media type application/xml was not found.

However if i write this function without templating (replacing T with an actual class name) it just works fine. Of course this way the function loses it's meaning.

Is there a way to fix this?

Upvotes: 21

Views: 24297

Answers (3)

Chris Hinshaw
Chris Hinshaw

Reputation: 7255

Extending on user2323189, you can use Collection instead of List.class so that you will be able to serialize all types extending Collection. I create a simple getter in my base client class and can simply use this to retrive any type of Collection. Not the clazz variable is supplied provided in my constructor so it is not a provided argument. You could probably turn this into a static method and use the signature GenericType> with a parameter for Class to make it even more generic.

public GenericType<Collection<T>> getParameterizedCollectionType() {
        ParameterizedType parameterizedGenericType = new ParameterizedType() {
            public Type[] getActualTypeArguments() {
                return new Type[] { clazz };
            }

            public Type getRawType() {
                return Collection.class;
            }

            public Type getOwnerType() {
                return Collection.class;
            }
        };
        return new GenericType<Collection<T>>(parameterizedGenericType){};
    }

Upvotes: 3

fmucar
fmucar

Reputation: 14548

See GenericType class of jersey which may help you as well

Unmarshaller needs to know what type the object there is before it can unmarhall the returned content . As generics information is not available at runtime so what you are asking is not possible. It cant unsmarhall something that it does not know anything about.

best you can do is ;

public <T> List<T> fetchResourceAsList(Class<?> beanClass, String url) {
    ...

   if(beanCLass.equals(MyBean.class)){
      return resource.get(new GenericType<List<MyBean>>()
   }else if(...){
      ...
   }...
}

or with generics warnings (I am not sure if this will work)

public List fetchResourceAsList(String url) {
    ...
      return resource.get(new GenericType<List<Serializable>>()
}

Upvotes: 6

Bogdan Aksonenko
Bogdan Aksonenko

Reputation: 460

I've found solution https://java.net/projects/jersey/lists/users/archive/2011-08/message/37

public <T> List<T> getAll(final Class<T> clazz) {

    ParameterizedType parameterizedGenericType = new ParameterizedType() {
        public Type[] getActualTypeArguments() {
            return new Type[] { clazz };
        }

        public Type getRawType() {
            return List.class;
        }

        public Type getOwnerType() {
            return List.class;
        }
    };

    GenericType<List<T>> genericType = new GenericType<List<T>>(
            parameterizedGenericType) {
    };

    return service.path(Path.ROOT).path(clazz.getSimpleName())
            .accept(MediaType.APPLICATION_XML).get(genericType);
}

Upvotes: 27

Related Questions