0

I have a function defined which returns a generic list of whatever objects which are implementing PaginationData interface

private <T> List<T> paginate(int pageNumber, int pageSize, int totalAvailable, PaginatedResponse paginatedResponse, String url) {
   List<T> listOfObjects = new ArrayList();
        while (pageNumber * pageSize <= totalAvailable) {
           paginatedResponse = sendRequest(url + "?pageNumber=" + pageNumber, paginatedResponse.getClass());

           listOfObjects.addAll(paginatedResponse
           .getPaginationData()
           .getPaginatedObjectsList());
 
           pageNumber++;
   }
  return listOfObjects;
}

and PaginatedResponse defined like this

public interface PaginatedResponse {

    Pagination getPagination();

    PaginationData getPaginationData();
}

Where PaginationData is an interface defined

public interface PaginationData<T> {

    List<T> getPaginatedObjectsList();
}

sendRequest method looks like this

private <T> T sendRequest(String url, Class<T> clazz) {
   HttpResponse httpResponse = httpClient.send(url);
   
   //Jackson's object mapper to transform the result
   // but this result can be also other type than the PaginatedResponse
   
        try {
            return objectMapper.readValue(httpResponse.getEntity(), clazz);
        } catch (IOException e) {
            throw new ParsingException(e);
        }
   
}

Everything works fine I'm just getting a warning when invoking .addAll() method on the listOfObjects variable. This warning states : Unchecked assignment, java.util.List to java.util.Collection<? extends T> Reason, paginatedResponse.getPaginationData() has raw type so the result of getPaginatedObjectList() is erased.

So the question is how to get rid of the warning when I'm just returning generic objects wrapped in the list and I'm getting them from the generic paginated response which can be of whatever type which implements PaginatedResponse.

MarkyMark
  • 199
  • 1
  • 15
  • 2
    You're using [raw types](https://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it) in a few places. Start by avoiding that. – ernest_k Oct 08 '20 at 17:11

1 Answers1

0

In your interface PaginatedResponse, PaginationData is of raw type. You should correct it as:

public interface PaginatedResponse<T> { // type parameter is required here or at the least at method level getPaginationData()
    Pagination getPagination();
    PaginationData<T> getPaginationData(); // this will remove raw type usage
}

Then, update paginate(...) method as below (argument PaginatedResponse paginatedResponse to PaginatedResponse<T> paginatedResponse to remove raw type usage):

private <T> List<T> paginate(int pageNumber, int pageSize, int totalAvailable, PaginatedResponse<T> paginatedResponse, String url) {
  // ...
}

Additionally, initialise the list as List<T> listOfObjects = new ArrayList<>(); instead of List<T> listOfObjects = new ArrayList(); to remove raw type usage.


Edit for follow up question about sendRequest() method:

Please use TypeReference from jackson instead of Class for sendRequest() method. Please check topic "Type erasure" for more details.

Define the method like this:

private <T> T sendRequest(String url, TypeReference<T> typeReference) {
    // ... your original code ...
    return objectMapper.readValue(httpResponse.getEntity(), typeReference);
    // ... your original code ...
}

Call it like this:

    paginatedResponse = sendRequest(url + "?pageNumber=" + pageNumber, new TypeReference<PaginatedResponse<T>>() {});
Viral Lalakia
  • 331
  • 2
  • 4
  • 14
  • Thanks for the comment @Viral.. unfortunately it only moved warning to the paginatedResponse = sendRequest(url + "?pageNumber=" + pageNumber); method which is returning private T sendRequest(url) – MarkyMark Oct 08 '20 at 21:30
  • @MarkyMark, there is no reference/detail regarding `sendRequest()` method in your question. Please update your question accordingly. – Viral Lalakia Oct 09 '20 at 04:09
  • I've updated the question to show the sendRequest method. Please check – MarkyMark Oct 09 '20 at 07:01
  • @MarkyMark, please check topic "Type erasure" for more details. In your case, you should use `TypeReference` from jackson instead of class for `sendRequest()` method. Define like this: `private T sendRequest(String url, TypeReference typeReference)`, use it like this: `objectMapper.readValue(httpResponse.getEntity(), typeReference);` and pass it like this: `paginatedResponse = sendRequest(url + "?pageNumber=" + pageNumber, new TypeReference>() {});` – Viral Lalakia Oct 09 '20 at 07:48
  • I have updated this answer with details for better understanding. – Viral Lalakia Oct 09 '20 at 08:07
  • ok, that makes sense but.. on the other hand how can I build new TypeReference for a class which implements the PaginatedResponse.. For example when I call ```paginate(1, 100, 300, Account accountsPaginatedResponse, url)``` or ```paginate(1, 100, 300, User usersPaginatedResponse, url)``` – MarkyMark Oct 09 '20 at 08:11
  • Well, that is beyond the scope of original question about warnings about generics. But let me add a possible solution in that case. 1. Update paginate method to: `private > List paginate(int pageNumber, int pageSize, int totalAvailable, TypeReference typeReference, String url)`. Here U must be PaginatedResponse or implementer of it. 2. Call sendRequest like this: `PaginatedResponse paginatedResponse = sendRequest("", typeReference);` 3. Call paginate like this: `paginate(1,100,300, new TypeReference>() {}, url)`. – Viral Lalakia Oct 09 '20 at 08:39