Criando Um Sistema de Leilão de Veículos Em Java

download Criando Um Sistema de Leilão de Veículos Em Java

of 90

description

Iniciando as atividades com JSF

Transcript of Criando Um Sistema de Leilão de Veículos Em Java

Criando um sistema de leilo de veculos em Java Parte 1Veja quais so as novidades do PrimeFaces 5 e aprenda a desenvolver um sistema de leilo de veculos em Java com o framework Primefaces.Fique por dentroA plataforma Java EE 7 tem obtido grande sucesso entre os desenvolvedores. Por este motivo, aprender a utilizar os recursos fornecidos por diversos frameworks derivados das especificaes desta extremamente aconselhado para quem deseja trabalhar com aplicaes web. Neste artigo veremos quatro dos frameworks que compem essa plataforma (JPA 2.1, CDI 1.1, JSF 2.2 e EJB 3.2) e os combinaremos com o recm-lanado PrimeFaces 5 para a elaborao de telas com componentes modernos e visualmente agradveis durante a implementao de um pequeno sistema de leilo de veculos.Atualmente, se uma equipe de desenvolvimento de sistemas receber a misso de implementar uma nova aplicao web em Java, existe uma grande possibilidade do responsvel pela definio da arquitetura optar pelo JSF como o framework MVC do projeto. claro que a deciso levar em conta vrios fatores, mas se esta for realmente a escolha, certamente a preferncia ser motivada por questes como a popularidade da biblioteca e o fato de ela pertencer especificao Java EE.A deciso pelo JavaServer Faces, entretanto, no a nica a ser tomada antes de iniciar a implementao. No que diz respeito elaborao da camada de viso, provvel que alguma biblioteca de interface rica como RichFaces, ICEfaces ou PrimeFaces tambm seja adicionada ao projeto. Esta constatao existe por conta de algumas limitaes do JSF, como: Os componentes visuais nativos so poucos e muito rsticos; No existe suporte embarcado no framework ao uso de temas/skins; Modelo nativo de requisies AJAX simples, sem suporte, por exemplo, a mecanismos depush.Neste contexto, frameworks RIA, como os comentados anteriormente, surgiram logo aps o lanamento das verses iniciais do JSF e trouxeram algumas vantagens, como uma experincia visual mais agradvel para o usurio, a possibilidade de executar processamento assncrono, diminuio no trfego de rede uma vez que a client enginepode efetuar processamento no lado do cliente , reduo da complexidade da aplicao, entre outras.Para conhecermos de forma mais aprofundada um destes frameworks, este artigo explorar o PrimeFaces 5, lanado recentemente pela PrimeTek e que tem se firmado como a biblioteca RIA para JSF mais popular do mercado. Como veremos, novos componentes foram lanados nesta verso, alm de vrias melhorias terem sido implementadas emtagsj existentes. A mais significativa delas talvez tenha sido a remodelagem do PrimeFaces Push, que agora est baseado no Atmosphere, considerado o framework para desenvolvimento assncrono mais popular do Java. Entre as vantagens da nova implementao do Push esto o desenvolvimento dos sistemas baseado no uso de anotaes, suporte a WebSockets e at mesmo integrao com servios em nuvem.Dito isso, nesta primeira parte do artigo iremos conhecer os principais recursos do PrimeFaces atravs do incio do desenvolvimento de um pequeno sistema de venda de veculos na modalidade leilo, no qual o usurio pode tambm dar sua opinio sobre os modelos de carros cadastrados.

O PrimeFaces 5Em 2008, a PrimeTek, empresa de origem turca, especializada em desenvolvimento gil, treinamento e consultoria Java EE, lanou no mercado uma biblioteca de componentes RIA chamada PrimeFaces. O framework foi criado pelo consultor aatay ivici, autor/revisor de vrios livros envolvendo desenvolvimento Java Web e JSF, e membro do JavaServer Faces Expert Group e do projeto Apache MyFaces. Contando com uma comunidade bastante ativa, o projeto possui cdigo aberto e uma pgina de demonstrao de dar inveja aos concorrentes.Embora a maior parte dos desenvolvedores utilize a verso gratuita da biblioteca, existem ainda dois planos de suporte diferenciados: PrimeFaces Elite:oferecereleasescom melhorias e correes mais constantes que a verso gratuita, acesso a temas exclusivos e um plano aperfeioado de correo de bugs que garante a incluso dopatchno prximoreleasese o defeito atingir mais de 15 votos de usurios na ferramenta de acompanhamento de ocorrncias da biblioteca; PrimeFaces Pro:traz as mesmas vantagens da verso Elite, alm de acesso a uma rea com contedo exclusivo (http://pro.primefaces.org), resposta a dvidas ou bugs em no mximo 24 horas, participao em conferncias de discusso, conexo remota mquina do desenvolvedor, entre outras.Na verso 5.0, lanada recentemente, o framework apresentou algumas novidades, a saber: O PrimeFaces Mobile foi reimplementado do zero e incorporado aocoreda biblioteca. Esta melhoria evita que o desenvolvedor precise implementar duas interfaces diferentes (uma para desktope outra para dispositivos mveis) no mesmo sistema; Novos componentes lanados: DataScroller: utilizado para recuperao de objetos sob demanda; Cache:reduz o tempo de carregamento de uma pgina; Spotlight: demarca uma rea da pgina para receber um efeito de iluminao; ColumnToggler: permite ocultar colunas de um DataTable via AJAX; ContentFlow: exibe uma galeria horizontal de imagens utilizando o efeito de apresentao deslides; Nova API para gerao de grficos; Um poderosoExceptionHandlerfoi disponibilizado.No que diz respeito a componentes j existentes, tambm houve melhorias. Algumas delas so: O componentepushfoi remodelado baseado no framework Atmosphere; O mtodo de execuo de JavaScript no carregamento da pgina est mais simples; Colunas e linhas podem agora ser reorganizadas no DataTable atravs de aes de arrastar e soltar; Implementado um filtro avanado paraDataTable; Um mtodo de ordenao paraTreeTablefoi disponibilizado; Implementado um filtro nos componentes SelectManyMenu eSelectOneListbox; Implementada uma mscara para o componenteCalendar.

Criando a aplicaoComo exemplo, criaremos um pequeno sistema de venda de veculos para demonstrar os principais componentes e recursos do PrimeFaces 5. Alm do framework RIA, a arquitetura do nosso sistema ter ainda a injeo de dependncias feita pelo CDI 1.1, o acesso ao banco se dar atravs da JPA 2.1, a camada de negcio envolver EJB 3.2, o papel decontrollercaber ao JSF 2.2, e o Facelets ser utilizado para gerao detemplatesna aplicao, evitando que dupliquemos cdigo em nossas pginas.O ambiente requerido para criar o sistema envolver os softwares listados a seguir, que precisam estar instalados na mquina em que a implementao dos exemplos deste artigo ser feita (se necessrio, confira a seoLinksno final do artigo para saber onde baix-los): Servidor de aplicao WildFly 8.0.0. Caso queira saber mais detalhes sobre como configur-lo, consulte a Java Magazine 128; Eclipse Kepler para desenvolvedores Java EE; Java Development Kit verso 1.7 configurado no Eclipse; SGBD PostgreSQL 9.3.Aps estarmos com todos os softwares configurados na mquina, vamos criar o projeto Maven. Para isso, naviewProject Explorerdo Eclipse, clique com o boto direito, selecioneNewe clique emOther.Na tela que surge, selecioneMavene depois clique emMaven Project. Marque a opoCreate a simple Project (skip archetype selection)e clique emNext. Neste passo, informe no campoGroup Ido valor br.com.javamagazine, noArtifact Ido valor leilaojm, no Packagingo valor war e noNameo valor leilaojm. Em seguida, clique emFinish.Logo aps, vamos configurar nosso projeto para utilizar o JSF 2.2 e informar alguns parmetros adicionais para a aplicao rodar corretamente. Assim, clique com o boto direito em cima da raiz do projeto, e depois na opoProperties. Na tela que surge, clique emProject Facets. No itemDynamic Web Module, selecione a verso 3.1 para trabalharmos com a verso mais recente da API de Servlets. No itemJava, selecione a opo 1.7 e marque o item abaixo, JavaServer Faces, selecionando posteriormente a verso 2.2 do framework. Mais abaixo, surgir a mensagemFurther configuration availableinformando que preciso confirmar alguns parmetros do JSF. Clique nela e informe as seguintes configuraes para o funcionamento da aplicao: emJSF Implementation Library, deixe marcadoDisable Library Configuration; no campoURL Mapping Patterns, clique em cima da opo existente (/faces/*) e depois no botoRemove. Feito isso, clique no botoAdde nopopupque aparece, informe *.xhtml. Ento, clique emOKna primeira tela, emOKna segunda e novamente emOKna terceira para confirmar as mudanas.Embora tenhamos informado o uso da verso 3.1 da API de Servlets no itemProject Facets, precisamos configurar este parmetro noweb.xml. Aproveitaremos a edio do arquivo para determinar qual a pgina inicial do sistema. Para realizar estas alteraes, abra o XML mencionado, que se encontra na pasta src/main/webapp/WEB-INF, e informe o cdigo presente naListagem 1.Listagem 1. Cdigo do arquivo web.xml.

leilaojm index.xhtml Faces Servlet javax.faces.webapp.FacesServlet 1

Faces Servlet *.xhtml

Modificando o pom.xmlChegamos ao ponto em que necessrio configurar as bibliotecas utilizadas pelo projeto no arquivopom.xml. Deste modo, abra o XML e selecione a abapom.xmlpara editar o cdigo fonte, que deve ficar semelhante ao daListagem 2.Listagem 2. Cdigo do arquivo pom.xml.

4.0.0 br.com.javamagazine leilaojm 0.0.1-SNAPSHOT war leilaojm maven-compiler-plugin 2.0.2 1.7 1.7 javax javaee-api 7.0 provided org.primefaces primefaces 5.0 org.apache.myfaces.tomahawk tomahawk21 1.1.14

As principais configuraes apresentadas so as seguintes: Especificaes gerais do projeto informadas no incio do artigo ao criarmos a aplicao. OgroupIdidentifica o grupo de projetos de uma organizao e normalmente obedece estrutura de pacotes do sistema. J oartifactId o nome utilizado para gerar o WAR; Nome do projeto; Configurao da verso 1.7 para opluginde compilao do cdigo fonte do sistema. Desta forma, informamos ao Eclipse que o JDK 1.7 ser usado e que ele deve constar noclasspathda aplicao; Definicao de todas as dependncias utilizadas no projeto; Informa que as bibliotecas da Java EE 7 usadas no projeto j esto noclasspath. No nosso caso, so fornecidas pelo WildFly; Informa a dependncia do PrimeFaces 5.0; Informa a dependncia do Apache Tomahawk para JSF 2.1 (tambm funciona com JSF 2.2). A biblioteca ser utilizada para salvar o estado de objetos com escopo de requisio entre pginas, uma vez que no utilizaremos escopo de conversao nestes casos.Aps modificar opom.xml, vamos atualizar as dependncias do Maven no sistema. Para realizar esse procedimento, clique com o boto direito em cima da raiz do projeto, selecioneMavene clique emUpdate Project. Na tela que surge, clique emOKe aguarde alguns segundos para que o Eclipse realize o processo.

Configurando o banco de dados e o datasourceCom o PostgreSQL rodando, crie uma base de dados chamada leilaojme rode oscriptdaListagem 3para gerar as tabelas e colocar algumas informaes nelas com o objetivo de j termos como realizar algumas operaes no sistema sem que precisemos cadastrar dados (as linhas com osinsertsforam omitidas e podem ser encontradas no arquivo completo que est na pastasrc/main/resourcesdo cdigo-fonte que voc pode baixar).Listagem 3. Script de criao do banco de dados. CREATE SEQUENCE anuncio_id_seq INCREMENT BY 1;CREATE SEQUENCE avaliacao_id_seq INCREMENT BY 1;CREATE SEQUENCE imagem_anuncio_id_seq INCREMENT BY 1;CREATE SEQUENCE modelo_id_seq INCREMENT BY 1;

CREATE TABLE "anuncio"( id INTEGER DEFAULT nextval('anuncio_id_seq') NOT NULL, id_modelo INTEGER NOT NULL, titulo VARCHAR(200) NULL, descricao TEXT NOT NULL, anomodelo INTEGER NOT NULL, anofabricacao INTEGER NOT NULL, uf CHAR(2) NULL, cidade VARCHAR(60) NULL, precofixo BOOL NOT NULL, valor DOUBLE PRECISION NULL, valorlanceatual DOUBLE PRECISION NULL, vendido BOOL NOT NULL, PRIMARY KEY (id));

CREATE TABLE "avaliacao"( id INTEGER DEFAULT nextval('avaliacao_id_seq') NOT NULL, id_modelo INTEGER NOT NULL, nome VARCHAR(100) NOT NULL, texto TEXT NOT NULL, PRIMARY KEY (id));

CREATE TABLE "imagem_anuncio"( id INTEGER DEFAULT nextval('imagem_anuncio_id_seq') NOT NULL, id_anuncio INTEGER NOT NULL, nome VARCHAR(45) NOT NULL, PRIMARY KEY (id)); CREATE TABLE "marca"( id INTEGER NOT NULL, nome VARCHAR(45) NOT NULL, imagem VARCHAR(20) NULL, PRIMARY KEY (id));

CREATE TABLE "modelo"( id INTEGER DEFAULT nextval('modelo_id_seq') NOT NULL, id_marca INTEGER NOT NULL, nome VARCHAR(30) NOT NULL, motorizacao VARCHAR(20) NULL, datalancamento DATE NULL, qtdpassageiros INTEGER NULL, linkvideo VARCHAR(120) NULL, PRIMARY KEY (id));

ALTER TABLE "anuncio" ADD CONSTRAINT anuncio_modelo_fk FOREIGN KEY (id_modelo) REFERENCES "modelo" (id);

ALTER TABLE "avaliacao" ADD CONSTRAINT avaliacao_modelo_fk FOREIGN KEY (id_modelo) REFERENCES "modelo" (id);

ALTER TABLE "imagem_anuncio" ADD CONSTRAINT imagem_anuncio_anuncio_fk FOREIGN KEY (id_anuncio) REFERENCES "anuncio" (id);

ALTER TABLE "modelo" ADD CONSTRAINT modelo_marca_fk FOREIGN KEY (id_marca) REFERENCES "marca" (id);

// inserts omitidos. Baixe o cdigo-fonte do projeto e pegue o script completo na pasta src/main/resources.Aps a criao das tabelas, o diagrama relacional da nossa base de dados ficar como o mostrado pelaFigura 1.

Figura 1. Diagrama relacional da base de dados.Podemos agora definir odatasourceno WildFly. No entanto, antes disso precisamos baixar odriverdo PostgreSQL (confira a seoLinkspara saber onde realizar o download) e configur-lo como um mdulo do servidor de aplicao. Depois de obter o JAR, crie a estrutura de diretriosorg/postgresql/maindentro de/modulese cole o arquivo JAR dodriverdentro da pastamain. Nessa mesma pasta, gere um arquivo chamadomodule.xmlcom o contedo o contedo daListagem 4.Listagem 4.Configurao do arquivo module.xml.

Pronto, nosso mdulo est configurado. Agora vamos fazer com que o WildFly reconhea o driver do SGBD. Assim, abra o arquivo standalone.xml localizado em /standalone/configuratione natag, que est dentro de,defina um novo item inserindo as linhas a seguir:

org.postgresql.xa.PGXADataSource

Finalizado este passo, falta somente definir um novodatasource, o que feito inserindo as linhas expostas naListagem 5aps a tag.Lembre-se de modificar os dados como usurio e senha pelos definidos na sua instalao do PostgreSQL.Listagem 5.Configurao do novo datasource.

jdbc:postgresql://localhost:5432/leilaojm org.postgresql.Driver org.postgresql postgres 1234

Configurando a JPAPara inserirmos a Java Persistence API em nosso projeto, necessrio primeiramente criarmos o XML de configurao da biblioteca. Deste modo, clique com o boto direito emsrc/main/resources, selecioneNewe ento clique emOther. Na tela que surge, clique emGenerale depois emFolder. No campoFolder nameinforme META-INF e clique emFinish. Agora, clique com o boto direito em cima da pasta criada, selecioneNewe depoisOther. Na tela apresentada, selecioneXML>XML Filee clique emNext. No campoFile nameinforme persistence.xml e clique emFinish. Executados esses passos, modifique o cdigo gerado automaticamente para ficar igual ao daListagem 6.Listagem 6. Cdigo do arquivo persistence.xml.

org.hibernate.ejb.HibernatePersistence java:jboss/datasources/leilaoDS

Observe que na linha 5definimos o nomeleilaoPUpara nossaPersistenceUnite indicamos que o tipo de transao JTA, o que facilitar nossa vida, j que no teremos que ficar manipulando as transaes manualmente. A linha 6determina qual ser a implementao doEntityManager. Como o WildFly usa o Hibernate, optamos pela classeHibernatePersistence. Na linha 7 configuramos o nome dodatasourceque ser referenciado (veja que est igual ao que digitamos no arquivostandalone.xml) e na linha 9 o dialeto a ser usado pelo Hibernate, que ser o do PostgreSQL.

Criando as entidades do projetoComo quase todo sistemawebdesenvolvido em Java, precisaremos de entidades para mapear os atributos das classes com os campos de entrada de dados nas telas. No nosso caso sero cinco: Marca,Modelo,Avaliacao,AnuncioeImagemAnuncio. Para criar a primeira delas (Marca), clique com boto direito em cima do projeto, selecione a opoNewe depois clique emClass. Na tela que surge, informe emPackageo valor br.com.javamagazine.leilaojm.domain, emNameinforme Marca e clique no botoFinish. Um cdigo inicial ser gerado automaticamente e deve ser modificado para ficar semelhante ao daListagem 7(lembre-se de inserir os gets, sets,equals()ehashCode()que foram omitidos).Listagem 7. Cdigo da classe Marca.package br.com.javamagazine.leilaojm.domain;

import java.io.Serializable;import javax.persistence.*;

@Entitypublic class Marca implements Serializable { private static final long serialVersionUID = 3324213972781520099L; @Id private Integer id; private String nome; private String imagem; // gets e sets omitidos // equals() e hashCode() omitidos}Veja que na linha 7 colocamos a anotao@Entitypara indicar que esta classe uma entidade mapeada para uma tabela no banco de dados (por padro, o nome da tabela o mesmo nome da classe, mas com a primeira letra tambm em minsculo).Repetindo o mesmo procedimento anterior para gerao de uma classe, crie a entidadeAvaliacaono pacote informado anteriormente e substitua o cdigo gerado automaticamente pelo Eclipse para ficar igual ao daListagem 8(lembre-se de inserir os gets, sets,equals()ehashCode()).Listagem 8. Cdigo da classe Avaliacao.package br.com.javamagazine.leilaojm.domain;

import java.io.Serializable;import javax.enterprise.context.Dependent;import javax.persistence.*;

@Dependent@Entitypublic class Avaliacao implements Serializable {

private static final long serialVersionUID = 2369525766962287562L;

@Id @GeneratedValue(generator="avaliacao_id_seq", strategy=GenerationType.SEQUENCE) @SequenceGenerator(name="avaliacao_id_seq", sequenceName="avaliacao_id_seq", allocationSize=1) private Integer id; private String nome; private String texto;

@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="id_modelo") private Modelo modelo; // gets e sets omitidos // equals() e hashCode() omitidos}Os principais trechos do cdigo dessa listagem podem ser explicados da seguinte forma: A anotao do CDI@Dependentpermite que a entidadeAvaliacaoseja injetada em outra classe e, como o prprio nome da anotao indica, faz com que a instncia deAvaliacaotenha o mesmo ciclo de vida do objeto no qual est inserida (no nosso caso, oManaged Beancom escopo de requisio que iremos criar posteriormente); Definio da classe como uma entidade JPA; Seta o atributoidcomo chave primria da tabela; Definio que o valor do atributoidser gerado automaticamente atravs de umasequenceno banco; Configura asequenceavaliacao_id_seq, que ser usada pelo atributoid; Define que a classeAvaliacaoter uma relao de muitos para um comModelo(vrias avaliaes para um modelo), expressa pelo atributomodelo, e que a chave estrangeira na tabelaavaliacaoser mapeada pela coluna id_modelo;Nosso prximo passo ser criar a terceira entidade,Modelo, no mesmo pacote das outras duas classes. Aps esse procedimento, substitua o cdigo gerado para ficar igual ao daListagem 9(lembre-se novamente de inserir os gets, sets,equals()ehashCode()).Listagem 9. Cdigo da classe Modelo.package br.com.javamagazine.leilaojm.domain;

import java.io.Serializable;import java.util.*;import javax.enterprise.context.Dependent;import javax.persistence.*;

@Dependent@Entitypublic class Modelo implements Serializable {

private static final long serialVersionUID = -6242474942033150604L;

@Id @GeneratedValue(generator="modelo_id_seq", strategy=GenerationType.SEQUENCE) @SequenceGenerator(name="modelo_id_seq", sequenceName="modelo_id_seq", allocationSize=1) private Integer id; private String nome; private String motorizacao; private Date dataLancamento; private Integer qtdPassageiros = 2; private String linkVideo;

@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name="id_marca") private Marca marca;

@OneToMany(mappedBy="modelo") private List listaAvaliacoes = new ArrayList();

// gets e sets omitidos // equals() e hashCode() omitidos}Os principais trechos do cdigo so os seguintes: Anotao do CDI@Dependentpermite injetarmos a entidade em outra classe; define a classe como uma entidade JPA; configura o atributoidcomo chave primria da tabela modelo; define que o valor do atributoiddeve ser gerado automaticamente, atravs da sequence modelo_id_seq no banco; define que a classeModeloter uma relao de muitos para um comMarca,expressa pelo atributomarca, e que a chave estrangeira na tabelamodeloser mapeada pela colunaid_marca; define que a classeModeloter uma relao de um para muitos comAvaliacao(um modelo com vrias avaliaes), expressa pelo atributolistaAvaliacoes, e que o atributomodelo, na classeAvaliacao, faz o relacionamento inverso (@ManyToOne) entre as duas classes.Nossa prxima classe serAnuncio, que dever ser criada no mesmo pacote das outras trs entidades. Aps o procedimento, substitua o cdigo automaticamente gerado pelo daListagem 10(mais uma vez, implemente os gets, sets,equals()ehashCode()).Listagem 10. Cdigo da classe Anuncio.package br.com.javamagazine.leilaojm.domain;

import java.io.Serializable;import java.util.*;

import javax.enterprise.context.Dependent;import javax.persistence.*;

@Dependent@Entitypublic class Anuncio implements Serializable {

private static final long serialVersionUID = -6530939806537115280L;

@Id @GeneratedValue(generator="anuncio_id_seq", strategy=GenerationType.SEQUENCE) @SequenceGenerator(name="anuncio_id_seq", sequenceName="anuncio_id_seq", allocationSize=1) private Integer id; private String titulo; private String descricao; private Integer anoModelo; private Integer anoFabricacao; private String uf; private String cidade; private Boolean precoFixo = true; private Double valor; private Double valorLanceAtual; private Boolean vendido;

@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name="id_modelo") private Modelo modelo;

@OneToMany(mappedBy="anuncio", fetch=FetchType.EAGER) private List imagensAnuncio = new ArrayList();

// Mtodo de negcio. Retorna lista de imagens como List public List getImagensComoListaDeStrings() { List imagensComoListaString = new ArrayList(); for (ImagemAnuncio img : imagensAnuncio) { imagensComoListaString.add(img.getNome()); } return imagensComoListaString; }

// gets e sets omitidos // equals() e hashCode() omitidos}Os principais trechos do cdigo so os seguintes: A anotao do CDI@Dependentpermite que a entidade seja injetada em outra classe; Define a classe como uma entidade JPA; Configura o atributoidcomo chave primria da tabela anuncio; Define que o valor do atributoiddeve ser gerado automaticamente, atravs da sequence anuncio_id_seq no banco; Define que a classeAnuncioter uma relao de muitos para um comModelo, expressa pelo atributomodelo, e que a chave estrangeira na tabelaanuncioser mapeada pela colunaid_modelo. A instruo fetch=FetchType.EAGER indica que toda vez que um anncio for recuperado do banco de dados, o atributo modelodeve ser preenchido automaticamente pela JPA; Define que a classeAnuncioter uma relao de um para muitos comImagemAnuncio, expressa pelo atributo imagensAnuncio, e que o atributoanuncio, na classe ImagemAnuncio, faz o relacionamento inverso (@ManyToOne) entre as duas classes. A instruo fetch=FetchType.EAGER indica que toda vez que um anncio for recuperado do banco de dados, o atributo imagensAnunciodeve ser preenchido automaticamente pela JPA; Criamos o mtodo getImagensComoListaDeStrings(), que transforma List em uma List. Esse cdigo ser utilizado por um dos componentes do PrimeFaces 5, como veremos na continuao do artigo.Como vimos, a classeAnunciotem uma lista deImagemAnuncio. Esta relao foi criada para que o usurio possa efetuar ouploadde imagens dos produtos venda. Neste ponto, voc deve lembrar que comentamos sobre algunsinsertsque haviam noscriptde criao das tabelas no banco de dados. Entre estesinserts, vrios deles se referiam a nomes de arquivos de imagens que so colocados na tabelaimagem_anuncioquando rodamos oscript. Alm destas imagens, o projeto possui alguns cones utilizados nas pginas internas, como as logomarcas dos fabricantes de veculos. Todas estas figuras esto dentro das pastassrc/webapp/imagense src/webapp/imagens_anuncios do cdigo fonte do projeto. Sugiro extra-las do pacote e coloc-las nas pastas equivalentes da aplicao que estamos criando.Por fim, nossa ltima entidade serImagemAnuncio. Assim como as outras, ela dever ser criada no pacote br.com.javamagazine.leilaojm.domain. Feito isso, substitua o cdigo gerado automaticamente pelo daListagem 11(implemente os gets, sets,equals()ehashCode()).Listagem 11. Cdigo da classe ImagemAnuncio.package br.com.javamagazine.leilaojm.domain;

import java.io.Serializable;import javax.persistence.*;

@Entity@Table(name="imagem_anuncio")public class ImagemAnuncio implements Serializable { private static final long serialVersionUID = 2282621816438840613L;

@Id @GeneratedValue(generator="imagem_anuncio_id_seq", strategy=GenerationType.SEQUENCE) @SequenceGenerator(name="imagem_anuncio_id_seq", sequenceName="imagem_anuncio_id_seq", allocationSize=1) private Integer id; private String nome;

@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="id_anuncio") private Anuncio anuncio;

// gets e sets omitidos // equals() e hashCode() omitidos}Os principais trechos do cdigo so os seguintes: Define a classe como uma entidade JPA; Define que o nome da tabela para o qual a entidade ser mapeada imagem_anuncio. Caso no especificarmos um, a JPA assumir o nomeimagemanuncio(sem caractere de separao entre as palavras); Configura o atributoidcomo chave primria da tabela imagem_anuncio; Define que o valor do atributoiddeve ser gerado automaticamente, atravs da sequence imagem_anuncio_id_seq no banco; Define que a classeImagemAnuncioter uma relao de muitos para um comAnuncio, expressa pelo atributo anuncio, e que a chave estrangeira na tabela imagem_anuncioser mapeada pela coluna id_anuncio.

Criando os EJBsEm nossa arquitetura, toda vez que for necessria alguma operao no banco de dados, invocaremos EJBs locais que realizaro toda a lgica de acesso ao SGBD e, se for o caso, devolvero o resultado para nossos Managed Beans. Com base em uma sequncia lgica, o primeiro serModeloService. Para cri-lo, clique com o boto direito em cima do projeto, selecioneNewe depois clique emClass. Na tela que surge, informe emPackageo valor br.com.javamagazine.leilaojm.ejb, emNameinforme ModeloService e confirme no botoFinish. Da mesma forma que fizemos quando criamos as entidades, precisamos modificar o cdigo gerado pelo Eclipse para ficar semelhante ao daListagem 12.Listagem 12. Cdigo da classe ModeloService.package br.com.javamagazine.leilaojm.ejb;

import java.util.List;

import javax.ejb.Stateless;import javax.persistence.*;

import br.com.javamagazine.leilaojm.domain.*;

@Statelesspublic class ModeloService {

@PersistenceContext private EntityManager entityManager;

public void salvaModelo(Modelo modelo) { entityManager.persist(modelo); }

@SuppressWarnings("unchecked") public List listaModelos() { Query query = entityManager.createQuery("Select m from Modelo m order by m.nome");

return query.getResultList(); }

@SuppressWarnings("unchecked") public List listaMarcas() { Query query = entityManager.createQuery("Select m from Marca m order by m.nome");

return query.getResultList(); }}Os principais trechos do cdigo so os seguintes: Define a classe como um EJB Stateless (verBOX 1) atravs da anotao@Stateless; Anotao@PersistenceContextda JPA injeta o EntityManagerno EJB a partir dos dados de conexo informados no arquivopersistence.xml(no nosso caso, usamos umdatasource) para podermos realizar as operaes no banco de dados; Invoca o mtodopersist()doEntityManager. Este mtodo realiza uma operao deinsertno banco de dados, gravando o objetomodelopassado na tabela correspondente; Cria um objeto do tipoQuerya partir do mtodo createQuery()doEntityManager. A classe Query oferece mtodos para consulta e atualizao de dados no banco de dados; MtodogetResultList()da classeQuery chamado para retorna uma listagem do banco de dados.BOX 1. EJB StatelessTrata-se de um EJB que no precisa manter o estado das regras de negcio nas quais que ele est envolvido. Por exemplo: um EJB que retorna o endereo baseado em um CEP fornecido no precisa ter informaes do ltimo CEP que foi consultado.Nosso prximo EJB,AvaliacaoService, ser responsvel por realizar as operaes que dizem respeito s avaliaes dos modelos de veculos no banco de dados. Assim, crie a classe no mesmo pacote do EJB anterior e substitua o cdigo gerado pelo daListagem 13.Listagem 13. Cdigo da classe AvaliacaoService.package br.com.javamagazine.leilaojm.ejb;

import java.util.List;import javax.ejb.Stateless;import javax.persistence.*;import br.com.javamagazine.leilaojm.domain.Avaliacao;

@Statelesspublic class AvaliacaoService { @PersistenceContext private EntityManager entityManager;

public void salvaAvaliacao(Avaliacao avaliacao) { entityManager.persist(avaliacao); }

public void excluiAvaliacao(Avaliacao avaliacao) { // evita erro de entidade no gerenciada pelo contexto avaliacao = entityManager.find(Avaliacao.class, avaliacao.getId()); entityManager.remove(avaliacao); }

@SuppressWarnings("unchecked") public List listaAvaliacoesDoModelo(Integer idModelo) { Query query = entityManager.createQuery("Select a from Avaliacao a where a.modelo.id = :idModelo"); query.setParameter("idModelo", idModelo); return query.getResultList(); }}Podemos observar no cdigo que, assim como fizemos na classe ModeloService, chamamos os mtodos persist(), createQuery() e getResultList() deEntityManager. As novidades aqui so as chamadas aos mtodosfind(), na linha 22 (que encontra um objeto a partir de sua chave primria), eremove(), na linha 23 (que exclui o objeto passado). Alm deles, invocamos o mtodosetParameter()da classeQueryna linha 29. Este substitui um parmetro na consulta (atravs da expresso:idModelo) pelo valor passado na chamada do mtodo.Nosso ltimo EJB serAnuncioService. Sua funo realizar as operaes com os anncios de veculos e as imagens dos anncios no banco de dados. Desta forma, crie a classe dentro do mesmo pacotebr.com.javamagazine.leilaojm.ejbe substitua o cdigo gerado pelo daListagem 14.Listagem 14. Cdigo da classe AnuncioService.package br.com.javamagazine.leilaojm.ejb;

import java.util.List;

import javax.ejb.Stateless;import javax.persistence.*;import br.com.javamagazine.leilaojm.domain.*;

@Statelesspublic class AnuncioService {

@PersistenceContext private EntityManager entityManager;

public Anuncio recuperaAnuncioPeloId(Integer id) { return entityManager.find(Anuncio.class, id); }

public void salvaAnuncio(Anuncio anuncio) { entityManager.persist(anuncio); }

public void salvaImagemAnuncio(ImagemAnuncio imagemAnuncio) { entityManager.persist(imagemAnuncio); }

public void atualizaAnuncio(Anuncio anuncio) { entityManager.merge(anuncio); }

@SuppressWarnings("unchecked") public List listaAnuncios() { Query query = entityManager.createQuery("Select a from Anuncio a order by a.titulo"); return query.getResultList(); }

@SuppressWarnings("unchecked") public List listaAnunciosDoModelo(Integer idModelo) { Query query = entityManager.createQuery("Select a from Anuncio a where a.modelo.id = :idModelo"); query.setParameter("idModelo", idModelo); return query.getResultList(); }}Assim como nos EJBs anteriores, o cdigo apresentadotraz chamadas aos mtodosfind(),persist()ecreateQuery()da classe EntityManager. A nica novidade est na invocao do mtodomerge(), na linha 29, utilizado para atualizar um objeto no banco de dados.

Criando os Managed BeansAgora que temos as entidades e os EJBs criados, precisamos dosControllerspara realizar a comunicao com as pginas XHTML. Nesta demonstrao, definiremos quatroManaged Beanscom escopo de requisio, que a soluo mais indicada para as operaes que iremos realizar, sobretudo por proporcionar economia de memria.Para seguir a mesma sequncia de cadastros do sistema (primeiro inserimos o modelo para depois cadastrarmos as avaliaes e os anncios dele), nosso primeiroManaged BeanserModeloBean, a ser criado no pacotebr.com.javamagazine.leilaojm.managedbean. Da mesma forma que fizemos nas etapas anteriores, precisamos modificar o cdigo gerado pelo Eclipse para ficar semelhante ao daListagem 15(lembre-se de inserir os gets e sets de modelo, listaModeloselistaMarcas, que foram omitidos).Listagem 15. Cdigo da classe ModeloBean.package br.com.javamagazine.leilaojm.managedbean;

import java.io.Serializable;//imports omitidos

@Named@RequestScopedpublic class ModeloBean implements Serializable { private static final long serialVersionUID = -5491076120921100881L;

@EJB private ModeloService modeloService;

@Inject private Modelo modelo;

private List listaModelos; private List listaMarcas;

public String preparaCadastroModelo() { listaMarcas = modeloService.listaMarcas(); modelo = new Modelo(); return "cadastrarModelo.xhtml"; }

public String cadastraModelo() { modeloService.salvaModelo(modelo); // adiciona mensagem de sucesso FacesMessage fm = new FacesMessage("Sucesso ao cadastrar o modelo " + modelo.getNome()); fm.setSeverity(FacesMessage.SEVERITY_INFO); FacesContext.getCurrentInstance().addMessage("form", fm); modelo = new Modelo(); return null; }

public String listaModelosParaAvaliacoes() { listaModelos = modeloService.listaModelos(); return "listarAvaliacoesPasso1.xhtml"; }

public String listaModelosParaAnuncio() { listaModelos = modeloService.listaModelos(); return "cadastrarAnuncioPasso1.xhtml"; }

public Marca retornaMarcaPeloNome(String marcaSelecionada) { for (Marca marca : listaMarcas) { if (marca.getNome().equals(marcaSelecionada)) { return marca; } } return null; }

// gets e sets de modelo, listaModelos e listaMarcas omitidos}Os principais trechos do cdigo podem ser explicados da seguinte forma: A anotao do CDI@Namedtransforma a classe em um Managed Bean ao dar um nome para que ele seja invocado via expression language (como no foi especificado nenhum, o CDI assume o nome da classe comeando com a primeira letra em minsculo) ou injetado em outra classe; A anotao do CDI@RequestScopeddefine o objeto com escopo de requisio; Com a anotao@EJBdefinimos que o EJB ModeloService deve ser injetado emModeloBean; A anotao@Injectinstrui o CDI a instanciar automaticamente o objetoModeloemModeloBean.Nosso segundoManaged Beana ser criado realizar as operaes de armazenar e remover as avaliaes de veculos reportadas pelos usurios. Assim, crie a classeAvaliacaoBeanno mesmo pacote do Managed Beananterior e deixe o cdigo igual ao daListagem 16(lembre-se de inserir o get e set deavaliacao).Listagem 16. Cdigo da classe AvaliacaoBean.package br.com.javamagazine.leilaojm.managedbean;

import java.io.Serializable;// imports omitidos

@Named@RequestScopedpublic class AvaliacaoBean implements Serializable { private static final long serialVersionUID = 4950531216902366633L;

@EJB private AvaliacaoService avaliacaoService;

@Inject private ModeloBean modeloBean;

@Inject private Avaliacao avaliacao;

public String listaAvaliacoesDoModelo() { List avaliacoes = avaliacaoService.listaAvaliacoesDoModelo(modeloBean.getModelo().getId()); modeloBean.getModelo().setListaAvaliacoes(avaliacoes); return "listarAvaliacoesPasso2.xhtml"; }

public void cadastraAvaliacaoModelo() { avaliacao.setModelo(modeloBean.getModelo()); avaliacaoService.salvaAvaliacao(avaliacao); modeloBean.getModelo().getListaAvaliacoes().add(0, avaliacao); // adiciona mensagem de sucesso FacesMessage fm = new FacesMessage("Sucesso ao cadastrar avaliao"); fm.setSeverity(FacesMessage.SEVERITY_INFO); FacesContext.getCurrentInstance().addMessage("form", fm); avaliacao = new Avaliacao(); }

public void excluiAvaliacaoModelo() { avaliacaoService.excluiAvaliacao(avaliacao); modeloBean.getModelo().getListaAvaliacoes().remove(avaliacao); // adiciona mensagem de sucesso FacesMessage fm = new FacesMessage("Sucesso ao excluir avaliao"); fm.setSeverity(FacesMessage.SEVERITY_INFO); FacesContext.getCurrentInstance().addMessage("form", fm); avaliacao = new Avaliacao(); }

// get e set de avaliacao omitidos}Observe que nas linhas 23 e 24 estamos injetando uma instncia deModeloBeanna classeAvaliacaoBean, permitindo que recuperemos valores de atributos que esto emModeloBeande forma bastante simples. O restante do cdigo daListagem 16 bastante semelhante ao daListagem 15, portanto no so necessrias explicaes adicionais.O terceiroManaged Beanda aplicao serAnuncioBean. Ele conter toda a lgica das operaes relacionadas aos anncios de veculos e deve ficar no mesmo pacote das duas classes anteriores. Aps a gerao, deixe-o com o cdigo semelhante ao daListagem 17(insira os gets e sets deanuncio,listaCidadeelistaAnuncios, omitidos por questes de espao).Listagem 17. Cdigo da classe AnuncioBean.package br.com.javamagazine.leilaojm.managedbean;

import java.io.Serializable;// imports omitidos

@Named@RequestScopedpublic class AnuncioBean implements Serializable { private static final long serialVersionUID = 5560852435670481973L;

@EJB private AnuncioService anuncioService;

@Inject private ModeloBean modeloBean;

@Inject private Anuncio anuncio;

private Map listaCidade; private List listaAnuncios;

public String listaAnunciosCadastrados() { listaAnuncios = anuncioService.listaAnuncios(); return "listarAnuncios.xhtml"; }

public String cadastraAnuncio() { anuncio.setModelo(modeloBean.getModelo()); anuncio.setVendido(false); if (!anuncio.getPrecoFixo()) { anuncio.setValorLanceAtual(100.0); } anuncioService.salvaAnuncio(anuncio); // Nenhuma mensagem de sucesso. A pgina j mostra. return "cadastrarAnuncioPasso3.xhtml"; }

public void atualizaAnuncio() { // recarrega o anncio do banco, pois pode ter mudado o valor do ltimo lance anuncio = anuncioService.recuperaAnuncioPeloId(anuncio.getId()); }

public void efetuaCompra() { anuncio.setVendido(true); anuncioService.atualizaAnuncio(anuncio); }

public void efetuaLance() { anuncio.setValorLanceAtual(anuncio.getValorLanceAtual() + 100.0); anuncioService.atualizaAnuncio(anuncio); }

public void atualizaCidadesPelaUF() { listaCidade = new LinkedHashMap(); if (anuncio.getUf() != null) { // selecionou CE listaCidade.put("Fortaleza", "Fortaleza"); listaCidade.put("Juazeiro do Norte", "Juazeiro do Norte"); } }

// get e set de anuncio, listaCidade e listaAnuncios omitidos}Na linha 27 do cdigo temos um atributo do tipoMap. Este atributo utilizado para preencher a listagem de cidades pertencentes Unidade de Federao selecionada pelo usurio na tela de cadastro de anncio. O mtodoatualizaCidadesPelaUF(), declarado na linha 62, realiza este preenchimento aps ser chamado por um evento AJAX na pgina.O ltimoManaged Beanque vamos adicionar serGraficoBean. Como o prprio nome diz, ele conter a lgica para montar um grfico a ser exibido pelo sistema. A informao que constar no grfico ser a quantidade de anncios de um modelo de veculo agrupada por ano do modelo. A classe deve ficar no mesmo pacote dos Managed Beans anteriores e apresentar um cdigo semelhante ao daListagem 18(lembre-se de inserir o get e o set degraficoNumeroAnuncios).Listagem 18. Cdigo da classe GraficoBean.package br.com.javamagazine.leilaojm.managedbean;

import java.io.Serializable;import java.util.*;import javax.ejb.EJB;import javax.enterprise.context.RequestScoped;import javax.inject.*;import org.primefaces.model.chart.*;import br.com.javamagazine.leilaojm.domain.Anuncio;import br.com.javamagazine.leilaojm.ejb.AnuncioService;

@Named@RequestScopedpublic class GraficoBean implements Serializable { private static final long serialVersionUID = 6281068679067518117L;

@EJB private AnuncioService anuncioService;

@Inject private ModeloBean modeloBean;

private BarChartModel graficoNumeroAnuncios; private Integer qtdMaximaAnuncios;

public void criaGraficoLinha() { graficoNumeroAnuncios = preencheDadosSeries(); graficoNumeroAnuncios.setTitle("Nmero de Anncios para " + modeloBean.getModelo().getNome() + " por ano do modelo"); graficoNumeroAnuncios.setLegendPosition("e"); graficoNumeroAnuncios.setShowPointLabels(true); graficoNumeroAnuncios.getAxes().put(AxisType.X, new CategoryAxis("Ano do Modelo")); Axis yAxis = graficoNumeroAnuncios.getAxis(AxisType.Y); yAxis.setMin(0); yAxis.setMax(qtdMaximaAnuncios+2); yAxis.setLabel("Quantidade"); }

private BarChartModel preencheDadosSeries() { BarChartModel model = new BarChartModel(); BarChartSeries series1 = new BarChartSeries(); List anuncios = anuncioService.listaAnunciosDoModelo(modeloBean.getModelo().getId()); Map mapaAnunciosPorAno = agrupaNumeroAnunciosPorAnoModelo(anuncios); series1.setLabel(modeloBean.getModelo().getNome()); Set chaves = mapaAnunciosPorAno.keySet(); for (Integer chave : chaves) { series1.set(chave, mapaAnunciosPorAno.get(chave)); } model.addSeries(series1); return model; }

private Map agrupaNumeroAnunciosPorAnoModelo(List anuncios) { Map anunciosPorAnoModelo = new HashMap(); qtdMaximaAnuncios = 1; for (Anuncio anuncio : anuncios) { if (anunciosPorAnoModelo.containsKey(anuncio.getAnoModelo())) { Integer qtdAnuncios = anunciosPorAnoModelo.get(anuncio.getAnoModelo()); anunciosPorAnoModelo.put(anuncio.getAnoModelo(), ++qtdAnuncios); if (qtdAnuncios > qtdMaximaAnuncios) { qtdMaximaAnuncios++; } } else { anunciosPorAnoModelo.put(anuncio.getAnoModelo(), 1); } } return anunciosPorAnoModelo; }

// get e set do atributo graficoNumeroAnuncios omitidos}Antes de comentar o cdigo apresentado, precisamos entender o conceito de srie em um grfico. Uma srie um conjunto de dados que se referem mesma informao. Por exemplo: podemos gerar um grfico comparando a quantidade de anncios cadastrados para dois modelos de veculos. Neste caso, teramos que ter duas sries no grfico: uma para mostrar a quantidade de anncios do primeiro modelo de veculo e outra para mostrar a do segundo. Como poderemos ver, no cdigo daListagem 18temos apenas uma srie, pois queremos exibir a quantidade de anncios do modelo de veculo selecionado pelo usurio na tela por ano do modelo. Assim, a nica srie envolver o ano do modelo (lembre-se: todo carro tem o ano de fabricao e o ano do modelo).Aps este entendimento, temos os seguintes trechos de cdigo importantes naListagem 18: implementa o mtodocriaGraficoLinha(), chamado por umna pgina a ser criada na continuao do artigo para mostrar o grfico; chama o mtodopreencheDadosSeries(), que monta o grfico de acordo com os anncios encontrados para o modelo; configura as informaes gerais a serem exibidas no grfico (ttulo, posio da legenda, indicao para exibir legenda com a quantidade de anncios e o texto da legenda do eixo horizontal); define as informaes do eixo vertical (valor mnimo, valor mximo e o texto da legenda); implementa o mtodopreencheDadosSeries(), que insere a srie de valores do eixo horizontal (anos dos modelos) e as respectivas quantidades de anncios encontradas para cada ano; armazena em umMapo retorno do mtodoagrupaNumeroAnunciosPorAnoModelo(). As chaves contidas noMapso os anos dos modelos encontrados entre os anncios para o modelo de veculo selecionado; define o nome do modelo de veculo como a legenda da nica srie do grfico. Neste ponto, o componente de grfico do PrimeFaces ir escolher uma cor para os valores da srie exibidos no grfico e mostrar o nome do modelo de veculo associado a esta cor; cria umSetcom os anos de modelo do veculo selecionado pelo usurio na tela encontrados entre os anncios, percorre os elementos doSete chama o mtodoset()deChartSeries. Este mtodo recebe o ano do modelo e a respectiva quantidade de anncios daquele ano como parmetros para colocar os valores na srie do grfico; adiciona ao grfico a srie com os anos de modelo encontrados entre os anncios e as respectivas quantidades de cada ano; implementa agrupaNumeroAnunciosPorAnoModelo(), que rene os anncios por ano do modelo e calcula a respectiva quantidade de anncios; percorre a lista de anncios do modelo, identifica cada ano de modelo entre os anncios e incrementa a quantidade de anncios por ano, armazenando-a em umMap. A chave doMap o ano do modelo e o valor associado chave a quantidade de anncios correspondente.

Criando o Converter de MarcaAinda no que se refere ao cdigo deback-end, outra classe que se far necessria no sistema MarcaConverter, que no momento do cadastro de um modelo receber umaStringda pgina que realizar esta operao e a converter em um objeto do tipoMarca. Como veremos na continuao do artigo, a classe MarcaConverterser utilizada pelo componente do PrimeFaces de nomeSelectOneMenu, que tem suporte para o uso de colunas (ao clicarmos no componente, os valores so exibidos no formato de tabela). O cdigo do Converter est naListagem 19e deve ser criado dentro do pacote br.com.javamagazine.leilaojm.converter.Listagem 19. Cdigo da classe MarcaConverter.package br.com.javamagazine.leilaojm.converter;

import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.convert.Converter;import javax.faces.convert.FacesConverter;import javax.inject.Inject;import br.com.javamagazine.leilaojm.domain.Marca;import br.com.javamagazine.leilaojm.managedbean.ModeloBean;

@FacesConverter("marcaConverter")public class MarcaConverter implements Converter {

@Inject private ModeloBean modeloBean;

@Override public Object getAsObject(FacesContext contexto, UIComponent componente, String marcaStr) { return (Marca) modeloBean.retornaMarcaPeloNome(marcaStr); }

@Override public String getAsString(FacesContext contexto, UIComponent component, Object marcaObjeto) { return ((Marca) marcaObjeto).getNome(); }}Podemos notar nas linhas 15 e 16 que estamos criando uma instncia deModeloBeanatravs da anotao@Inject. J na linha 20, recebemos aStringque corresponde ao nome da marca selecionada pelo usurio na tela e a convertemos em um objeto do tipoMarca. Este procedimento necessrio porque na instncia deModelotemos um relacionamento comMarca.Esta primeira parte do artigo mostrou o quanto podemos produzir cdigo eficiente e bastante limpo em nossas aplicaes utilizando a Java EE 7. Nesta situao, o acesso ao banco de dados atravs da JPA 2.1, a injeo de dependncias provida pelo CDI 1.1, os recursos do JSF 2.2 fornecidos para a camada de viso e a implementao da camada de negcios com EJB 3.2 permitem deixar o cdigo organizado, coeso e desacoplado. Todas estas caractersticas proporcionam uma leitura mais simples das classes e uma manuteno do sistema mais barata.

Leia mais em:PrimeFaces: Criando um sistema de leilo de veculos em Java Parte 1http://www.devmedia.com.br/primefaces-criando-um-sistema-de-leilao-de-veiculos-em-java-parte-1/31536#ixzz3Iqu4ptPQ

Criando um sistema de leilo de veculos em Java Parte 2Confira neste artigo como desenvolver um sistema de leilo de veculos e conhea os principais componentes do framework RIA para JSF mais popular do mercado.Fique por dentroEscolher bem o framework RIA para JSF do seu projeto uma tarefa extremamente importante na definio da arquitetura. Para auxiliar na realizao deste passo, este artigo ir apresentar vrios recursos do PrimeFaces 5 atravs de exemplos prticos criados na implementao de um sistema de leilo de veculos.As solues iro envolver uma grande quantidade de componentes da biblioteca turca dos mais diversos tipos e permitiro descobrir porque ela a opo mais popular para JavaServer Faces do mercado.O PrimeFaces 5 veio com muitos recursos novos e vrias melhorias em relao verso anterior. Alm das novidades adicionadas ao produto, a biblioteca oferece uma variedade muito grande de componentes (mais de 135), sendo vrios deles de forma exclusiva.Como poderemos constatar, boa parte desses componentes ser utilizada em nosso projeto em solues que serviro de exemplo para operaes semelhantes encontradas pelos desenvolvedores na maioria dos sistemas JSF, como listagens de dados, cadastros de objetos e submisses parciais de dados com AJAX.Na primeira parte do artigo, vimos as principais novidades do PrimeFaces 5 e construmos oback enddo sistema utilizando alguns dos principais frameworks que compem a plataforma Java EE 7, como JPA 2.1, CDI 1.1, JSF 2.2 e EJB 3.2.Nesta segunda parte do artigo, continuaremos a implementao do sistema de leilo de veculos atravs da criao das pginas XHTML do projeto e da realizao de pequenas modificaes em um dos nossosManaged Beans.Entre os principais recursos que iremos utilizar, esto o processamento de dados de formulrio via AJAX e a renderizao parcial de elementos na tela. Em termos de componentes, os mais importantes que colocaremos nas pginas do sistema sero o DataTableeCalendar(ambos remodelados na verso 5 do PrimeFaces), DataScroller(novidade da verso 5 desta biblioteca), Panel, PanelGridetagsrelacionadas criao de menus (Menubar, MenuItemeSubmenu).

Criando as pginas do sistemaDando continuidade ao desenvolvimento do sistema, nosso prximo passo ser criar as pginas XHTML. Em cada uma delas utilizaremos vrios componentes do PrimeFaces que sero explicados um a um, descrevendo para que servem e quais instrues foram utilizadas para que eles funcionem da forma como desejamos nas pginas.

Criando o templateA primeira estrutura que iremos criar otemplategeral das pginas do sistema, utilizando para isso o framework Facelets, uma linguagem de descrio de pginas voltada especificamente para JSF.Otemplateservir para definirmos alguns trechos comuns a todas as pginas do sistema (como o menu e o componente destatus das requisies AJAX) e nos permitir codificar apenas o corpo interno das outras telas.Desta forma, clique com o boto direito em cima desrc/main/webapp, selecione a opoNewe depois clique emHTML File. Na tela que surge, informe o nome layoutBase.xhtml e clique emNext. Em seguida, selecione a opoNew XHTML File (1.0 strict)e clique emFinish. O Eclipse gerar um pequeno cdigo que deve ser alterado para ficar igual ao daListagem 1, que traz os seguintes componentes do PrimeFaces: Menubar: coloca uma barra de menu horizontal na pgina, permitindo adicionar itens de menu; MenuItem: componente genrico que pode ser adicionado a vrias outrastagsdo PrimeFaces. No nosso caso, adicionaremos dentro doMenuBarpara aparecer diretamente como umlinkno menu e dentro do SubMenupara aparecer internamente dentro de um menu hierrquico; Submenu: adiciona um menu hierrquico a um Menubar ou, como o prprio nome diz, um submenu a um menu j existente; Messages: estende o componente de mensagens do JSF adicionando customizao de CSS; Dialog: mostra um painel flutuante que pode sobrepor os outros componentes da pgina. Em nossa pgina, o Dialogser utilizado para mostrar que a requisio AJAX est sendo processada; AjaxStatus: trata-se de um notificador de como se encontram as requisies AJAX realizadas no sistema; GraphicImage: exibe imagens estticas que podem estar no contexto da aplicao, ser criadas em tempo de execuo, ou at mesmo armazenadas no banco de dados.Listagem 1. Cdigo da pgina layoutBase.xhtml.

Leilo JM

Os principais trechos do cdigo dessa listagem so: o componentedeclara um possvel ponto de substituio. Isto significa que pginas que usem esta pgina comotemplatepodem redefinir o cdigo que est dentro datagque, no nosso caso, codifica o menu. Isto pode ser til, por exemplo, caso em uma pgina do sistema o menu no deva ser exibido; adiciona um formulrio do JSF. Sem ele, os itens do menu no funcionam; insere o componente de barra de menu; insere um item de menu para ficar diretamente como linkna barra de menu. A instruo ajax=falseconfigura a ao disparada no clique domousecomo uma requisio no AJAX; adiciona dois menus hierrquicos barra de menu; insere itens de menu como opes internas nos menus hierrquicos criados; adiciona o componente de mensagens do PrimeFaces. Colocando-o aqui, permitimos que sejam mostradas quaisquer mensagens de erro, sucesso ou aviso no sistema que usem estetemplate; adiciona oDialog pgina. Em nosso sistema, esse painel servir para mostrar que a requisio ajax do usurio est sendo processada. Por este motivo, o nico contedo dele uma imagemgifque representa que um processo est sendo executado. O atributowidgetVarsubstitui o atributo name encontrado na maioria dos elementos HTML para que o PrimeFaces localize o componente na tela no caso de uma outratagreferenci-lo.A instruomodal=trueindica que os outros componentes da tela devem ficar sobrepostos enquanto o painel estiver sendo exibido. As instruesdraggable=false,closeable=falseeresizable=falseindicam que o painel no pode ser movido, fechado e nem redimensionado, e a instruoshowHeader=false sinaliza que o painel no deve ter cabealho; inserimos o componente GraphicImageapontando para o gifesttico do projeto dentro do painel; atravs do componenteAjaxStatus, notificamos o usurio a respeito da situao da requisio. No atributo onstart colocamos uma instruo para que oDialogdeclarado anteriormente seja mostrado na tela nas requisies AJAX. J no atributoonsuccesscolocamos uma instruo para que oDialogseja ocultado. Assim, o usurio acompanha visualmente o andamento da sua requisio; adicionamos outro componentecomo possvel ponto de substituio. Neste caso no h cdigo dentro do componente. Assim, se uma pgina que usar este XHTML comotemplateno redefinir a estrutura com o nomecorpo(explicado a seguir), este trecho da pgina ficar sem contedo.

Criando a pgina inicialAgora que criamos nossotemplate, vamos elaborar nossa pgina inicial do sistema. Assim, crie o arquivoindex.xhtmldentro da mesma pasta do XHTML anterior. Da mesma maneira que no passo anterior, um cdigo ser gerado e deve ser modificado para ficar semelhante ao daListagem 2.Listagem 2. Cdigo da pgina index.xhtml.

Bem vindo. Escolha sua opo no menu acima.

Observe que temos o componente. Podemos verificar no cdigo que indicamos a pgina layoutBase.xhtml comotemplateatravs da instruo template=layoutBase.xhtml.Aps inserimos a instruo, que indica que estamos redefinindo um trecho criado com. Neste caso, o presente no template.Aps salvar o arquivo, vamos rodar a aplicao. Para isso, necessrio que o WildFly j esteja configurado no Eclipse. Caso no tenha o servidor criado na IDE, na seoLinksh um post do blogdo autor em que possvel ver como realizar esta etapa. Quando tudo estiver pronto, para executar a aplicao clique com o boto direito em cima da raiz do projeto, selecioneRun As, depois a opoRun On Server, marque o item WildFly na tela que surge e pressione o botoFinishpara confirmar. Aps a publicao, a tela inicial do sistema ser exibida conforme aFigura 1.

Figura 1. Tela inicial do sistema.

Criando a pgina de cadastro de modelosNossa prxima pgina ser a de cadastro de modelos. Para ger-la, crie o arquivocadastrarModelo.xhtmldentro da mesma pasta das pginas anteriores e deixe o cdigo igual ao daListagem 3, que contm, entre todas astags, os seguintes componentes do PrimeFaces no comentados ainda no artigo: PanelGrid: gera uma tabela na pgina com o nmero de colunas determinado pelo atributocolumns. Possui suporte para mesclagem de linhas e colunas; OutputLabel: gera umlabelem formulrios; InputText: cria uminputde texto para entrada de dados; Message: exibe na pgina uma mensagem nica criada a partir da classeFacesMessage; SelectOneMenu: gera um componentedropdownpara permitir a seleo de uma das opes; Column: insere uma coluna em alguns componentes do PrimeFaces, tais como tabelas (PanelGrid), rvores (TreeTable) edropdown(SelectOneMenu); Tooltip: gera umtooltipassociado a outro componente da tela. Em nosso caso, vincularemos a umInputText; Slider: gera um componente na tela atravs do qual o valor escolhido pelo usurio especificado arrastando um ponteiro com omousedentro de um intervalo pr-determinado; Calendar: campo para entrada de data, hora ou ambos. Na verso 5 do PrimeFaces recebeu o suporte a mscaras, para que o valor digitado obedea a umpattern; CommandButton: exibe um boto para submeter os dados preenchidos no formulrio.Listagem 3. Cdigo da pgina cadastrarModelo.xhtml.

$(document).ready( function() { PrimeFaces.locales['pt_BR'] = { prevText : 'Anterior', nextText : 'Prximo', currentText : 'Data Atual', monthNamesShort : [ 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez' ], dayNamesShort : [ 'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sb' ], firstDay : 1, isRTL : false, showMonthAfterYear : false, yearSuffix : '', month : 'Ms', week : 'Semana', day : 'Dia' }; }); 28 Cadastrar Modelo 29 Informe os dados do modelo do veculo. 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 Esta pgina faz uso de um importante recurso presente na verso 5 do PrimeFaces: a validao de dados no lado do cliente. Aengineque realiza este procedimento extremamente eficiente, entra em ao em requisies comuns ou AJAX e tem suporte para submisso parcial dos dados, i18n econvertersde objetos.Para habilitar o recurso de validao no cliente preciso modificar o arquivoweb.xml, adicionando as seguintes linhas antes da tag de fechamento:

primefaces.CLIENT_SIDE_VALIDATION true

Os principais trechos do cdigo daListagem 3so: Linhas 11 e 12: adiciona o componentesaveStatedo Tomahawk. Ele necessrio porqueModeloBeantem escopo de requisio e, devido ao comportamento do ciclo de vida do JSF, se no salvarmos o estado (ou seja, guardarmos os valores) demodeloelistaMarcas, os atributos demodeloe a varivellistaMarcasficaro como null noManaged Beanantes de chamarmos o mtodo cadastraModelo().Uma soluo para este problema seria utilizarmos o escopo de viso (@ViewScoped) do JSF, mas como preferimos o escopo de requisio do CDI, temos que recorrer a recursos como este; Linhas 15 a 24: cdigo JavaScript para traduzir oslabelsdo componente Calendarpara portugus do Brasil; Linha 30: define umPanelGridcom trs colunas. Geramos a estrutura da tabela no cdigo com a primeira coluna contendo oslabels, a segunda os componentes de entrada de dados e a terceira oMessageassociado a cada campo para exibir um eventual erro no caso de um campo obrigatrio no estar preenchido ou apresentar valor invlido (veja aFigura 2); Linhas 31, 35, 48, 55 e 63: adiciona quatrolabels pgina. O atributofordetermina a que componente oOutputLabelest associado; Linhas 32 e 50: insere campos de entrada de textoInputText; Linha 33, 46, 53, 61 e 65: define um componenteMessagepara cada componente de entrada de dados (observe o atributoforque faz esta ligao). Eles foram colocados para exibir mensagens de erro caso qualquer um dos componentes de entrada de dados (InputText,SelectOneMenu,SlidereCalendar) no esteja preenchido, ou tenha sido fornecido um valor invlido; Linhas 36 a 45: insere umdropdownna pgina. Como mencionado anteriormente, o componenteSelectOneMenudo PrimeFaces tem suporte para apresentao do seu contedo interno como tabela. Em nosso exemplo usamos este recurso e inserimos uma coluna para mostrar a logomarca do fabricante e outra para exibir o nome. Veja que neste componente que estamos utilizando o converterMarcaConverter, criado anteriormente no projeto; Linhas 39 a 41 e 42 a 44: insere colunas noSelectOneMenu. Esta estrutura necessria quando se tem mais de uma coluna no componentedropdown. O objetivo delimitar o que vai constar em cada uma delas; Linha 49: insere uma coluna noPanelGrid. Aqui ela foi colocada para que mais de um componente (InputTexteTooltip) fossem adicionados na mesma coluna da tabela; Linha 51:tooltipcolocado para aparecer quando oInputTextque contm o valor da motorizao receber o foco e sumir quando o InputText perder o foco (veja os atributos for, showEvent e hideEvent). O texto a ser exibido noTooltip obtido do atributo titledoInputText; Linha 57: adiciona umOutputTextnativo do JSF para exibir o valor selecionado no componenteSlider; Linha 58: insere um componenteInputHiddennativo do JSF para submeter o valor selecionado no componenteSlider; Linha 59: adiciona o componenteSlider pgina. O atributo displayindica qual componente ser atualizado para exibir o valor que o usurio selecionou,forindicaqual componente submeter o valor selecionado noSlider(geralmente umInputHidden o nosso caso , ou umInputText),minValueemaxValuedeterminamo intervalo de valores possveis para seleo edisplayTemplateo texto que o componente especificado no atributodisplayreceber a cada troca de valor; Linha 64: adiciona o componenteCalendar. No nosso caso, especificamos que ele no pode aceitar entrada de dados manualmente (readOnlyInput=true), que o usurio pode escolher o ms e o ano atravs de um atalho (navigator=true), que o padro de data segue o formato dia, ms e ano (pattern=dd/MM/yyyy), que o idioma utilizado deve ser portugus do Brasil (locale=pt_BR) e que as opes de ano compreendem o intervalo entre o ano seguinte ao da data atual e 100 anos atrs (yearRange=c-100:c+1); Linha 68: insere o boto de submisso do formulrio na pgina. A instruoajax=falseindica que a requisio a ser feita no deve ser do tipo AJAX e a instruovalidateCliente=truesinaliza que os dados do formulrio devem ser validados do lado do cliente.Para visualizar a tela, reinicie o servidor WildFly e ao acessar a aplicao, clique na opoCadastrar Modelo, do menuModelos de Carros. AFigura 2exibe como ficou a pginacadastrarModelo.xhtml.

Figura 2. Tela de cadastro de modelo.J aFigura 3mostra a pgina aps a submisso dos dados com os campos vazios e, por isso, com os erros de validao sendo exibidos.

Figura 3. Erros de validao aps submeter o formulrio.

Criando as pginas para cadastrar/listar avaliaesNosso prximo passo ser criar as pginas do fluxo de cadastro/listagem de avaliaes. Neste cenrio, preciso primeiro selecionar o modelo para s depois cadastrar ou listar as avaliaes. Por este motivo, teremos que gerar dois arquivos XHTML. Inicialmente, vamos criar a pgina para seleo do modelo, gerando listarAvaliacoesPasso1.xhtmldentro da mesma pasta do XHTML anterior.Modifique o cdigo definido automaticamente para ficar semelhante ao daListagem 4, que contm, entre todas astags, os seguintes componentes do PrimeFaces no comentados ainda no artigo:Carousel: gera um componente que exibe dados dispostos em um formato que lembra um carrossel;CommandLink: gera umlinkque aponta para algum mtodo em umManaged Beanou para outra pgina;LightBox: gera umadivflutuante que pode exibir texto esttico, imagens, contedo multimdia e at mesmo uma pgina externa;Media: permite colocar contedo multimdia na pgina, como vdeos, udios e PDF.Listagem 4. Cdigo da pgina listarAvaliacoesPasso1.xhtml. 01 02 09 10 11 12 13 14 15 16 Cadastrar/Listar Avaliaes 17 Selecione o modelo para cadastrar/visualizar as avaliaes. 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 Os principais trechos do cdigo so: Linhas 12 e 13: adiciona o componentesaveStatedo Tomahaw para salvar o estado dos atributos modelo e listaModelos de ModeloBean; Linhas 19 a 52: insere o componente que mostra os dados dos modelos cadastrados no formato de um carrossel; Linhas 20 a 47: insere umPanelGridnoCarouselpara mostrar os dados de cada modelo em uma tabela de duas colunas; Linhas 21 a 27: define o cabealho de cada coluna da tabela com dois elementos: umlinkgerado pelo componenteCommandLink, sendo posicionado do lado direito da coluna (exibido apenas se existir um vdeo de apresentao do modelo do veculo), e uma imagem com a logomarca do fabricante, posicionada automaticamente no centro da coluna; Linhas 22 a 25: gera umlinkatravs de umCommandLinkse o modelo do veculo possui um vdeo de divulgao. A instruoajax=trueindica que a requisio do tipo AJAX eoncomplete=PF('boxvideo').show();indica que adivboxvideodeve ser mostrada depois do processamento da requisio, logo aps a atualizao dadivrealizada pela instruoupdate=:form:boxvideo; Linhas 49 a 51: define o rodap doCarouselpara mostrar a informao de quantos modelos esto cadastrados no sistema; Linhas 54 a 58: insere umadivflutuante na pgina gerada pelo componenteLightBox. Por padro, adivfica oculta at que alguma instruo determine que ela seja mostrada. A instruoname=inlineda linha 55 sinaliza que o contedo interno dadivdeve ser mostrado sem que uma quebra de linha seja criada na tela; Linha 56: o componenteMediainsere um reprodutor de contedo multimdia nadivflutuante. O atributoplayer=flashindica que o contedo a ser mostrado do tipoflash.Assim, se clicarmos no cone que aparece para o modeloNovo Golf, ser exibido um vdeo, uma vez que ao subirmos a aplicao o modelo foi instanciado com o atributolinkVideoapontando para uma URL de divulgao do veculo no YouTube.Para testar a nova pgina, entre no menuModelos de Carrose clique emCadastrar/Listar Avaliaes. AFigura 4exibe como ficou a pginalistarAvaliacoesPasso1.xhtml.

Figura 4. Tela de seleo do modelo para cadastrar/listar as avaliaes.Caso deseje, teste a visualizao do vdeo clicando no cone do filme exibido no canto direito superior da terceira coluna (espao que mostra os dados do modeloNovo Golf). Voc perceber que o componenteLightBoxser apresentado e o vdeo aparecer no centro dadivpronto para ser exibido.Agora que temos nossa tela de seleo do modelo funcionando, vamos elaborar a pgina de cadastro e listagem de avaliaes. Desta forma, crie a pginalistarAvaliacoesPasso2.xhtmldentro da pastasrc/main/webappe altere o cdigo gerado pelo Eclipse, deixando-o igual ao daListagem 5, que possui, alm de outrastags, os seguintes componentes do PrimeFaces no comentados ainda no artigo:Growl: coloca na pgina um componente posicionado como umadivflutuante que tem como finalidade exibir mensagens para o usurio baseadas na classeFacesMessagedo JSF;Panel: insere um componente visual com cabealho, contedo e rodap que pode agrupar outros elementos da pgina, como formulrios,labels,inputs, etc.;Editor: gera um componente de edio de texto no formato HTML;Spacer: coloca na pgina espaamentos (vertical e/ou horizontal) entre contedos;DataScroller: este um dos componentes novos lanados na verso 5 do PrimeFaces. Tem como funo exibir informaes na pgina no formato de lista atravs do carregamento dos dados sob demanda medida que se rola a pgina para baixo;Confirm: elemento que funciona em conjunto com oConfirmDialogpara pedir a confirmao do usurio na realizao de uma ao;Separator: coloca uma linha horizontal na pgina para separar contedos;ConfirmDialog: insere umadivflutuante exibida para que o usurio confirme uma ao desejada.Listagem 5. Cdigo da pgina listarAvaliacoesPasso2.xhtml. 01 02 08 09 10 11 12 13 14 15 16 Listar Avaliaes 17 Avaliaes do modelo #{modeloBean.modelo.nome} #{modeloBean.modelo.motorizacao} 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Os principais trechos do cdigo so: Linha 11: adiciona o componentesaveStatedo Tomahawk para salvar o estado dos atributosmodeloelistaModelosdeModeloBean; Linha 14: coloca o componenteGrowlna pgina para exibir mensagens criadas viaFacesMessage; Linhas 19 a 29: insere o painel na pgina contendo os campos para preenchimento da avaliao. A instruotoggleable=trueindica que o contedo do painel pode ser ocultado atravs de um boto ecollapsed=trueindica que o painel j deve estar fechado quando a pgina for exibida; Linha 25: insere o editor HTML na pgina; Linha 27: insere um boto para submeter a avaliao do cliente. A instruooncomplete=PF('painelAvaliacao').toggle();determina que o contedo do painel deve ser ocultado aps a requisio ser processada eupdate=@formdetermina que o formulrio deve ser recarregado em seguida para que a mensagem de sucesso criada noManaged Beanseja mostrada pelo componenteGrowl, os campos sejam limpos por conta de uma novaAvaliacaoter sido instanciada e a lista de avaliaes traga a avaliao adicionada; Linha 32: adiciona um espaamento vertical de 15pixelsentre o painel e o resto do contedo da pgina; Linha 34: exibe um aviso, caso nenhuma avaliao para o modelo estiver cadastrada no banco de dados; Linhas 35 a 49: insere oDataScrollerna pgina. Este componente trar grupos de cinco avaliaes medida que a pgina for rolada para baixo (instruochunkSize=5); Linhas 36 a 47: insere umPanelGriddentro doDataScrollerpara exibir os dados das avaliaes do modelo em uma tabela com uma coluna por linha; Linha 39: insere umlinkpara chamar o mtodo de excluso de avaliao. A instruoupdate=@formdetermina que o formulrio deve ser recarregado aps a requisio ser processada para que a mensagem de sucesso criada noManaged Beanseja mostrada pelo componenteGrowle a avaliao determinada seja removida da lista de avaliaes; Linha 40: adiciona uma ao de confirmao para a excluso da avaliao. Os atributosheaderemessagedefinem, respectivamente, o cabealho e a mensagem que o componenteConfirmDialogdeve ter e o atributoicon, que tipo de cone deve ser exibido ao lado da mensagem nadivflutuante; Linha 46: mostra o texto da avaliao. Observe o atributoescapecom o valorfalse. Ele especifica que o texto a ser mostrado deve ser formatado em HTML pelo navegador; Linha 48: adiciona uma linha horizontal entre as avaliaes atravs do componenteSeparator; Linhas 51 a 54: define adivflutuante a ser exibida pedindo a confirmao do usurio quando ele clicar noCommandLinkde excluso da avaliao. Pelo fato deCommandLinkpoder ter mais de uma ocorrncia na pgina (ser exibido em cada avaliao), precisamos colocar o atributoglobal=truepara indicar que o componente pode ser chamado por mais de um elemento;Aps terminar de modificar o cdigo da pgina, entre novamente na tela de seleo do modelo, atravs do menuModelos de Carros >Cadastrar/Listar Avaliaes, e clique em uma das opes para poder gravar uma avaliao e visualizar as j cadastradas. AFigura 5exibe como ficou a pginalistarAvaliacoesPasso2.xhtml.

Figura 5. Tela de visualizao/cadastro de avaliaes do modelo.Aps abrir a pgina, teste a excluso de uma avaliao para verificar o funcionamento do componente de confirmao. O cadastro de uma nova avaliao tambm pode ser realizado abrindo o painel, fornecendo os dados necessrios e clicando no botoCadastrar Avaliao.

Criando as pginas para cadastro de annciosAgora que fechamos o cenrio das operaes envolvendo avaliao, vamos partir para o cadastro de anncio. Esta operao ser feita em trs passos: no primeiro, iremos selecionar o modelo de veculo a ser anunciado, no segundo informaremos os dados do anncio e no terceiro teremos a opo de enviar fotos do veculo para o servidor.Sendo assim, crie a primeira das nossas pginas, cadastrarAnuncioPasso1.xhtml, dentro da pastasrc/main/webappe deixe o cdigo semelhante ao daListagem 6, que apresenta, entre outrastags, como nico componente do PrimeFaces ainda no comentado no artigo, oDataTable, que recebeu melhorias na verso 5 da biblioteca e exibe dados em formato de tabela, permitindo aplicar filtros, ordenar por uma das colunas, trazer dados sob demanda, entre outros recursos importantes.Listagem 6. Cdigo da pgina cadastrarAnuncioPasso1.xhtml. 01 02 08 09 10 11 12 13 14 15 Cadastrar Anncio 16 Selecione o modelo para cadastrar o anncio. 17 18 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 O principal trecho de cdigo daListagem 6 o que est presente entre as linhas 18 a 48, onde inserimos uma tabela na pgina atravs do componenteDataTable. Os atributos mais importantes colocados na declarao deste componente so:emptyMessage, que define qual mensagem deve ser mostrada se no houver dados a exibir;paginator, que informa que os dados devem ser agrupados por pgina;paginatorPosition, que determina a posio do paginador noDataTable;rows, que especifica quantas linhas devem ser exibidas por pgina;paginatorTemplate, que define o texto que deve ser exibido no paginador; e currentPageReportTemplate, que especifica o texto que deve ser exibido para indicar a pgina atual selecionada.Para visualizar a pgina gerada, entre no menuAnncioe clique na opoCadastrar Anncio. AFigura 6demonstra como ficou a tela.

Figura 6. Tela de seleo do modelo para cadastro de anncio.Depois que testamos a pgina de seleo do modelo, vamos para o prximo passo. Sendo assim, gere uma pgina chamada cadastrarAnuncioPasso2.xhtmldentro do mesmo diretrio de todas as pginas anteriores e deixe o cdigo igual ao daListagem 7, que possui, entre todas astags, os seguintes componentes novos do PrimeFaces ainda no comentados no artigo:InputMask: cria uminputde texto com a possibilidade de definio de uma mscara para que os dados sejam informados seguindo a formatao determinada;Ajax: componente utilizado para realizar algum processamento AJAX, como submeter parcialmente dados de um formulrio, executar um mtodo em umManaged Bean, entre outros;SelectBooleanCheckbox: coloca umcheckboxna pgina para determinar se um atributo verdadeiro ou falso;Captcha: gera uma imagem desafio baseada no reCAPTCHA para ser colocada no formulrio da pgina.Listagem 7. Cdigo da pgina cadastrarAnuncioPasso2.xhtml. 01 02 08 09 10 11 12 13 14 15 16 Cadastrar Anncio de #{modeloBean.modelo.marca.nome} #{modeloBean.modelo.nome} #{modeloBean.modelo.motorizacao} 17 Informe os dados do anncio. 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Os principais trechos do cdigo so: Linhas 26 e 28: coloca o componente de entrada de dados com uma mscara no formato de ano, aceitando uma sequncia de quatro dgitos numricos; Linha 34: define um processamento AJAX na pgina. Pelo fato do componenteAjaxestar dentro doSelectOneMenude UF, o valor selecionado pelo usurio ser submetido, atualizando o atributo noManaged Bean.A instruolistener="#{anuncioBean.atualizaCidadesPelaUF}"indica que o mtodoatualizaCidadesPelaUF()deAnuncioBeandeve ser chamado aps algum item noSelectOneMenuser selecionado e a instruoupdate="cidade"determina que oSelectOneMenude Cidade (id cidade) seja atualizado aps o mtodo ser executado. Este procedimento foi feito para trazer as cidades da UF selecionada; Linhas 43 a 45: insere um campocheckboxna pgina para determinar se o anncio tem preo fixo ou leilo; Linha 44: coloca outro componente para processamento AJAX na pgina. Pelo fato da instruo estar dentro do SelectBooleanCheckbox, o valor selecionado pelo usurio ser submetido paraAnuncioBean, atualizando o atributoprecoFixoda varivelanunciodoManaged Bean.A instruoupdate="valor"determina que oInputTextdo valor do anncio (id valor) seja atualizado aps a invocao do mtodosetPrecoFixo(). Este procedimento foi feito para determinar se o campo do valor deve ficar desabilitado ou no (a instruo disabled="#{!anuncioBean.anuncio.precoFixo}"no InputText define este comportamento); Linha 52: insere o componenteCaptchana pgina.Como mencionado anteriormente, temos nesta pgina o componente Captcha, que foi criado baseado no reCAPTCHA do Google. O servio de validao contraspamfornecido pela empresa norte-americana determina que sejam definidas uma chave pblica e uma privada para que seja possvel utilizar o componente. Ambas devem ser geradas nolinkque se encontra no final do artigo e, no caso do PrimeFaces, dois parmetros de contexto devem ser colocados noweb.xmlantes datagde fechamentopara informar estas chaves. Os parmetros so lidos e repassados em tempo de execuo para o reCAPTCHA.O trecho de cdigo daListagem 8traz dois exemplos de parmetros que serviro apenas para testes locais; portanto, se for colocar oCaptchado PrimeFaces no seu sistema, gere as chaves atravs do endereo indicado na seoLinkse substitua os valores daListagem 8no seuweb.xml.Listagem 8.Chaves pblica e privada a serem adicionadas no web.xml. primefaces.PUBLIC_CAPTCHA_KEY 6LdTufUSAAAAAOxnrayslEjsCiCNuvjpN72MMHgu primefaces.PRIVATE_CAPTCHA_KEY 6LdTufUSAAAAAFd7SHF8L0mkC4bHJXNrx6Pvnav4 Aps modificar o cdigo da pgina e oweb.xml, reinicie o WildFly, abra novamente a tela inicial do sistema, acesse o menuAnncioe clique na opoCadastrar Anncio. Na primeira tela do fluxo, clique no cone da colunaSelecionardo modelo desejado. AFigura 7exibe como ficou a pginacadastrarAnuncioPasso2.xhtml.

Figura 7. Tela para informar dados do anncio.Caso deseje, teste os processamentos AJAX existentes na seleo da UF e na marcao/desmarcao do campo que indica se o anncio tem preo fixo.Agora que verificamos o funcionamento da operao, vamos criar a ltima pgina do fluxo de cadastro de anncio que vai permitir ouploadde imagens do veculo.Antes, porm, precisamos adicionar dois mtodos na aplicao que sero responsveis pelo processamento dos arquivos que o usurio fizeruploadno sistema. O primeiro deles ser umlistenerchamado pelo componente deuploaddo PrimeFaces para processar a imagem enviada e, por este motivo, receber como parmetro uma instncia da classeFileUploadEvent, pertencente ao pacote org.primefaces.event. O segundo ser um mtodo privado criado para gravar a imagem em disco em uma subpasta de imagens_anuncios.Isto posto, para conseguirmos efetuar ouploaddas imagens no sistema, coloque o cdigo daListagem 9dentro deAnuncioBean.Listagem 9. Trecho de cdigo a ser adicionado na classe AnuncioBean.01public void processaArquivoDeAnuncio(FileUploadEvent event) {02 UploadedFile uf = event.getFile();03 ImagemAnuncio imagemAnuncio = new ImagemAnuncio();04 try {05 copiaArquivo(uf.getFileName(), uf, anuncio.getId());06 imagemAnuncio.setAnuncio(anuncio);07 imagemAnuncio.setNome(uf.getFileName());08 anuncioService.salvaImagemAnuncio(imagemAnuncio);09 FacesMessage fm = new FacesMessage();10 fm.setSummary("Sucesso ao enviar o(s) arquivo(s)");11 fm.setSeverity(FacesMessage.SEVERITY_INFO);12 FacesContext.getCurrentInstance().addMessage(null, fm);13 } catch (IOException e) {14 e.printStackTrace();15 FacesMessage fm = new FacesMessage();16 fm.setSummary("Erro ao enviar o(s) arquivo(s)");17 fm.setSeverity(FacesMessage.SEVERITY_ERROR);18 FacesContext.getCurrentInstance().addMessage(null, fm);19 }20}2122private static void copiaArquivo(String nomeDoArquivo, UploadedFile upload, Integer idAnuncio) throws IOException {23OutputStream out = null;24 InputStream is = null;25 String diretorioImagem = FacesContext.getCurrentInstance().getExternalContext().getRealPath("/imagens_anuncios");26 File diretorio = new File(diretorioImagem + File.separator + idAnuncio);27 diretorio.mkdir();28 try {29 is = upload.getInputstream();30 out = new FileOutputStream(new File(diretorio, nomeDoArquivo));31 int read = 0;32 byte[] bytes = new byte[1024];3334 while ((read = is.read(bytes)) != -1) {35 out.write(bytes, 0, read);36 }37} finally {38try {39 is.close();40 out.flush();41 out.close();42 } catch (IOException e) {43 e.printStackTrace();44 }45 }46}Depois de alterarmos a classeAnuncioBean, vamos gerar uma pgina chamadacadastrarAnuncioPasso3.xhtmldentro da pasta src/main/webapp.O seu cdigo apresentado naListagem 10, que tem como nico componente novo do PrimeFaces ainda no comentado no artigo, oFileUpload, que viabiliza duas opes de envio de arquivos para o servidor: utilizando ouploadnativo do navegador ou atravs de um componente poderoso elaborado pelos desenvolvedores da biblioteca que aceita, inclusive, operaes de arrastar e soltar.Listagem 10. Cdigo da pgina cadastrarAnuncioPasso3.xhtml. 01 02 08 09 10 11 12 13 14 15 16 17 Sucesso ao Cadastrar Anncio do #{modeloBean.modelo.marca.nome} #{modeloBean.modelo.nome} #{modeloBean.modelo.motorizacao} 18 Caso queira, faa o upload de imagens do seu anncio abaixo. 19 20 21 22 23 24 25 26 27 28 29 30 36 37 38 39 40 41 42 43 44 45 Os principais trechos do cdigo so: Linha 14: define que o formulrio deve enviar os dados codificados no formato multipart/form-data. Este procedimento necessrio no HTML quando existem componentes deupload; Linha 15: insere o componenteGrowlpara exibir mensagens criadas viaFacesMessage. Deve ser observado que ao gerarmos as mensagens no Managed Bean, especificamosnullcomo componente destino para que os informativos e erros no sejam mostrados tambm pelo componenteMessagesque est notemplate(veja as linhas 16 e 22 daListagem 9); Linha 30: define o componente deuploadde arquivos da pgina com as seguintes instrues relevantes:mode=advanceddetermina que no deve ser utilizado ouploadnativo do navegador; dragDropSupport="false"indicaque no ser possvel selecionar os arquivos atravs de operaes de arrastar e soltar; multiple="true"sinalizaque ser permitido enviar mais de um arquivo por vez; update=":form:msgsflutuantes", por sua vez, indica que o componenteGrowl(id msgsflutuantes) deve ser atualizado aps o processamento do envio para mostrar a mensagem de sucesso ou erro;sizeLimit=1048576determina que o tamanho mximo de cada arquivo enviado 1Mb (1048576 bytes);fileLimit=5indica que a quantidade mxima de arquivos enviadas por vez 5; e allowTypes=="/(\.|\/)(gif|jpe?g|png)$/"define que os tipos de extenses de imagens aceitas so gif, jpg, jpeg e png.Por fim, como dito anteriormente, a instruo fileUploadListener="#{anuncioBean.processaArquivoDeAnuncio}"especifica que o mtodoprocessaArquivoDeAnuncio(), deAnuncioBean, deve ser chamado para processar os arquivos enviados para o servidor.Aps a alterao no cdigo, reinicie o WildFly e abra novamente a tela inicial do sistema. Em seguida, acesse o menuAnncioe clique na opoCadastrar Anncio. Na primeira tela do fluxo, clique no cone da colunaSelecionardo modelo desejado e na segunda tela informe os dados do seu anncio. AFigura 8exibe como ficou a terceira pgina da operao.

Figura 8. Tela para realizaruploadde imagens do veculo do anncio.Caso queira testar ouploaddos arquivos, clique emPesquisar, selecione imagens no seu computador na caixa de dilogo que aparece e clique emEnviarpara finalizar a operao. Do contrrio, clique emIr para Pgina Inicialpara pular este passo.Agora que temos o fluxo de cadastro de anncio completo, precisamos de mais duas operaes no sistema: listar os anncios cadastrados e visualizar um anncio para compra. Vamos partir para a primeira delas. Sendo assim, crie uma pgina chamadalistarAnuncios.xhtmlna pastasrc/main/webappe deixe o cdigo igual ao daListagem 11.Listagem 11. Cdigo da pgina listarAnuncios.xhtml. 01 02 08 09 10 11 12 13 14 15 Listar Anncios 16 Selecione o anncio desejado. 17 18 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 Como pode ser observado na pgina de listagem de anncios no existem componentes novos do PrimeFaces e nem trechos de cdigo que precisem de uma explicao para melhor entendimento. O objetivo da pgina apenas permitir que o usurio selecione o modelo desejado para listar os anncios vinculados a ele.AFigura 9exibe como ficou a tela, acessada atravs do menuAnncio, opoListar Anncios.

Figura 9. Tela de seleo do modelo para listar os anncios vinculados a ele.Nossa ltima pgina ser a de visualizao de um anncio. Para cri-la, emsrc/main/webappvamos gerar o arquivo detalharAnuncio.xhtml e implementar seu cdigo conforme aListagem 12.Alm de outrastagsexistentes na pgina, os componentes novos do PrimeFaces naListagem 12que ainda no foram comentados no artigo so:Galleria: exibe um conjunto de imagens no formato de uma galeria. O componente deve receber umaCollectioncomo parmetro;Effect: dispara um efeito em um determinado componente a partir de alguma ao executada. Entre as opes esto piscar, sumir, explodir, entre outras;Poll: utilizado para executar requisies AJAX periodicamente, o componente bastante til em situaes que preciso verificar se houve alguma alterao noback-endda aplicao.Listagem 12. Cdigo da pgina detalharAnuncio.xhtml. 01 02 08 09 10 11 12 13 14 #{anuncioBean.anuncio.titulo} 15 16 17 18 19 20 21 22 24 25 26 27 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 Os principais trechos do cdigo so: Linhas 16 a 18: insere o componenteGalleriana pgina para exibir as imagens do anncio, caso tenham sido enviada s imagens do veculo. Observe a chamada agetImagensComoLista()na linha 16. Este mtodo foi criado para que o componente receba uma Collection como retorno. Os atributos panelWidthepanelHeight especificam a largura e a altura da galeria; Linhas 22 a 25: adiciona um boto na pgina para comprar o veculo, caso o anncio seja do tipo preo fixo. As principais instrues colocadas no componente so: actionListener="#{anuncioBean.efetuaCompra}", que indica que o mtodoefetuaCompra()deAnuncioBeandeve ser executado quando o boto for clicado;update="painelCompra", que sinaliza que adivem que o boto est inserido deve ser atualizada para exibir que o carro foi comprado (a linha 24 tem umOutputTextpara este caso); eglobal="false", que especifica que o componente de status no deve ser mostrado nesta requisio AJAX (lembre-se que colocamos um componenteAjaxStatusnotemplatedo sistema); Linha 24: define uma ao de confirmao para a compra do veculo atravs do componenteConfirm; Linhas 27 a 30: adiciona outro boto na pgina para dar lance no anncio, caso a venda seja do tipo leilo. As principais instrues colocadas no componente so: actionListener="#{anuncioBean.efetuaLance}", que indica que o mtodoefetuaLance()deAnuncioBeandeve ser executado quando o boto for clicado;update="agrupamentoValor", que determina que ospanque mostra o valor do ltimo lance deve ser atualizado para exibir o novo preo; e aglobal="false", que