Paginação em Memória com JSF
A paginação em memória é realmente muito simples com o JSF e ajuda muito quando a página não contém muitas informações. Normalmente essa página é o espelho de um Managed Bean onde o mesmo possui um atributo referente a sua listagem.
Managed Bean UsuarioBean:
public class UsuarioBean {
private Usuario usuario = new Usuario();
private List<Usuario> listUsuario = new ArrayList<Usuario>();
private UsuarioBO usuarioBO = new UsuarioBO();
private String retorno;
public String list(){
listUsuario = usuarioBO.findAll();
retorno = "showListUsuario";
return retorno;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public List<Usuario> getListUsuario() {
return listUsuario;
}
public void setListUsuario(List<Usuario> listUsuario) {
this.listUsuario = listUsuario;
}
public UsuarioBO getUsuarioBO() {
return usuarioBO;
}
public void setUsuarioBO(UsuarioBO usuarioBO) {
this.usuarioBO = usuarioBO;
}
}
faces-config.xml
<managed-bean>
<description>Bean de Usuários do Sistema</description>
<managed-bean-name>usuarioBean</managed-bean-name>
<managed-bean-class>br.com.view.UsuarioBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Note que o nosso Managed Bean tem escopo de Sessão, sendo todas as informações guardadas na sessão do usuário no momento em que houver uma requisição deste Bean. Esse também é um problema para aplicações de grande porte, quanto mais Beans de sessão sua aplicação possuir mais memória seu servidor terá que alocar para manter as informações e se o tempo de sessão de cada usuário estiver muito longo poderá ocorrer um leak de memória e logo seu servidor ficará fora do ar.
A intenção é ter o máximo de Beans com escopo de requisição e manter informações necessárias através do a4j:keepAlive ou do t:saveState, o primeiro faz parte do pacote a4j encontrado no richFaces e o segundo faz parte do projeto Tomahawk da apache. Os dois conseguem manter um escopo maior que requisição e menor que sessão, o chamado escopo de “conversação” que o JBoss Seam possui. Isso faz com que algumas informações necessárias permaneçam vivas após a requisição ter sido encerrada.
PAGINAÇÃO EM MEMÓRIA
Para fazermos a paginação em memória utilizaremos o método list do Managed Bean para localizar todos os registros, colocar dentro de uma lista que está no escopo da classe e acessarmos na página diretamente em um DataTable ou DataGrid da seguinte forma:
<rich:dataTable id="tabelaUsuario" rows="10" var="c" value="#{usuarioBean.listUsuario}">
<f:facet name="header">
<rich:columnGroup>
<rich:column>
<h: outputText value="Código" />
</rich:column>
<rich:column>
<h: outputText value="Usuário" />
</rich:column>
</rich:columnGroup>
</f:facet>
<rich:column filterBy="#{c.id}" filterEvent="onkeyup">
<f:facet name="header">
<h: outputText value=" " />
</f:facet>
<h: outputText value="#{c.id}" />
</rich:column>
<rich:column filterBy="#{c.usuario}" filterEvent="onkeyup">
<f:facet name="header">
<h: outputText value=" " />
</f:facet>
<h: outputText value="#{c.usuario}" />
</rich:column>
</rich:dataTable>
<rich:datascroller for="tabelaUsuario" maxPages="10" stepControls="hide" />
Note que o dataTable possui algumas informações especificas: A primeira seria a listagem que será utilizada (localizada no atributo value do dataTable), a segunda seria a variável que dará acesso aos atributos da lista, ou seja, o “item da vez”.
Destaquei em negrito alguns atributos interessantes.
Primeiro o filterBy do rich:column. Este atributo informa que, nesta coluna, existirá um filtro. Esse filtro é exibido como uma caixinha de texto logo abaixo do nome da coluna, para fazermos isso é necessário criar o objeto “facet” sendo o header da coluno e dentro desse facet é necessário que tenha um outputText onde o usuário poderá digitar o que desejar localizar.
Isto é um recurso muito interessante mas que funciona muito bem com a paginação em memória, pois todos os itens estão carregados na memória naquele instante e poderão ser “localizados” com o digitar do usuário. Explicando melhor: O usuário ao digitar uma palavra esse filtro irá começar a filtrar a listagem que se encontra na sessão do usuário naquele determinado momento, trazendo apenas as informações digitadas.
Na paginação por demanda isso se torna mais complicado, pois a listagem não está toda na memória, apenas parte dela. Para isso o usuário terá que criar um evento que irá buscar a informação a cada tecla que o usuário digitar, isso poderá acarretar em leak de memória novamente pois, dependendo da quantidade de informações dentro do BD, cada tecla digitada será realizado uma consulta no banco de dados.
Segundo está o nosso paginador padrão do RichFaces, o datascroller. Esse é o responsável por realizar a paginação em memória, nele informamos quantas páginas serão exibidas em seu paginador.
Esse seria um exemplo bem comum para a paginação em memória.
Parabens pelo post, muito bem explicado.