Como recuperar listagens sob demanda no Java EE 7

Imagine que você precisa criar uma aplicação que recupera um grande volume de dados e o exibe no formato de listagens. Para implementar esse requisito, temos duas abordagens: a primeira, considerada por muitos uma má prática, consiste em carregar todos os registros cadastrados no SGBD ao mesmo tempo e colocá-los em memória; já a segunda, bastante recomendada para listagens extensas, é aquela na qual recuperamos do banco de dados apenas os registros que estão sendo visualizados pelo usuário, ou seja, trazemos as informações sob demanda. De forma intuitiva, sabemos que a segunda solução traz alguns benefícios para qualquer aplicação. Para demonstrar isso, criaremos um pequeno sistema Java explorando inicialmente a listagem em memória de uma grande quantidade de clientes cadastrados no SGBD. Em seguida, mostraremos como implementar a mesma operação utilizando a recuperação por demanda, para podermos comprovar as vantagens da segunda opção através da análise de apontamentos de performance e consumo de recursos.
Autores: Pablo Bruno de Moura Nóbrega e Joel Xavier Rocha

Em geral, as aplicações que desenvolvemos — sejam elas web, desktop ou mobile — necessitam exibir listas de registros em tabelas. Essa é uma situação mais do que comum para a maioria dos programadores. O problema surge quando a quantidade de linhas a ser mostrada é muito grande. Nesses casos, colocar em memória todo o volume de dados retornado do banco pode ser extremamente perigoso, podendo inclusive derrubar a aplicação. Por esse motivo, precisamos tratar com bastante atenção como devemos recuperar o conteúdo a ser exibido para o usuário. Uma boa recomendação é dar uma lida em alguns artigos e discussões na web bem relevantes sobre o assunto. Entre essas postagens, podemos destacar “Avoid the Pains of Pagination” e “The Impact of Paging vs. Scrolling on Reading Online Text Passages” (consulte a seção Links para saber onde encontrá-las).

No que se refere à implementação da solução para o cenário descrito anteriormente, a estratégia comumente adotada para exibir dados em tabelas é a primeira que mencionamos: recuperar de uma única vez o conteúdo da base de dados, adicioná-lo em uma coleção e, a partir dessa coleção, permitir que o usuário possa visualizar os dados em uma tabela através de páginas, tendo cada uma delas uma quantidade predefinida de registros. Essa abordagem é chamada de paginação em memória porque os dados já estão todos disponíveis na RAM ou em disco (se a memória virtual estiver sendo usada), mesmo que só uma parte dos registros esteja sendo mostrada. Fica claro, no entanto, que esse cenário é considerado uma má prática, pois pode consumir amplamente os recursos disponíveis do servidor de aplicação.

Para resolver esse problema, utilizamos o que chamamos de paginação por demanda, que consiste em obter da base de dados apenas o conteúdo visível para o usuário, ou seja, os registros que estão sendo mostrados na página. Assim, reduzimos largamente a quantidade de memória consumida e o processamento envolvido na operação, pois estamos criando um número pequeno de objetos por vez.

Neste artigo, veremos as duas implementações de listagem de dados descritas em funcionamento através de um pequeno sistema que iremos criar envolvendo JSF 2.2, CDI 1.1 para injeção de dependências, EJB 3.2 na camada de negócio, PrimeFaces 5.3 como biblioteca de interface rica, Facelets para utilização de templates (evitando que dupliquemos código em nossas páginas) e Hibernate 5.0 acessando uma base de dados no PostgreSQL. Além disso, o Maven será configurado para gerenciamento das dependências, e nosso servidor de aplicação será o WildFly 10.0.0. Finalizando o conteúdo, analisaremos, através de gráficos e relatórios gerados pelo VisualVM e pelo pacote de ferramentas do desenvolvedor do Google Chrome, a diferença no consumo de recursos e no tempo de processamento entre as soluções.

Iniciando nosso conteúdo teórico, teremos, neste primeiro momento, uma visão geral dos dois principais frameworks envolvidos na solução.

JavaServer Faces 2.2

O JavaServer Faces (ou simplesmente JSF) é um framework orientado a eventos lançado em 2004 que adota o padrão MVC (Model-View-Controller) e atualmente se encontra na versão 2.2. É utilizado para a construção da interface com o usuário e, graças aos seus componentes de tela e controllers de utilização muito simples (chamados de Managed Beans), tem se consolidado como um dos frameworks mais populares entre os desenvolvedores Java. Também contribuem para essa aceitação o fato de ser um produto oficial Java EE e de apresentar um grande envolvimento de usuários na especificação da JSR.

Na versão 2.2 algumas inovações foram lançadas, como:

  • Adição de suporte ao escopo FlowScoped;
  • Maior integração com o CDI;
  • Melhoria no suporte a HTML5;
  • Proteção contra ataques do tipo CSRF (Cross-Site Request Forgery).

PrimeFaces 5.3

O PrimeFaces é uma biblioteca de código aberto que possui diversos componentes adicionais aos já existentes no JSF. Foi lançado em 2008 por uma empresa turca especializada em desenvolvimento ágil, treinamento e consultoria Java EE chamada PrimeTek. O framework conta com uma comunidade bastante ativa e possui uma página de demonstração muito superior às dos concorrentes.

Embora a versão gratuita da biblioteca seja a mais popular, existem ainda dois planos de suporte diferenciados: o PrimeFaces Elite e o PrimeFaces Pro, que oferecem, entre outras coisas, releases com melhorias e correções mais constantes que a versão comunitária, acesso a temas exclusivos e um plano aperfeiçoado de correção de bugs.

Na versão 5.3 as seguintes novidades estão disponíveis:

  • Mais de 100 correções feitas;
  • Lançamento do componente Signature, que permite assinar documentos em uma tela touchscreen;
  • Componentes Captcha e Carousel reescritos;
  • Design responsivo aprimorado;
  • Componentes de arrastar e soltar agora compatíveis com dispositivos móveis;
  • Acessibilidade aperfeiçoada.

Criando a aplicação

Como dito anteriormente, faremos uma pequena aplicação para exibir clientes cadastrados em um banco de dados. Nosso objetivo é implementar as duas formas de paginação que comentamos anteriormente (em memória e sob demanda) e comparar os resultados. Para criar o sistema, precisaremos dos seguintes softwares instalados:

  • Servidor de aplicação WildFly 10.0.0 Final;
  • Eclipse Mars para desenvolvedores Java EE;
  • Java Development Kit 1.7;
  • SGBD PostgreSQL 9.5.

Após ter configurado todos os softwares necessários, vamos primeiro criar o projeto Maven. Para isso, abra o Eclipse e clique no menu File > New > Maven Project. Na janela que surgir, marque a opção Create a simple project (skip archetype selection) e clique em Next. Na próxima tela, insira no campo Group Id o valor br.com.javamagazine, no Artifact Id o valor paginacaojm, no Packaging o valor war e no Name o valor paginacaojm. Em seguida, confirme no botão Finish. Observe que após esses passos, o Maven criará um projeto que possui uma estrutura semelhante à mostrada na Tabela 1.

Diretórios do projeto

Conteúdo

src/main/

java/

Classes Java.

resources/

Arquivos de propriedades.

webapp/

Conteúdo relacionado à parte web do projeto (páginas, arquivos XML de configuração, etc.).

src/test/

java/

Classes de testes unitários. No nosso sistema, não terá conteúdo.

resources/

Arquivos de propriedades utilizados pelos testes. No nosso sistema, não terá conteúdo.

target/

Arquivos construídos pelo Maven.

pom.xml

Arquivo POM do Maven.

Tabela 1. Estrutura do projeto criado.

Modificando o pom.xml e gerando o web.xml

Para fazer com que nos ...

Quer ler esse conteúdo completo? Tenha acesso completo