Desenvolvimento - Java
Gerenciando Coleções com Primefaces
Este é mais um artigo que submeto ao Linha de Código, dando sequência a uma série de material, resultado obtido através de pesquisas e laboratórios com meus alunos da UTFPR...
por Everton Coimbra de AraújoEste é mais um artigo que submeto ao Linha de Código, dando sequência a uma série de material, resultado obtido através de pesquisas e laboratórios com meus alunos da UTFPR, campus Medianeira. Reforço o empenho e dedicação destes alunos, que foi extremamente comprometido com a pesquisa e aprendizado durante os meses que mantivemos contato próximo nas disciplinas que a eles eu ministrava. Isso me motivou muito e fazer com que o resultado dos trabalhos deles aparecesse para o mundo e, nada melhor do que o Linha de Código para isso.
Neste artigo apresento o Fernando César S. Brito, que pode ser contactado pelo email fercesarb2@ig.com.br. O Fernando foi meu aluno durante sua graduação e agora na especialização. Me auxiliou na revisão técnica de meu livro de Algoritmos pela Visual Books. Tem uma grande experiência no desenvolvimento de aplicativos Delphi e Java com Banco Oracle, principalmente aplicações voltadas para o agronegócio. Já atuou como professor de desenvolvimento de sistemas e algoritmos e na orientação ao desenvolvimento de projetos acadêmicos para alunos de cursos da área da computação.Desta forma, estejam a vontade em solicitar o curriculum dele. |
Este tutorial apresenta a implementação de uma aplicação bastante simples de carrinho de compras fazendo uso de um recurso que nos permite manipular coleções de maneira bastante simples e eficiente, o collector. Poderemos compreender o quão rápido é adicionar e remover objetos de collections sem ter que escrever códigos adicionais para isso em nossos managed beans.
Introdução
Quando desenvolvemos as aplicações, seja ela web ou não, a chance de utilizarmos coleções (collections) é muito grande. Uma lista de produtos ou pessoas é um exemplo disso, e com o collector (que faz parte da suíte de componentes do primefaces), gerenciar essas listas torna-se bastante simples, já que ele nos permite fazer isso sem ter que escrever códigos Java em nossos backing beans.
Para o exemplo de aplicação demonstrada neste material foi utilizado a IDE Eclipse Helios JEE para a implementação e o Glassfish V3 Prelude para receber a publicação do projeto. Os outros recursos utilizados foram:
Recurso |
URL |
Java Server Faces 2.0 |
|
Primefaces 2.1 |
Conhecimentos necessários
Para a aplicação do apresentado neste material os conhecimentos abaixo se fazem necessários para um melhor aproveitamento do conteúdo:
Uso do Glassfish;
Configuração do WTP;
Criação de projetos Web Dinâmicos;
Criação e configuração de um Server Runtime através do Eclipse;
Criação e manutenção de User Libraries no Eclipse;
Uso e configuração do Primefaces em aplicações web;
Conhecer e saber como criar e configurar um Managed/Backing Bean;
Criando um projeto JSF
Vamos começar a criar o projeto web. Criá-lo com o JSF e WTP (Web Tools Platform) habiltados, através do Eclipse, é bastante simples. Clique no menu em File→New→Other→Web→Dynamic Web Project, pressione Next e será exibida a janela representada pela Figura 1.
Figura 1 – Criando um projeto web |
1. Na janela exibida e representada pela Figura 1 informe o nome para seu projeto no campo Project Name.
2. Selecione o Runtime do servidor web onde o deploy será realizado. Caso não apareça um Runtime, é preciso adicionar e configurar um. O Runtime representa uma configuração para um servidor web específico, onde, normalmente sua aplicação será publicada. No nosso exemplo é o Glassfish.
3. Selecione a configuração para o projeto JSF. Para nosso exemplo, como selecionamos o Glassfish como Server podemos escolher o JSF 2.0.
4. Clique no botão Next e uma janela de acordo à exibida pela Figura 2 será exibida.
Figura 2 – Configurando a estrutura de pastas |
A Figura 2 permite a criação das pastas que seu projeto possa necessitar. Para continuar, clique em Next e configure os dados web do projeto, conforme a Figura 3.
Figura 3 - Configurando os dados web |
Configurando o Primefaces
Quando escolhemos o Glassfish como Server, e selecionamos o JSF 2.0, a configuração inicial dos arquivos web.xml e faces-config.xml é realizado automaticamente. Para o exemplo deste material vamos alterar o arquivo web.xml para que aceite também qualquer arquivo com extensão .jsf, em seu contexto. Conforme a Figura 4:
Figura 4 - Configurando o web.xml |
Além do arquivo web.xml é necessário adicionar o .jar do primefaces na pasta lib da WEB-INF. Para isso basta copiar o arquivo e colar diretamente sobre a pasta lib. Conforme a Figura 5:
Figura 5 - Adicionando a biblioteca do primefaces 2.1 |
Contextualizando
Para facilitar o entendimento e aumentar o aprendizado, é necessário tornar claro qual o objetivo deste pequeno projeto. Podemos começar informando que é totalmente para fins didáticos e que as práticas realizadas nele podem não ser as mais adequadas a algum ambiente profissional de desenvolvimento.
No que se refere à implementação, vamos trabalhar com um carrinho de compras, que terá a disposição uma lista de produtos para serem adquiridos, e esse carrinho poderá remover os produtos comprados. O interessante é que podemos fazer isso usando o collector sem nos preocupar com índices, tamanho de coleção, duplicidade de objetos e até mesmo com o “tipo da coleção”. Podemos usar um ArrayList ou um Vector, por exemplo.
Disponibilizando os produtos ao carrinho
Os produtos disponíveis ao carrinho de compras são fornecidos por uma classe de controle ProdutoController, que possui uma coleção de produtos estática. Claro que essa lista de produtos poderia ser obtida dinamicamente através de consulta a alguma tabela no banco de dados, mas como o objetivo deste material é exemplificar o uso do componente collector não faremos isso. Resumindo, teremos duas classes, a Produto que é a nossa POJO e a ProdutoController.
Classe Produto
A classe Produto não requer maior explicação, porque possui apenas alguns atributos, seus métodos set e get e o override do equals e hashcode. Para criá-la, clique com o botão direito sobre a pasta src, e em New→Class, e forneça o nome do pacote em Package e da classe em Name, como demonstra a Figura 6.
Figura 6 - Criando a classe Produto |
Em seguida clique em Finish e escreva o código da Figura 7.
Figura 7 - Código da classe Produto |
Classe ProdutoController:
A classe ProdutoController possui a lista de produtos disponíveis ao carrinho de compras. Esta lista é populada no construtor da classe. Para criá-la, clique com o botão direito sobre a pasta src, e em New→Class, e forneça o nome do pacote em Package e da classe em Name, como demonstra a figura 8.
Figura 8 - Criando a classe ProdutoController |
Em seguida clique em Finish e escreva o código da Figura 9.
Figura 9 - Código da classe ProdutoController |
Adicionando os produtos ao carrinho
Os produtos disponibilizados pelo ProdutoController são adicionados ao carrinho de compras referenciado na classe CarrinhoController. Ela possui além da referência ao Carrinho a referência ao Produto que é utilizado pelo componente collector. Resumindo, teremos duas classes, a Carrinho que é a nossa pojo e a CarrinhoController.
Classe Carrinho:
A classe Carrinho é que representa o carrinho de compras e possui apenas uma lista de produtos com seus respectivos métodos. Para criá-la, clique com o botão direito sobre a pasta src, e em New→Class, e forneça o nome do pacote em Package e da classe em Name, como demonstra a Figura 10.
Figura 10 - Criando a classe Carrinho |
Em seguida clique em Finish e escreva o código da Figura 11.
Figura 11 - Código da classe Carrinho |
Classe CarrinhoController:
A classe CarrinhoController possui a referencia a um Produto e a um Carrinho de compras. É esta classe que será utilizada em nosso arquivo .jsf pelo componente collector. Para criá-la, clique com o botão direito sobre a pasta src, e em New→Class, e forneça o nome do pacote em Package e da classe em Name, como demonstra a Figura 12.
Figura 12 - Criando a classe CarrinhoController |
Em seguida clique em Finish e escreva o código da Figura 13.
Figura 13 - Código da classe CarrinhoController |
Configurando o arquivo faces-config
O JSF 2.0 introduz anotações como uma alternativa ao arquivo de configurações Faces padrão (faces-config.xml) para configurar seu aplicativo. Portanto, ao adicionar o suporte JSF 2.0 a um projeto, não é obrigatório o uso do arquivo faces-config.xml (como acontecia no JSF 1.2), mas podemos adicioná-lo ao projeto a fim de definir configurações específicas. Em nosso exemplo vamos adicionar à ele os managed beans que nossa página irá utilizar. Para isso, edite o arquivo e adicione o código demonstrado na Figura 14.
Figura 14 - Adicionando managed beans ao faces-config.xml |
Linha 9 e 14: Damos o nome ao managed bean da mesma forma que referenciamos na página.
Linha10 e 15: Damos o nome da classe do managed bean.
Linha11 e 16: Definimos o escopo, no nosso exemplo será de session.
Desse modo poderemos usar os managed beans diretamente na página, como se tivéssemos uma instância nela mesma.
E se utilizássemos anotações? Seu uso dispensa a criação do faces-config.xml (como já informamos) com o JSF 2.0 e bastaria apenas adicionar diretamente nos managed beans as anotações necessárias. Desta forma, as classes CarrinhoController e ProdutoController seriam anotadas assim:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean(name="carrinhoController")
@SessionScoped
public class CarrinhoController {/*foram ocultados atributos e metodos*/}
@ManagedBean(name="produtoController")
@SessionScoped
public class ProdutoController {/*foram ocultados atributos e metodos*/}
Criando a página do JSF
Vamos criar uma página que chamaremos de carrinho.xhtml. Essa página irá possuir uma lista de produtos disponibilizados pelo produtoController um botão que terá a tarefa de atualizar o carrinho de compras, e outra lista que exibirá os itens do carrinho de compras. É importante lembrar que esse arquivo deve estar na pasta WebContent.
Linha 3 a 6: Fazemos uso da taglibs para utilizar os componentes na página, como o collector.
Figura 15 - Criando a lista de produtos disponíveis |
Linha 15: Fazemos uso da dataTable que recebe do produtoController (que configuramos no faces-config.xml) a lista de produtos. Temos também o atributo var onde definimos que cada linha da tabela é referenciada pelo valor desse atributo, no nosso exemplo, cada linha é representada por “produto”.
Linha 17 a 28: Definimos as colunas da tabela. O atributo value recebe o valor diretamente da var produto.
Linha 31 e 32: Fazemos uso do commandLink e em seu actionListener o método “novoProduto” do carrinhoController (que configuramos no faces-config.xml) é acionado para criar um novo produto.
Linha 33 e 34: Utilizamos o collector. Em addTo definimos qual será a coleção controlada que receberá os novos produtos, que no nosso exemplo é a lista de produtos do carrinho de compras, e em value definimos qual o produto que será adicionado na coleção.
Figura 16 - Criando o panel com o botão que atualiza produtos no carrinho |
Linha 41 a 43: Criamos um commandButton e em seu atributo update atribuímos o nome do dataTable “carrinho” (conforme mostra a figura 17) que possui a lista de produtos do carrinho de compras.
Figura 17 - Criando a lista de produtos do carrinho de compras |
Linha 47: Fazemos uso da dataTable que recebe do carrinhoController (que configuramos no faces-config.xml) a lista de produtos do carrinho de compras. Temos também o atributo var onde definimos que cada linha da tabela é referenciada pelo valor desse atributo, no nosso exemplo, cada linha é representada por “produtoCarrinho”.
Linha 51 a 62: Definimos as colunas da tabela. O atributo value recebe o valor diretamente da var produtoCarrinho.
Linha 66 e 67: Utilizamos o collector. Em removeFrom definimos qual será a coleção controlada que terá objetos removidos de sua lista, que no nosso exemplo é a lista de produtos do carrinho de compras, e em value definimos qual o produto que será removido da coleção.
Estrutura do projeto
Podemos observar na Figura 18 a estrutura do projeto, onde em src estão nossos pojos Produto e Carrinho e nossos controllers ProdutoController e CarrinhoControler.
Além disso, na pasta WebContent temos a biblioteca do primefaces 2.1 na pasta WEB-INF→lib e os arquivos web.xml e faces-config.xml em WEB-INF.
Figura 18 - Estrutura pastas e arquivos do projeto |
Executando a aplicação
O resultado da página sendo executado no browser pode ser observado na Figura 19. Não faz parte deste material, demonstrar como realizar o deploy no Glassfish.
Figura 19 - Página criada executada no browser |
Ao clicar em adicionar ao carrinho o produto disponibilizado é adicionado através do collector (atributo addTo) à lista de produtos do carrinho de compras, ao clicar no botão verificar carrinho de compras, a lista do carrinho de compras é atualizada, exibindo então os produtos adicionados, e ao clicar em remover do carrinho o item selecionado é excluído da lista de compras do carrinho através do collector (atributo removeFrom).
Componente Collector
Como foi dito no inicio deste material o componente collector permite que coleções sejam utilizadas sem precisar escrever códigos Java para realizar os controles, como adicionar e remover, por exemplo. Ele não é um componente visual, ou seja, adicionar sua declaração <p:collector/> não causará mudança no visual de sua página.
O collector possui apenas três atributos:
value: é do tipo Object e representa o valor a ser usado nas operações da coleção.
addTo: é do tipo Collection e representa uma instância deste tipo.
removeFrom: é do tipo Collection e representa uma instância deste tipo.
De maneira resumida, para o collector trabalhar é necessário apenas uma coleção e um objeto qualquer. É importante que o objeto ligado ao atributo value sobrescreva os métodos equals e hashcode
Conclusões
Poder construir aplicações web verdadeiramente ricas com o uso do primefaces é perfeitamente possível. Quando podemos utilizar componentes que encapsulam funcionalidades que antes deviam ser criadas pelo desenvolvedor a curva de aprendizado é menor e a produtividade é aumentada, além de tornar o trabalho de codificação muito mais simples, como o componente collector demonstrado nesse material. Fica então a sugestão, para que verifiquem e utilizem os outros componentes do primefaces, para que possam usufruir do potencial que eles podem proporcionar.