DataTable Primefaces com paginação e muitos registros

1,479 views
Skip to first unread message

Fernando Oliveira

unread,
Aug 30, 2011, 3:58:01 PM8/30/11
to jav...@googlegroups.com
Pessoal,

Estou tendo o seguinte problema. Preciso pegar informações de clientes em uma tabelas e mostrar as entradas em uma dataTable usando a paginação. Só consegui implementar isso colocando o ManagedBean em escopo de sessão. Quando uso escopo de request que mudo de página os registros não aparecem mais. Não testei com ViewScoped porque estou usando CDI.

O problema é que uma das empresas tem mais de 25000 clientes e quando acesso com o usuário dessa empresa não consigo carregar os valores e fazer a paginação funcionar. Fica só carregando e depois de muito tempo gera uma exceção:

javax.servlet.ServletException: Java heap space

Não sei se estou certo mas acredito que seja porque não tem espaço suficiente para colocar todos os 25000 registros na session. Como eu poderia implementar a paginação sem precisar colocar todos os registros direto na sessão. Tipo, carregando somente os que serão apresentados e quando clicasse lá no dois ele carregasse outros e assim por diante.

Desculpem, sei que é provavelmente um problema besta, mas como estou começando com JSF fiquei meio perdido nisso.

atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     

Bruno Maomeh

unread,
Aug 30, 2011, 4:17:09 PM8/30/11
to jav...@googlegroups.com
pesquise sobre paginação por demanda.. aqui no grupo já teve várias discussões sobre isso.. isso resolverá o seu problema..

uma coisa.. o problema não se dá pelo motivo de conter 25000 registros na session..
mas sim no espaço disponível de memória para o java.. mesmo se teu managedBean for de request, ele dará esse problema..

outra coisa.. NUNCA utilize o escopo de session onde ele não é necessário.. isso fará sua aplicação cair constantemente..
existem vários componentes, para o faces, que criam um escopo maior que o de request e menor que o de session..
o viewScoped é apenas um deles..


--
Você recebeu esta mensagem por que é membro do Javasf
http://groups.google.com/group/javasf
 
Conheça também o Java Brazil: http://groups.google.com/group/thejavabrazil



--
Bruno Maomeh
   http://brunomaomeh.wordpress.com

Fernando Oliveira

unread,
Aug 30, 2011, 4:01:11 PM8/30/11
to jav...@googlegroups.com
Só completando... como rootCause ele coloca o seguinte erro:

java.lang.OutOfMemoryError: Java heap space


atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Em 30 de agosto de 2011 16:58, Fernando Oliveira <nandooli...@gmail.com> escreveu:

Fernando Oliveira

unread,
Aug 30, 2011, 4:08:36 PM8/30/11
to jav...@googlegroups.com
Acabei de ler um slide do Rafael Ponte no slideshare aonde ele fala sobre essa forma de implementar a paginação e fala que a solução seria implementar paginação sobre demanda. Alguém poderia me dar uma luz sobre como faço isso!?


atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Matruskan

unread,
Aug 30, 2011, 4:22:37 PM8/30/11
to jav...@googlegroups.com
Dê uma olhada aqui:

Carlos Amaral

unread,
Aug 30, 2011, 6:51:11 PM8/30/11
to jav...@googlegroups.com
Eu ia propor justamente pra voce dar uma olhada nisto aí. Perceba que lá voce tem 100.000.000 (cem milhões) de carros.
E a coisa rola rapidinho e leve.

p.s.: é paginação SOB demanda.
--
Carlos Amaral
(11) 8827-0162

Fernando Oliveira

unread,
Aug 31, 2011, 2:11:44 PM8/31/11
to jav...@googlegroups.com
Vlw pessoal,

Estou tentando usar o lazy loading como vocês recomendaram, mas a primeira página não mostra nenhum registro e se clico para ir pra alguma outra página a seguinte Exception é lançada:

Grave: Error Rendering View[/index.xhtml]
java.lang.ArithmeticException: / by zero
    at org.primefaces.model.LazyDataModel.setRowIndex(LazyDataModel.java:62)
    at javax.faces.component.UIData.setRowIndexWithoutRowStatePreserved(UIData.java:485)
    at javax.faces.component.UIData.setRowIndex(UIData.java:473)
    at javax.faces.component.UIData.visitTree(UIData.java:1401)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
    at javax.faces.component.UIForm.visitTree(UIForm.java:344)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1600)
    at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:376)
    at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:297)
    at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
    at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:981)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:390)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)


Já procurei um bocado no google e no grupo, mas não consigo encontrar o erro. Minha classe está assim:


import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.servlet.http.HttpSession;

import org.primefaces.model.LazyDataModel;

import br.com.aloo.hotspot.bean.Cliente;
import br.com.aloo.hotspot.bean.Empresa;
import br.com.aloo.hotspot.dao.ClienteDAO;

@Named("tableClientes")
@RequestScoped
public class TableClientesController implements Serializable {
   
    /**
     *
     */
    private static final long serialVersionUID = -6031863689532220186L;
    private LazyDataModel<Cliente> lazyModel;
   
    /**
     * @return the lazyModel
     */
    public LazyDataModel<Cliente> getLazyModel() {
        return lazyModel;
    }

    public TableClientesController () {
        lazyModel = new LazyDataModel<Cliente>() {
           
           
            /**
             *
             */
            private static final long serialVersionUID = -7523175909484101194L;

            @Override
            public List<Cliente> load(int first, int pageSize, String sortField,
                    boolean sortOrder, Map<String, String> filters) {
               
                setPageSize(pageSize);
                List<Cliente> lista = new ArrayList<Cliente>();
                populateList(lista, first, pageSize);
                               
                return lista;
            }
           
            @Override
            public int getRowCount() {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
                Empresa emp = (Empresa) session.getAttribute("emp");
               
                ClienteDAO dao = new ClienteDAO();
               
                return dao.getNumeroDeClientes(emp.getFlag());
            }
           
           
        };
       
    }
   
    protected void populateList (List<Cliente> lista, int first, int pageSize) {
       
        ClienteDAO dao = new ClienteDAO();
       
        FacesContext facesContext = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
        Empresa emp = (Empresa) session.getAttribute("emp");
       
        lista = dao.getListaByFlag(emp.getFlag(), first, pageSize);
    }
}


Alguém tem idéia do que pode estar acontecendo!?


atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Mayara Madeira Trevisol

unread,
Aug 31, 2011, 2:22:56 PM8/31/11
to javasf: JavaServer Faces Group
Oi Fernando...

no inicio da pilha de erros ele coloca
"java.lang.ArithmeticException: / by zero "

voce esta tentando fazer alguma divisão em algum dos métodos chamados
pela tela?

da uma conferida no seu MBean se não esta dividindo um valor zerado...

Abraços,

Mayara Madeira Trevisol

Rafael Pestano

unread,
Aug 31, 2011, 2:29:32 PM8/31/11
to jav...@googlegroups.com
Boa tarde Fernando,

Vi que você está utilizando escopo de request você teria como incluir o CODI(cdi ext) e tentar com ViewAccessScoped?

pra incluir o codi no projeto basta adicionar um jar

1 - utilizando maven:

<dependency>
    <groupId>org.apache.myfaces.extensions.cdi</groupId>
    <artifactId>myfaces-extcdi-dist-jsf20</artifactId>
    <version>0.9.5</version>
    <scope>compile</scope>
</dependency>

2 - ou você pode baixar o jar manualmente aqui:
http://mvnrepository.com/artifact/org.apache.myfaces.extensions.cdi/myfaces-extcdi-dist-jsf20/0.9.5
 
Segue a documentação: https://cwiki.apache.org/confluence/display/EXTCDI/JSF+Usage


Espero que ajude.

Att,

--

Rafael Mauricio Pestano

Graduando em Ciência da Computação
UFRGS


De: Fernando Oliveira <nandooli...@gmail.com>
Para: jav...@googlegroups.com
Enviadas: Quarta-feira, 31 de Agosto de 2011 15:11
Assunto: Re: [javasf] Re: DataTable Primefaces com paginação e muitos registros

Fernando Oliveira

unread,
Aug 31, 2011, 2:30:01 PM8/31/11
to jav...@googlegroups.com
Não faço nenhum divisão no meu  código.. Inclusive fiz alguns testes aqui e o dao estão pegando os valores no banco normalmente (mendei imprimir no terminal). Se você olhar na segunda linha vai ver que a divisão está sendo feita dentro do método setRowIndex da classe org.primefaces.model.LazyDataModel, mas não entendo porque esse erro está ocorrendo. Já tentei até sobrescrever esse método mas o mesmo erro continuou acontencendo.

org.primefaces.model.LazyDataModel.setRowIndex(LazyDataModel.java:62)



atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Matruskan

unread,
Aug 31, 2011, 2:41:49 PM8/31/11
to jav...@googlegroups.com
Você chegou a colocar isso:

        totais.setRowCount(count);
        totais.setPageSize(20);

??



2011/8/31 Fernando Oliveira <nandooli...@gmail.com>

Matruskan

unread,
Aug 31, 2011, 2:42:16 PM8/31/11
to jav...@googlegroups.com
considere: totais=LazyDataModel

2011/8/31 Matruskan <matr...@gmail.com>

Rafael Pestano

unread,
Aug 31, 2011, 2:46:14 PM8/31/11
to jav...@googlegroups.com
@Override
            public List<Cliente> load(int first, int pageSize, String sortField,
                    boolean sortOrder, Map<String, String> filters) {
               
                setPageSize(pageSize);
                List<Cliente> lista = new ArrayList<Cliente>();
                populateList(lista, first, pageSize);
                this.setRowCount(lista.size());//isso talvez ajude               
                return lista;
            }
 
Att,

--

Rafael Mauricio Pestano

Graduando em Ciência da Computação
UFRGS


De: Matruskan <matr...@gmail.com>
Para: jav...@googlegroups.com
Enviadas: Quarta-feira, 31 de Agosto de 2011 15:42

Assunto: Re: [javasf] Re: DataTable Primefaces com paginação e muitos registros

Fernando Oliveira

unread,
Aug 31, 2011, 3:31:59 PM8/31/11
to jav...@googlegroups.com
Rafael,

Se coloco em ViewAccessScoped a exceção deixa de ser lançada, porém minha tabela continua não sendo populada.

Matruskan,

Chamei os métodos setRowCount(count) e setPageSize(), mas o erro continua aparecendo. Não sei se estou chamando eles no local adequado, chamei dentro do método load().



atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Rogério Martins da Silva

unread,
Aug 31, 2011, 3:38:53 PM8/31/11
to jav...@googlegroups.com
o setRowCount vc tem q passar pra ele o valor total de registros da sua busca, acho que ai esta seu erro.
faz o que o @Rafael recomendo acima que deve funcionar.
Atenciosamente: Rogério Martins da Silva
Bacharel em Sistemas de Informação - Universidade Estadual de Goiás
Desenvolvedor Java / C# / PHP
MSN | Talk : rogerioma...@gmail.com
Contato Claro: (64) 8402-2308 
Contato Oi: (64) 8404-8590
Contato Tim: (64) 8122-2608
skype: rogeriomartinsilva

"Eu queria mudar o mundo. Mas não me deram o código fonte"

"Qualquer tolo pode escrever códigos que um computador entenda. Bons programadores escrevem códigos que humanos conseguem entender."

"Grandes espíritos sempre encontraram uma grande resistência das mentes medíocres"

"O sábio nunca diz tudo o que pensa, mas pensa sempre tudo o que diz."  (Aristóteles)

Matruskan

unread,
Aug 31, 2011, 3:47:00 PM8/31/11
to jav...@googlegroups.com
Eu botei no construtor do bean, depois da inicialização do LazyDataModel


2011/8/31 Fernando Oliveira <nandooli...@gmail.com>

Fernando Oliveira

unread,
Aug 31, 2011, 3:45:54 PM8/31/11
to jav...@googlegroups.com
Eu fiz mas continua do mesmo jeito, ele não está populando a tabela. Acredito que o rowCount seja pego sem problemas porque a quantidade é mostrada e o botões para cada página são mostrados. Só os registros que não aparecem.

Para o RowCounts eu sobrescrevi o método getRowCount(), dessa forma ele está verificando direto no banco a quantidade de linhas.


@Override

            public int getRowCount() {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
                Empresa emp = (Empresa) session.getAttribute("emp");
               
                ClienteDAO dao = new ClienteDAO();
               
                return dao.getNumeroDeClientes(emp.getFlag());
            }


No xhtml eu posso chamar da forma abaixo e usar cliente como um objeto Cliente realmente?! Ou seja, o que é retornado para a tabela é o ArrayList<Cliente> que eu defini no DataModel mesmo!?


<p:dataTable id="clientes" var="cliente"
                value="#{tableClientes.lazyModel}"
                rendered="#{emp.tipo eq 'modelCadastro'}"
                paginator="true" rows="20" lazy="true"
                paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" 
                rowsPerPageTemplate="20,40,60"
                style="font-size:12px; font-family:sans-serif;">
<f:facet name="header"> 
                        Clientes Cadastrados no Hotspot
                     </f:facet>

                <p:column sortBy="#{cliente.nome}" filterBy="#{cliente.nome}">
                    <f:facet name="header">
                        <h:outputText value="Nome" />
                    </f:facet>
                    <h:outputText value="#{cliente.nome}" style="text-transform:capitalize;" />
                </p:column>
                <p:column>
                    <f:facet name="header">
                        <h:outputText value="Acessos" />
                    </f:facet>
                    <h:outputText value="#{cliente.acessos}" />
                </p:column>
                <p:column>
                    <f:facet name="header">
                        <h:outputText value="Down" />
                    </f:facet>
                    <h:outputText value="#{cliente.down}"
                        converter="com.aloo.bitconverter" />
                </p:column>
                <p:column>
                    <f:facet name="header">
                        <h:outputText value="Up" />
                    </f:facet>
                    <h:outputText value="#{cliente.up}"
                        converter="com.aloo.bitconverter" />
                </p:column>
                <p:column>
                    <f:facet name="header">
                        <h:outputText value="&Uacute;ltimo Acesso" />
                    </f:facet>
                    <h:outputText value="#{cliente.ultimoAcesso.time}">
                        <f:convertDateTime timeZone="GMT-3" type="both"
                            pattern="dd/MM/yyyy HH:mm:ss" />
                    </h:outputText>
                </p:column>
            </p:dataTable>


atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Matruskan

unread,
Aug 31, 2011, 7:10:45 PM8/31/11
to jav...@googlegroups.com
Putz, Fernando, não estou achando o problema... Mas vou te dar pelo menos algumas dicas:


Eu fiz mas continua do mesmo jeito, ele não está populando a tabela. Acredito que o rowCount seja pego sem problemas porque a quantidade é mostrada e o botões para cada página são mostrados. Só os registros que não aparecem.

Para o RowCounts eu sobrescrevi o método getRowCount(), dessa forma ele está verificando direto no banco a quantidade de linhas.

@Override
            public int getRowCount() {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
                Empresa emp = (Empresa) session.getAttribute("emp");
               
                ClienteDAO dao = new ClienteDAO();
               
                return dao.getNumeroDeClientes(emp.getFlag());
            }


O "getRowCount" deve ser chamado diversas vezes ao montar a página, então é melhor você fazer o "setRowCount( dao.getNumeroDeClientes() )", assim a busca é realizada apenas uma vez.

Sugiro colocar o setPageSize(), uma vez eu tive um problema porque não tinha colocado isso. Não lembro qual era o problema, mas talvez resolva o seu. (Mas aí você também vai ter que tirar o dropdown e o rowsPerPageTemplate da tabela, acho que não vai custar nada, só para ver se resolve)

 

No xhtml eu posso chamar da forma abaixo e usar cliente como um objeto Cliente realmente?! Ou seja, o que é retornado para a tabela é o ArrayList<Cliente> que eu defini no DataModel mesmo!?
 
Sim, a chamada do cliente na página parece certa, e a tabela recebe o ArrayList<Cliente>.


Para tentar resolver o problema, você pode dar um print ou fazer o debug para ver o tamanho da lista que o método populateLista tá retornando?
Se não me engano, você passa o "ponteiro" da lista para esse método (objetos são passados por referência), aí, dentro do método você faz "lista = alguma outra coisa", então a sua lista antiga não foi alterada. Tente fazer: "lista.addAll(busca no dao);"

Fernando Oliveira

unread,
Sep 1, 2011, 7:44:19 AM9/1/11
to jav...@googlegroups.com
Matruskan,

O problema estava realmente no método populateLista. Como você disse as variáveis de objeto são referências aos objetos ae a lista antiga não estava sendo alterada e por isso a tabela estava vazia.

Obrigado pelas dicas, vou usá-las tbm...

Pessoal,

Obrigado a todos que contribuíram,


atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



--

Fabrício Massula

unread,
Sep 1, 2011, 11:07:06 AM9/1/11
to jav...@googlegroups.com
Muitas dúvidas a respeito do PrimeFaces pode ser tiradas diretamente no manual dele. Muita coisa no Showcase (principalmente o Labs) é meio ambíguo ou incompleto. 

Quando for assim, corra pro manual em PDF: http://www.primefaces.org/documentation.html

Fernando Oliveira

unread,
Sep 1, 2011, 12:42:09 PM9/1/11
to jav...@googlegroups.com
Fabrício,

Conheço o manual e o showcase, e os consultei antes de perguntar. Também procurei na internet, mas infelizmente não consegui resolver o problema por isso recorri ao grupo.

De qualquer forma obrigado pela dica e desculpa se levantei uma questão que não deveria ter postado. Prometo que vou me policiar mais da próxima vez.

atc,


Fernando Oliveira
Desenvolvedor Java / PHP
(82) 8841-7959 / 9927-4021     



Fabrício Massula

unread,
Sep 1, 2011, 1:55:03 PM9/1/11
to jav...@googlegroups.com
Fernando,

Me desculpe se me expressei mal, nem estava falando para você diretamente.
Acho que toda dúvida tem que postar aqui mesmo, bom que ajuda todo mundo na solução e refresca a memória.

Abração
Reply all
Reply to author
Forward
0 new messages