Implementei um esquema de paginação simples com o Vraptor4 e JPA e funcionou bem bacana, me inspirei no SpringData, Minhas classes ficaram assim:
public class Page {
private List<T> lista;
private int page;
private Long total;
public Page(List<T> lista, int page, Long total) {
this.lista = lista;
this.page = page;
this.total = total;
}
public List<T> getLista() {
return lista;
}
public int getPage() {
return page;
}
public Long getTotal() {
return total;
}
public int getTotalPages() {
return total == 0 ? 1 : (int) Math.ceil((double) total / (double) 10);
}
}
public class Pageable {
private int page;
private int pageNumber;
private int pageSize;
public Pageable() {
this.pageSize = 10;
}
public void setPageNumber(Integer page) {
this.pageNumber = page;
this.pageSize = 10;
}
public int getPageNumber() {
return pageNumber;
}
public int getPageSize() {
return pageSize;
}
public int getOffSet(){
return pageNumber * pageSize;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.pageNumber = page;
}
}
public abstract class UsuarioRepository extends AbstractEntityRepository<Usuario, Integer> {
public Page<Usuario> todos(int page,int max){
List<Usuario> lista = typedQuery("select u from Usuario u").setFirstResult(page).setMaxResults(max).getResultList();
return new Page<Usuario>(lista,page,total());
}
@Query("select count(u) from Usuario u")
public abstract Long total();
}
@Get("/usuario")
@Controller
public class UsuarioController {
@Inject
private UsuarioRepository repository;
@Inject
private Result result;
@Inject
private Pageable pageable;
@Get
@Path("/lista")
public void lista(Pageable pageable){
result.include("page",repository.todos(pageable.getOffSet(), pageable.getPageSize()));
}
}
e por fim minha jsp bem simplificada:
<c:forEach items='${page.lista}' var='object'>
<tr>
<td><a href="<c:url value='/usuario'/>/${object.usuarioId}">${object.usuarioId}</a></td>
<td>${object.login}</td>
<td>${object.matricula}</td>
<td><a
href="<c:url value='/usuario/remove'/>/${object.usuarioId}">Remove</a></td>
</tr>
</c:forEach>
<div class="col-sm-12 text-center">
<nav>
<ul class="pagination pagination-sm">
<c:forEach begin="1" end="${page.totalPages}" var="index">
<li><a href="?page=${index-1}">${index}</a></li>
</c:forEach>
</ul>
</nav>
</div>
O problema está ocorrendo quando clico nos links da paginação ou quando digito diretamente na url por exemplo localhost:8080/seguranca/usuarios/lista&page=1, o vraptor não está conseguindo popular a propriedade page no bean Pageable, se eu não estiver errado ele deveria ser capaz de popular o bean, correto?
então eu mudei meu padrão de url para:
@Path("/lista/{pageable.page}")
public void lista(Pageable pageable){}
Dessa maneira o Vraptor populou o bean da maneira correta, entretanto cai no problema que este parâmetro page pode ser opcional ou seja, a url localhost:8080/seguranca/usuario/lista deve ser equivalente a url localhost:8080/seguranca/usuario/lista/0, a única forma de fazer que encontrei foi fazendo com que este método lista aceite as duas rotas
@Get
@Path({"/lista/{pageable.page}","/lista"})
public void lista2(Integer page){
Gostaria de saber se o Vraptor aceita parâmetros opcionais na url, tipo de eu passar apenas /listar ele cair na rota /listar/0. Isso iria facilitar demais