1

I'm having trouble adding generics to a piece of code that I'm working on, I've searched around and none of the examples I've seen so far quite capture what I've trying to do so I'm reaching out for help.

Currently I have this code which processes a list of UserDTO objects that have only their ID's populated and gets the full details of each User from a restful web-service:

//userIds  and userDetails declared previously
for (UserDTO user : userIds) {
    UserDTO populatedUser = webResource.path(REST_USER_PATH).path(user.getId().
        toString()).type(MediaType.APPLICATION_XML).get(ClientResponse.class).
            getEntity(UserDTO.class);

    userDetails.add(populatedUser);
}

Now this is going to be a pattern for the piece of work I'm currently undertaking, I'll need to be able to convert lists of DTO objects which have just the Id's populated, to lists of fully populated DTO objects by calling a web service. What I'd like to do is create a generic method to let me do this.

All the different DTO objects that I need to do this for extend our BaseDTO so I came up with the following, unfortunately it does not compile but hopefully it will show what I'm trying to accomplish:

  public <T extends BaseDTO> getListOfPopulatedDTOs(
      List <T extends BaseDTO> unpopulatedDTOs, String restPath) {

      List<BaseDTO> populatedDTOs = new ArrayList<BaseDTO>();

      for (BaseDTO unpopulatedDTO : unpopulatedDTOs) {
          BaseDTO populatedDTO = webResource.path(restPath).path(
              unpopulatedDTO.getId().toString()).type(MediaType.APPLICATION_XML).
                  get(ClientResponse.class).getEntity(T.class);

          populatedDTOs.add(populatedDTO);
      }

      return populatedDTOs;
  }

Any help or advice would be gratefully received. Many thanks in advance :)

2
  • Can you share the compilation errors? Commented Feb 11, 2014 at 17:19
  • 1
    I am learning to - so question - if he wants a generic method - how do you get rid of the 'ClientResponse.class' which is hard-coded in the method, right? Don't you need some type of clazz or something to be more generic, or is ClientResponse a 'base' class for the response data? Commented Feb 11, 2014 at 17:39

3 Answers 3

1

You don't need to give the bounds again in the formal parameter. And also T.class is not valid. You've to pass the Class<T> explicitly to the method. You can change your method to something like this:

public <T extends BaseDTO> List<T> populateDTOList(List<T> unpopulatedDTOs, Class<T> clazz, String restPath) {
    List<T> populatedDTOs = new ArrayList<T>();

    for (T unpopulatedDTO : unpopulatedDTOs) {
        T populatedDTO = webResource.path(restPath)
                            .path(unpopulatedDTO.getId().toString())
                            .type(MediaType.APPLICATION_XML)
                            .get(ClientResponse.class)
                            .getEntity(clazz);

        populatedDTOs.add(populatedDTO);
    }

    return populatedDTOs;
}

Just make sure you have the getId() method declared in type BaseDTO, else you won't be able to access it.

Also, you're missing the return type of the method. I've put it here. And the method is better named as populateDTOList.

Sign up to request clarification or add additional context in comments.

4 Comments

I am learning to - so question - if he wants a generic method - how do you get rid of the 'ClientResponse.class' which is hard-coded in the method, right? Don't you need some type of clazz or something to be more generic, or is ClientResponse a 'base' class for the response data?
@mikemil Good question. You should post it on the question itself, so that we can get answer from OP.
Thanks all for the reply, I'm must grateful for a speedy response. Rohit's answer seems most complete but I am having problems calling the method. I will post additional info in the question. Thanks again!
Actually I solved my compile error, I was just calling with the wrong parameters! Rohit's answer is correct! Thanks again all!
0

You need to declare type information only one time.In a generic method,you do this before teh return type,not in the parameter itself.Just change it to this :-

 public <T extends BaseDTO> getListOfPopulatedDTOs(List <T> unpopulatedDTOs, String restPath) {
List<BaseDTO> populatedDTOs = new ArrayList<BaseDTO>();

for (BaseDTO unpopulatedDTO : unpopulatedDTOs) {
  BaseDTO populatedDTO = webResource.path(restPath).path(unpopulatedDTO.getId().toString()).type(MediaType.APPLICATION_XML)
      .get(ClientResponse.class).getEntity(T.class);

  populatedDTOs.add(populatedDTO);
}

return populatedDTOs;

Comments

0

Generics are only compile time checks. So you can't do T.class because T and all other generic information gets removed during compiling.

Your interface could be something like:

public <T extends BaseDTO> List<T> getListOfPopulatedDTOs(List <T> unpopulatedDTOs, String restPath)

And you can do getEntity(unpopulatedDTOs.get(0).getClass()) (check that the list is not null or 0 size)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.