[Resolvido] VRaptor Paginacao

Tem algum plugin oficial do projeto VRaptor para paginacao?

Já achei alguns exemplos aqui, mas queria saber se tem algum recomendado. Acho uma coisa tão genérica que antes de reinventar a roda gostaria de saber se tem alguma coisa já engatilhada.

Valeu

oficial não… mas o http://datatables.net/ (jQuery) e o http://www.displaytag.org (jsp) são boas pedidas.

Valeu o front end é tranquilo o chato é ficar reescrevendo lógica de páginação…Maaaas vamos lá…

em java não dá pra fugir muito de:

@Get("/coisas")
public void lista(int pagina) {
   result.include("pagina", pagina);
   result.include("coisas", dao.lista(pagina);
}

e no dao

public List<Coisa> lista(int pagina) {
   return entityManager.createQuery(....)
       .setFirstResult(pagina * PAGE_SIZE)
       .setMaxResults(PAGE_SIZE)
       .getResultList();
}

talvez adicionando como parametro o tamanho da página tb.

é meio difícil escrever um plugin que deixe mais fácil de usar que isso, se vc já está usando JPA ou Hibernate.

agora se vc não precisa/quer paginar do lado do servidor, os plugins javascript e jsp que eu falei já resolvem.

Valeu pela dica cara, vc é fera.

Me dá mais uma força aqui.

Tipo eu quero passar para minha view via JSON a minha lista de objetos e ainda 2 atributos inteiros com o total de páginas e a pagina atual. Como seria esse Wrapper?

exatamente do jeito que vc descreveu :wink:

uma classe com uma lista e dois atributos inteiros…

na hora de serializar vc tem que fazer:

result.use(Results.json()).withoutRoot().from(wrapper).include("nomeDaLista").serialize();

lá no meu repositório no git tem um exemplo.
O método em javascript carregarVeiculos em:

https://github.com/rogeriopaguilar/Projetos/blob/master/projetos/cadastroveiculos/WebContent/js/cadveiculos-js.jsp

chama o método listarJson em:

e à partir deste método vc consegue chegar até o código que faz a paginação.

JackOld,

Conforme o Lucas mencionou… caso vc esteja trabalhando com jQuery, o componente datatable (datatables.net) é otimo.

Uso no meu projeto e é muito tranquilo de se trabalhar.

Fiz uma classe Wrapper p/ retorno o json de acordo com o o componente da Datatable precisa…

DataTableModel.java

[code]package br.com.virtuoso.prosaude.utils.view;

/**

  • @author guilherme.virtuoso

*/
public class DataTableModel {

private String sEcho;
private int iTotalRecords;
private int iTotalDisplayRecords;
private Object[] aaData;

public String getsEcho() {
    return sEcho;
}

public void setsEcho(String sEcho) {
    this.sEcho = sEcho;
}

public int getiTotalRecords() {
    return iTotalRecords;
}

public void setiTotalRecords(int iTotalRecords) {
    this.iTotalRecords = iTotalRecords;
}

public int getiTotalDisplayRecords() {
    return iTotalDisplayRecords;
}

public void setiTotalDisplayRecords(int iTotalDisplayRecords) {
    this.iTotalDisplayRecords = iTotalDisplayRecords;
}

public Object[] getAaData() {
    return aaData;
}

public void setAaData(Object[] aaData) {
    this.aaData = aaData;
}

}
[/code]

Minhas classes Controller extende uma Controller base para Processos… que tem este método:

[code]
/**
* Metodo Responsavel por alimentar as DataTables nas telas de Pesquisa
* @param data
* @throws Exception
*/
protected void processaDataTable(List<Object[]> data) throws Exception {
String localProcesso = tClass.getName() + “Controller.processaDataTable()”;
if (data == null) {
throw new MetodoNaoImplementadoException("O método " + localProcesso + “, não foi implementado corretamente!”);
}
DataTableModel dtModel = new DataTableModel();
dtModel.setsEcho(new Long(new Date().getTime()).toString());
dtModel.setiTotalDisplayRecords(baseDAO.getTotalRegistrosUltimaConsulta());
dtModel.setiTotalRecords(baseDAO.getTotal());
dtModel.setAaData(data.toArray());

    result.use(Results.json()).withoutRoot().from(dtModel).include("aaData").serialize();
}[/code]

Abaixo um exemplo de uso em uma classe controller:
TabPaisController.java

[code]@Get
@Path("/tabPais/dataTableListaTodos.json")
@Override
@Restrito
public void dataTableListaTodos() {
String localProcesso = tClass.getName() + “Controller.dataTableListaTodos()”;
try {

        String[] colunas = { "id", "descricao", "sigla", "tabAtivo.descricao" };

        Map&lt;String, Object&gt; parametersDataTable = getParametersDataTable();
        List&lt;TabPais&gt; lstTabPais = baseDAO.dataTableListaTodos(colunas, parametersDataTable);
        .
        .
        . RESTANTE DE CODIGO
        .
        .
        List&lt;Object[]&gt; data = new ArrayList&lt;Object[]&gt;();
        for (TabPais tabPais : lstTabPais) {
            Object[] linha = { ..... COLUNAS QUE ALIMENTARAO A DATA TABLE COM ALGUNS TRATAMENTOS ......   };
            data.add(linha);
        }
        super.processaDataTable(data);
    } catch (Exception e) {
        lancarExcecao(e, localProcesso);
    }
}[/code]

Note que no inicio do metodo anterior eu chamo getParametersDataTable(). Este método já traz um Map com todas as variaveis de request que a DataTable trabalha.

getParametersDataTable()

[code]/**
* Retorna os parametros necessarios para o funcionamento da DataTable
* @return
*/
protected Map<String, Object> getParametersDataTable() {

    Map&lt;String, Object&gt; retorno = new HashMap&lt;String, Object&gt;();

    Integer iDisplayLength = new Integer(request.getParameter(&quot;iDisplayLength&quot;) == null ? &quot;0&quot; : request.getParameter(&quot;iDisplayLength&quot;));
    Integer iDisplayStart = new Integer(request.getParameter(&quot;iDisplayStart&quot;) == null ? &quot;0&quot; : request.getParameter(&quot;iDisplayStart&quot;));
    Integer iColumns = new Integer(request.getParameter(&quot;iColumns&quot;) == null ? &quot;0&quot; : request.getParameter(&quot;iColumns&quot;));
    String allSearch = (request.getParameter(&quot;sSearch&quot;) == null ? &quot;&quot; : request.getParameter(&quot;sSearch&quot;));
    Boolean allRegex = new Boolean((request.getParameter(&quot;bRegex&quot;) == null ? false : true));
    Boolean allSearchable = new Boolean((request.getParameter(&quot;bSearchable&quot;) == null ? false : true));
    Boolean allSortable = new Boolean((request.getParameter(&quot;bSortable&quot;) == null ? false : true));

    List fdRegex = new ArrayList();
    List fdSearchable = new ArrayList();
    List fdSortable = new ArrayList();
    List fdDataProp = new ArrayList();
    List fdSearch = new ArrayList();
    List fdSortCol = new ArrayList();
    List fdSortDir = new ArrayList();

    for (int i = 0; i &lt; iColumns; i++) {
        fdRegex.add(new Boolean((request.getParameter(&quot;bRegex_&quot; + i) == null ? false : true)));
        fdSearchable.add(new Boolean((request.getParameter(&quot;bSearchable_&quot; + i) == null ? false : true)));
        fdSortable.add(new Boolean((request.getParameter(&quot;bSortable_&quot; + i) == null ? false : true)));
        fdDataProp.add((request.getParameter(&quot;mDataProp_&quot; + i) == null ? &quot;&quot; : request.getParameter(&quot;mDataProp_&quot; + i)));
        fdSearch.add((request.getParameter(&quot;sSearch_&quot; + i) == null ? &quot;&quot; : request.getParameter(&quot;sSearch_&quot; + i)));
        fdSortCol.add((request.getParameter(&quot;iSortCol_&quot; + i) == null ? &quot;&quot; : request.getParameter(&quot;iSortCol_&quot; + i)));
        fdSortDir.add((request.getParameter(&quot;sSortDir_&quot; + i) == null ? &quot;&quot; : request.getParameter(&quot;sSortDir_&quot; + i)));
    }

    //        System.out.println(&quot;#####################  PARAMETROS DATA TABLE  #################################################&quot;);
    //        System.out.println(&quot;iDisplayLength..:&quot; + iDisplayLength.toString());
    //        System.out.println(&quot;iDisplayStart...:&quot; + iDisplayStart.toString());
    //        System.out.println(&quot;iColumns........:&quot; + iColumns.toString());
    //        System.out.println(&quot;allSearch.......:&quot; + allSearch.toString());
    //        System.out.println(&quot;allRegex........:&quot; + allRegex.toString());
    //        System.out.println(&quot;allSearchable...:&quot; + allSearchable.toString());
    //        System.out.println(&quot;allSortable.....:&quot; + allSortable.toString());
    //        System.out.println(&quot;fdRegex.........:&quot; + fdRegex.toString());
    //        System.out.println(&quot;fdSearchable....:&quot; + fdSearchable.toString());
    //        System.out.println(&quot;fdSortable......:&quot; + fdSortable.toString());
    //        System.out.println(&quot;fdDataProp......:&quot; + fdDataProp.toString());
    //        System.out.println(&quot;fdSearch........:&quot; + fdSearch.toString());
    //        System.out.println(&quot;fdSortCol.......:&quot; + fdSortCol.toString());
    //        System.out.println(&quot;fdSortDir.......:&quot; + fdSortDir.toString());
    //        System.out.println(&quot;#####################  PARAMETROS DATA TABLE  #################################################&quot;);

    // Montando o retorno
    retorno.put(&quot;iDisplayLength&quot;, iDisplayLength);
    retorno.put(&quot;iDisplayStart&quot;, iDisplayStart);
    retorno.put(&quot;iColumns&quot;, iColumns);
    retorno.put(&quot;allSearch&quot;, allSearch);
    retorno.put(&quot;allRegex&quot;, allRegex);
    retorno.put(&quot;allSearchable&quot;, allSearchable);
    retorno.put(&quot;allSortable&quot;, allSortable);
    retorno.put(&quot;fdRegex&quot;, fdRegex);
    retorno.put(&quot;fdSearchable&quot;, fdSearchable);
    retorno.put(&quot;fdSortable&quot;, fdSortable);
    retorno.put(&quot;fdDataProp&quot;, fdDataProp);
    retorno.put(&quot;fdSearch&quot;, fdSearch);
    retorno.put(&quot;fdSortCol&quot;, fdSortCol);
    retorno.put(&quot;fdSortDir&quot;, fdSortDir);

    return retorno;
}[/code]

Bom, trabalhei duro durante um tempo quando iniciei os trabalhos com a datatable do jQuery, p/ que estes componentes ficassem o mais genérico e pratico possivel para uso… :wink:

Hoje em dia a reusabilidade deste codigo no meu sistema é enorme… ficou muito pratico… e espero que lhe ajude em algo tbm… caso decida usar jQuery.

Abraços

Valeu galera pela força, por isso decidi usar o VRaptor aqui na empresa, que por sinal é uma empresa a nível nacional, porque a comunidade é extremamente ativa.

Virtuoso, já estou usando JQuery, alias sou viciado nele, vou dar uma estudada nos códigos apresentados.

Guilherme e JackOld, eu mudaria algumas coisas para que o código fique mais reutilizável…

[quote=guivirtuoso]DataTableModel.java

[code]package br.com.virtuoso.prosaude.utils.view;

/**

  • @author guilherme.virtuoso

*/
public class DataTableModel {

private String sEcho;
private int iTotalRecords;
private int iTotalDisplayRecords;
private Object[] aaData;

public String getsEcho() {
    return sEcho;
}

public void setsEcho(String sEcho) {
    this.sEcho = sEcho;
}

public int getiTotalRecords() {
    return iTotalRecords;
}

public void setiTotalRecords(int iTotalRecords) {
    this.iTotalRecords = iTotalRecords;
}

public int getiTotalDisplayRecords() {
    return iTotalDisplayRecords;
}

public void setiTotalDisplayRecords(int iTotalDisplayRecords) {
    this.iTotalDisplayRecords = iTotalDisplayRecords;
}

public Object[] getAaData() {
    return aaData;
}

public void setAaData(Object[] aaData) {
    this.aaData = aaData;
}

}
[/code]
[/quote]

Ao invés de fazer um POJO, com get e setter, crie um abstract wrapper que vai ter esses atributos:

public abstract class DataTables {
	private List&lt;List&gt;&lt;String&gt;&gt; aaData;
	private long iTotalRecords;
	private long iTotalDisplayRecords;
	private int minSearch;

	@Override
	public String toString() {
		return &quot;{'minSearch':&quot; + minSearch + &quot;, 'iTotalRecords':&quot;
				+ iTotalRecords + &quot;, 'iTotalDisplayRecords':&quot;
				+ iTotalDisplayRecords + &quot;, 'aaData':&quot; + aaData.toString()
				+ &quot;}&quot;;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;

		return this.hashCode() == obj.hashCode();
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	protected void setAaData(List&lt;List&gt;&lt;String&gt;&gt; aaData) {
		if (aaData == null)
			aaData = new ArrayList&lt;List&gt;&lt;String&gt;&gt;();

		this.aaData = aaData;
	}

	protected void setiTotalRecords(long iTotalRecords) {
		if (iTotalRecords &lt; 0)
			iTotalRecords = 0;

		this.iTotalRecords = iTotalRecords;
	}

	protected void setiTotalDisplayRecords(long iTotalDisplayRecords) {
		if (iTotalDisplayRecords &lt; 0)
			iTotalDisplayRecords = 0;

		this.iTotalDisplayRecords = iTotalDisplayRecords;
	}

	protected void setMinSearch(int minSearch) {
		if (minSearch &lt; 0)
			minSearch = 0;

		this.minSearch = minSearch;
	}
}

E depois você extende ele no seu wrapper (Exemplo: uma classe de Pessoas)

public class PessoasDataTables extends DataTables {

	public PessoasDataTables(List&lt;Pessoas&gt; objs, long iTotalRecords,
			long iTotalDisplayRecords, int minSearch) {
		if (objs == null)
			objs = new ArrayList&lt;Pessoas&gt;();

		super.setAaData(this.toListString(objs));
		super.setiTotalRecords(iTotalRecords);
		super.setiTotalDisplayRecords(iTotalDisplayRecords);
		super.setMinSearch(minSearch);
	}

	protected List&lt;List&gt;&lt;String&gt;&gt; toListString(List&lt;Pessoas&gt; objs) {
		List&lt;List&gt;&lt;String&gt;&gt; list = new ArrayList&lt;List&gt;&lt;String&gt;&gt;();

		for (Pessoas obj : objs)
			list.add(this.getAttributes(obj));

		return list;
	}

	private List&lt;String&gt; getAttributes(Pessoas obj) {
		List&lt;String&gt; list = new ArrayList&lt;String&gt;();

		list.add(this.getString(obj.getCode()));
		list.add(this.getString(obj.getName()));

		return list;
	}
}

Assim, você só precisa entregar uma lista de pessoas que ele te retorna uma lista de wrapper, daí você consegue usar em vários locais…

E esse seu método passa a fazer menos coisas:

Valeu pela atenção Rafael, vou estudar oq vc propos.

Agora eu to com uma dúvida no VRaptor, por exemplo, se quando eu passo o Wrapper pra minha view eu dou um include na minha lista, só que eu também preciso incluir um objeto que está dentro dessa lista, só que ele diz que esse objeto nao existe dentro do Wrapper oq é verdade, pois esse objeto esta dentro da minha lista.

Vejam meu retorno:

result.use( Results.json() ).withoutRoot().from(wrapper).include("lista").include("problema").serialize();

problema está dentro de lista e aí como deveria fazer?

Duas dicas:

Primeira:
Tanto o include quanto o exclude, recebem varArgs, ou seja, isso:

Pode ficar assim:

Segunda:
Faça a serialização recursiva, ou seja, ele pega todos os atributos que estão dentro dos seus atributos. E assim vai indo… Eu sugiro que o seu wrapper tenha uma Lista de Strings ao invés de uma lista de Object, pois tudo o que você vai mostrar na tela é String, assim, você não precisa se preocupar em pegar os atributos de dentro da lista. Basta mandar ele pegar a lista.

De qualquer forma, tente a recursiva:

EDIT
Só agora que eu vi que problema está dentro de lista, então eu alterei a primeira dica.

[quote=Rafael Guerreiro]Duas dicas:

Primeira:
Tanto o include quanto o exclude, recebem varArgs, ou seja, isso:

Pode ficar assim:

Segunda:
Faça a serialização recursiva, ou seja, ele pega todos os atributos que estão dentro dos seus atributos. E assim vai indo… Eu sugiro que o seu wrapper tenha uma Lista de Strings ao invés de uma lista de Object, pois tudo o que você vai mostrar na tela é String, assim, você não precisa se preocupar em pegar os atributos de dentro da lista. Basta mandar ele pegar a lista.

De qualquer forma, tente a recursiva:

EDIT
Só agora que eu vi que problema está dentro de lista, então eu alterei a primeira dica.[/quote]

Guerreiro,

primeiramente obrigado por responder. As duas primeiras eu ja havia vasculhado no forum e tinha encontrado, só que não rolou ele disse que não foi possível encontrar problema dentro de lista pois ele é uma java.util.List. Agora a sua última solução com o recursive() funcionou na moral, você aconselha ou desaconselha utilizá-la? Eu particularmente não vejo nenhum problema, a não ser que seja um método custoso.

Tome cuidado com esse recursive, se você tiver uma entidade com relacionamento bidirecional, vai entrar em loop… Outro problema é uma lista de uma classe que possui lista de outra classe… Fica bem pesado. Tenha certeza do que está fazendo.

Eu não sabia se isso funcionaria ou não. Mas é verdade. É um list…

O que eu realmente acho que a melhor forma é se você fizer uma lista de String e quando você for converter do seu objeto para String, leve só o que importa. Pois para o DataTables, tudo será String, faça tráfego somente do que importa.

Se um dia você alterar a sua classe e adicionar mais atributos, se você continuar usando Object, você vai mandar todos os atributos, desnecessariamente. Faça aquele wrapper que vai converter do seu tipo para String. Assim você pode dar um recursive no wrapper sem se preocupar.

[quote=Rafael Guerreiro]Tome cuidado com esse recursive, se você tiver uma entidade com relacionamento bidirecional, vai entrar em loop… Outro problema é uma lista de uma classe que possui lista de outra classe… Fica bem pesado. Tenha certeza do que está fazendo.

Eu não sabia se isso funcionaria ou não. Mas é verdade. É um list…

O que eu realmente acho que a melhor forma é se você fizer uma lista de String e quando você for converter do seu objeto para String, leve só o que importa. Pois para o DataTables, tudo será String, faça tráfego somente do que importa.

Se um dia você alterar a sua classe e adicionar mais atributos, se você continuar usando Object, você vai mandar todos os atributos, desnecessariamente. Faça aquele wrapper que vai converter do seu tipo para String. Assim você pode dar um recursive no wrapper sem se preocupar.[/quote]

Faz sentido o que você disse, estou implementando o Wrapper recebendo String, vamos ver se rola.

Cara, muito obrigado!!!

Repare que é uma lista de lista de String… Fica algo assim:

   &lt;tr&gt; &lt;!--// list[0] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[0][0] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[0][1] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[0][2] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[0][3] --&gt;
   &lt;/tr&gt;
   &lt;tr&gt; &lt;!--// list[1] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[1][0] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[1][1] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[1][2] --&gt;
        &lt;td&gt;&lt;td&gt;&lt;!--// list[1][3] --&gt;
   &lt;/tr&gt;

[quote=Rafael Guerreiro]Repare que é uma lista de lista de String… Fica algo assim:

&lt;tr&gt; &lt;!--// list[0] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[0][0] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[0][1] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[0][2] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[0][3] --&gt; &lt;/tr&gt; &lt;tr&gt; &lt;!--// list[1] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[1][0] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[1][1] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[1][2] --&gt; &lt;td&gt;&lt;td&gt;&lt;!--// list[1][3] --&gt; &lt;/tr&gt; [/quote]

Valeeuu, consegui mano!!! Fiz o Wrapper nos moldes que vc citou e ficou show, nada de recursive() só o include mesmo e escolhendo os atributos que eu vou levar seguindo aquela sua idéia de método. Show!!

Pode me mostrar como que ficou o seu wrapper e a sua chamada do serialize?

Rafael,

Muito legal sua sugestão em transformar o DataTableModel em uma classe abstract p/ otimizar sua reutilizacao…

Vou implementar com carinho essa dica… pois achei que o código evoluiu bastante…

Muitissimo Obrigado! :wink:

Ficou basicamente igual ao que vc propos, pois eu acho que não vou usar o DataTable, quero enxugar bastante o javascript na app.


public class Wrapper {
	
	
	public List< List<String> > lista;
	
	public int qtdPaginas;
	
	public int paginaAtual;
	

	public int getQtdPaginas() {
		return qtdPaginas;
	}

	public void setQtdPaginas(int qtdPaginas) {
		this.qtdPaginas = qtdPaginas;
	}

	public int getPaginaAtual() {
		return paginaAtual;
	}

	public void setPaginaAtual(int paginaAtual) {
		this.paginaAtual = paginaAtual;
	}

	public List<List<String>> getLista() {
		return lista;
	}

	public void setLista(List<List<String>> lista) {
		this.lista = lista;
	}

		
	
	
	
}

E a minha serializacao ficou bem simples também

result.use( Results.json() ).withoutRoot().from(wrap).include("lista").serialize();