I would like to get rid of those PicturesPaginator and PicturesPage and make it generic, but the list() method from the abstract class Page would return a generic List (List<T> or List<GenericModel> since I use Play here).
What I would expect is this list() method to return the correct List, aka List<Picture> in my case. Is this possible ?

Note: I now there is a module for pagination in Play! Framework, my question is mainly for understanding more about java too :)

5 Answers
5

You can view my Play--Pagination module's source code to see how I handle this type of thing. I put my source on github.

What you want to do is make Page generic as well, and probably non-abstract:

public class Page<T> {
public List<T> list() {}
}

And instead of PicturesPage you could just do:

new Page<Picture>()

The Paginator interface would also need to be generified:

public interface Paginator {
public Page<T> page(Integer page);
}

Generifying PicturesPaginator would be harder since you invoke methods on the Picture class. Java's generics implementation erases types at runtime, so you'll have to deal with type tokens and reflection.

Thank you for your help. I don't understand what you saw that I use from the Picture class : I only use items from JPA (find & count). But finally, I upgraded my code to allow generic Classes using T extends GenericModel and I have a problem : the Class<T> typeToken = ... throws this error : java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType. What am I doing wrong?
–
Cyril N.Dec 12 '11 at 19:39

Re: Picture class, I was referring to the class methods find and count which Play! provides for you. Re: ClassCastException -- I would assume you didn't make the PicturesPaginator like I described above, with a subclass that extends a generic base class, providing a parameterized type (the "class PicturesPaginator extends GenericPaginator<Picture>" is an example of that). An alternative approach would be to just add a Class<T> typeToken method parameter to the constructor for GenericPaginator.
–
Lawrence McAlpinDec 12 '11 at 20:17

You assumed correctly! :) I tried to move everything into one Class, moving the content of PicturesPaginator to Page. I finally decided to add the work directly into my model, and call Page with those parameters : JPAQuery (result of find()), Long (result of count()). It's not neat, but at least it works. Thanks for your help :)
–
Cyril N.Dec 12 '11 at 21:08

If I understand you correctly, your problem with introducing generics here are lines like this:

this.query = Picture.find(query, params);

AFAIK you can't invoke static methods on generic types directly, so you'd have to use reflection here. In that case you might have to pass the class of the parameter type as a parameter (or get it from reflection data if it exists), find the method you want to invoke and invoke it.