Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 251
NagyI Avatar asked Aug 12 '11 08:08

NagyI


3 Answers

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);
}
like image 168
Bogdan Aksonenko Avatar answered Oct 25 '22 13:10

Bogdan Aksonenko


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>>()
}
like image 6
fmucar Avatar answered Oct 25 '22 14:10

fmucar


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){};
    }
like image 3
Chris Hinshaw Avatar answered Oct 25 '22 14:10

Chris Hinshaw