Get T generic type of the class to the T in the new GenericType<List<T>>() Java

2k Views Asked by At

I have implmented the follwing class and implemented a search method get list of Object for the given type of T using a REST call.

    public class AmapiService<T extends Resource> implements RestService<T> {


    @Override
    public List<T> search( MultivaluedMap<String, String> aQueryParams ) {
          MultivaluedMap<String, String> lQueryParams = aQueryParams;
          Client lClient = buildClient();

      WebTarget ltarget = lClient.target( iRestDriver.target( aApiUrl ).getUri() );

      for ( String lKey : lQueryParams.keySet() ) {
         ltarget = ltarget.queryParam( lKey, lQueryParams.getFirst( lKey ) );
      }

      List<T> lObjects = null;

      lObjects = ltarget.request( MediaType.APPLICATION_JSON ).get( new GenericType<List<T>>() {
      } );

      return lObjects;
   }
}

this is how the instance is created for the class and search method call.

AmapiService<RFQDefinition> RFQService =
            new AmapiService<RFQDefinition>();

List<RFQDefinition> qfq = RFQService.search( lQueryParam );

when i run this im getting the following error

May 07, 2018 1:48:14 PM org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor aroundReadFrom
SEVERE: MessageBodyReader not found for media type=application/json, type=interface java.util.List, genericType=java.util.List<T>.

That means the RFQDefinition does not set to the T in the new GenericType<List<T>>().

how can i set the type from the T in the AmapiService<T extends Resource> to new GenericType<List<T>>()

if i define it new GenericType<List<RFQDefinition>>() Instead of T its working

3

There are 3 best solutions below

0
JanithOCoder On BEST ANSWER

I have changed the Search method Implementation like this, now it is working. iClass you can take this as a parameter eg: RFQDefinition.class

ObjectMapper mapper = new ObjectMapper();
      JavaType type = mapper.getTypeFactory().constructCollectionType( List.class, iClass );
      List<T> lObjects = null;

      JsonArray lResponse = ltarget.request( MediaType.APPLICATION_JSON ).get( JsonArray.class );
      try {
         lObjects = mapper.readValue( lResponse.toString(), type );
      } catch ( JsonParseException e ) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch ( JsonMappingException e ) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch ( IOException e ) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }  
1
Mạnh Quyết Nguyễn On

It's not related to generic.

The server complains that it does not have any MessageBodyReader to read the application/json body.

Normally, you can add Jackson as json decode/encode for your application

Read this:

https://jersey.github.io/documentation/latest/media.html#json.jackson

4
ernest_k On

Your use of generics does actually not serve a purpose here.

There's no true generic implementation as your response is based on the parameter you give to the service you consume (.get( new GenericType<List<T>>(){})). The type parameter doesn't help this because the code is being invoked by the jax-rs implementation, which does not go through static linking.

In other words, no code is going to compile and run against your class/method using the parameter:

//this is not a valid use-case:
List<ActualType> res = search(aQueryParams);

A simple translation for this can be: Java generics don't make it into the REST API. You have to statically use the Java type for the model your API is supposed to return (just as you do with new GenericType<List<RFQDefinition>>()).