Documente Academic
Documente Profesional
Documente Cultură
grande
possibilidade
do
responsvel
pela
definio
da
Neste
contexto,
frameworks
RIA,
como
os
comentados
agradvel
para
usurio,
possibilidade
de
executar
conhecermos
frameworks,
este
de
artigo
forma
mais
explorar
aprofundada
o
PrimeFaces
um
destes
5,
lanado
assncrono
mais
popular
do
Java.
Entre
as
O PrimeFaces 5
Em 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:
de
acesso
uma
rea
com
contedo
exclusivo
Criando a aplicao
Como 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 de controller caber ao JSF 2.2, e o Facelets ser utilizado para
gerao de templates na 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 seo Links no final do artigo para saber onde baix-los):
no Artifact
Id o
valor
leilaojm,
no
Logo aps, vamos configurar nosso projeto para utilizar o JSF 2.2 e
informar alguns
parmetros
adicionais
Library
Configuration;
no
campo URL
Mapping
Feito
no popup que
item Project
Facets,
precisamos
configurar
este
parmetro
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
Modificando o pom.xml
Chegamos ao ponto em que necessrio configurar as bibliotecas
utilizadas pelo projeto no arquivo pom.xml. Deste modo, abra o XML
e selecione a aba pom.xml para editar o cdigo fonte, que deve ficar
semelhante ao da Listagem 2.
Listagem 2. Cdigo do arquivo pom.xml.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>br.com.javamagazine</groupId>
<artifactId>leilaojm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>leilaojm</name>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Bibliotecas Java EE 7 que j esto no Wildfly, incluindo o
JSF
-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>5.0</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.tomahawk</groupId>
<artifactId>tomahawk21</artifactId>
<version>1.1.14</version>
</dependency>
</dependencies>
</project>
Nome do projeto;
JDK
1.7
ser
usado
que
ele
deve
constar
no classpath da aplicao;
no
arquivo
completo
que
est
na
precisamos
baixar
o driver do
PostgreSQL
(confira
estrutura
de
Nessa
mesma
pasta,
gere
um
arquivo
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
dentro
de <subsystem
Configurando a JPA
Para inserirmos a Java Persistence API em nosso projeto, necessrio
primeiramente criarmos o XML de configurao da biblioteca. Deste
modo,
clique
com
boto
direito
em src/main/resources,
da
pasta
apresentada,
campo File
Executados
criada,
selecione New e
name informe
esses
depois Other.
File e
persistence.xml
passos,
modifique
clique
e
tela
em Next.
No
clique
Na
cdigo
em Finish.
gerado
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="leilaoPU" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/leilaoDS</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.PostgreSQLDialect" />
</properties>
</persistence-unit>
</persistence>
Observe
que
na
linha
5 definimos
pela
classe HibernatePersistence.
Na
linha
de
dados
nas
telas.
No
nosso
caso
sero
cinco:
Para
informe
em Package o
valor
clique
no
boto Finish.
Um
cdigo
inicial
ser
gerado
7 (lembre-se
de
inserir
os
gets,
ao
da Listagem
8 (lembre-se
de
inserir
os
gets,
import javax.persistence.*;
@Dependent
@Entity
public 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
}
anotao
do
que
escopo
de
requisio
que
iremos
criar
posteriormente);
Definio
que
valor
do
atributo id ser
gerado
na
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 da Listagem 9 (lembrese novamente de inserir os gets, sets, equals() e hashCode()).
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
@Entity
public 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<Avaliacao> listaAvaliacoes = new
ArrayList<Avaliacao>();
// gets e sets omitidos
// equals() e hashCode() omitidos
}
Anotao
do
injetarmos
define
que
valor
do
atributo id deve
ser
gerado
modelo
com
vrias
10 (mais
uma
vez,
implemente
os
gets,
coluna id_modelo.
instruo
muitos
com ImagemAnuncio,
expressa
pelo
transforma
List<ImagemAnuncio>
em
uma
do
PrimeFaces
5,
como
veremos
na
continuao do artigo.
Como vimos, a classe Anuncio tem uma lista de ImagemAnuncio.
Esta relao foi criada para que o usurio possa efetuar o upload de
imagens dos produtos venda. Neste ponto, voc deve lembrar que
comentamos sobre alguns inserts que haviam no script de criao das
tabelas no banco de dados. Entre estes inserts, vrios deles se
referiam a nomes de arquivos de imagens que so colocados na
tabela imagem_anuncio quando
rodamos
o script.
Alm
destas
figuras
esto
dentro
das
pastas src/webapp/imagens e
outras,
ela
dever
ser
criada
no
pacote
@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
}
JPA assumir
atravs
da
sequence
imagem_anuncio_id_seq no banco;
que
imagem_anuncio ser
id_anuncio.
chave
estrangeira
mapeada
pela
na
tabela
coluna
Criando os EJBs
Em 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 ser ModeloService. Para cri-lo, clique com o boto direito
em cima do projeto, selecione New e depois clique em Class. Na tela
que
surge,
informe
em Package o
br.com.javamagazine.leilaojm.ejb,
valor
em Name informe
Anotao @PersistenceContext da
JPA
injeta
um datasource)
para
podermos
realizar
as
Invoca
Este
Cria
um
objeto
do
tipo Query a
createQuery() do EntityManager.
partir
A
do
mtodo
classe
Query
Mtodo getResultList() da
classe Query
chamado
}
}
objeto
passado).
Alm
deles,
invocamos
substitua
cdigo
entityManager.persist(anuncio);
}
public void salvaImagemAnuncio(ImagemAnuncio imagemAnuncio) {
entityManager.persist(imagemAnuncio);
}
public void atualizaAnuncio(Anuncio anuncio) {
entityManager.merge(anuncio);
}
@SuppressWarnings("unchecked")
public List<Anuncio> listaAnuncios() {
Query query = entityManager.createQuery("Select a from Anuncio a
order by a.titulo");
return query.getResultList();
}
@SuppressWarnings("unchecked")
public List<Anuncio> listaAnunciosDoModelo(Integer idModelo) {
Query query = entityManager.createQuery("Select a from Anuncio a
where a.modelo.id = :idModelo");
query.setParameter("idModelo", idModelo);
return query.getResultList();
}
}
EntityManager.
nica
novidade
est
na
classe
invocao
do
criado
no
de
inserir
os
gets
sets
de
modelo,
via
expression
language
(como
no
foi
Com
que
EJB
CDI
instanciar
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
}
classe AvaliacaoBean,
permitindo
que
semelhante
ao
da Listagem
15,
portanto
no
so
ser AnuncioBean.
Ele
terceiro Managed
Bean da
aplicao
na
tela
de
cadastro
de
anncio.
da Listagem
18 (lembre-se
de
inserir
get
set
de graficoNumeroAnuncios).
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
@RequestScoped
public 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<Anuncio> anuncios =
anuncioService.listaAnunciosDoModelo(modeloBean.getModelo().getId());
Map<Integer, Integer> mapaAnunciosPorAno =
agrupaNumeroAnunciosPorAnoModelo(anuncios);
series1.setLabel(modeloBean.getModelo().getNome());
Set<Integer> chaves = mapaAnunciosPorAno.keySet();
for (Integer chave : chaves) {
series1.set(chave, mapaAnunciosPorAno.get(chave));
}
model.addSeries(series1);
return model;
}
private Map<Integer, Integer>
agrupaNumeroAnunciosPorAnoModelo(List<Anuncio> anuncios) {
Map<Integer, Integer> anunciosPorAnoModelo = new HashMap<Integer,
Integer>();
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
}
implementa
mtodo preencheDadosSeries(),
que
contidas
no Map so
os
anos
dos
modelos
entre
os
anncios
as
respectivas
implementa agrupaNumeroAnunciosPorAnoModelo(),
que rene os anncios por ano do modelo e calcula a
respectiva quantidade de anncios;
na Listagem
19 e
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();
}
}
coeso
uma
desacoplado.
leitura
mais
Todas
simples
estas
das
caractersticas
classes
uma
Criando um sistema de
leilo de veculos em Java
Parte 2
Confira neste artigo como desenvolver um sistema de leilo de veculos e conhea os
principais componentes do framework RIA para JSF mais popular do mercado.
semelhantes
encontradas
pelos
desenvolvedores
na
os
principais
recursos
que
iremos
utilizar,
esto
remodelados
na
verso
do
criao
de
menus
Criando o template
A primeira estrutura que iremos criar o template geral das pginas
do sistema, utilizando para isso o framework Facelets, uma linguagem
de descrio de pginas voltada especificamente para JSF.
O template servir para definirmos alguns trechos comuns a todas as
pginas do sistema (como o menu e o componente de status das
requisies AJAX) e nos permitir codificar apenas o corpo interno
das outras telas.
Desta
forma,
clique
com
boto
direito
em
cima
MenuItem:
componente
genrico
que
pode
ser
como
um link no
menu
dentro
do
Submenu:
adiciona
um
menu
hierrquico
um
html
PUBLIC
"-//W3C//DTD
XHTML
1.0
Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Leilo JM</title>
</h:head>
<h:body>
<ui:insert name="menu">
<h:form>
<p:menubar>
<p:menuitem
value="Home"
action="index.xhtml?faces-
value="Cadastrar
Anncio"
action="#{modeloBean.listaModelosParaAnuncio}"
ajax="false" />
<p:menuitem
value="Listar
action="#{anuncioBean.listaAnunciosCadastrados}"
ajax="false" />
</p:submenu>
</p:menubar>
</h:form>
</ui:insert>
<p:messages id="mensagens" />
Anncios"
<p:dialog
widgetVar="statusDialog"
modal="true"
draggable="false"
closable="false" resizable="false" showHeader="false">
<p:graphicImage value="/imagens/carregando.gif" width="100" />
</p:dialog>
<p:ajaxStatus
onstart="PF('statusDialog').show()"
onsuccess="PF('statusDialog').hide()" />
<ui:insert name="corpo" />
</h:body>
</html>
barra
de
ajax=false configura
menu.
a
ao
disparada
instruo
no
clique
est
sendo
executado.
o
atributo
O
name
atravs
do
componente AjaxStatus,
notificamos
colocamos
uma
instruo
para
que
requisies
AJAX.
no
adicionamos
outro
componente <ui:insert
/> como
html
PUBLIC
"-//W3C//DTD
XHTML
1.0
Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<h2>Bem vindo. Escolha sua opo no menu acima.</h2>
</ui:define>
</ui:composition>
</html>
no
cdigo
que
indicamos
pgina
layoutBase.xhtml
da
instruo
template=layoutBase.xhtml.
Aps inserimos a instruo <ui:define />, que indica que estamos
redefinindo um trecho criado com <ui:insert />. Neste caso, o
<ui:insert name=corpo /> 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 seo Links h um post do
blog do autor em que possvel ver como realizar esta etapa.
entre
todas
as tags,
os
seguintes
componentes
do
determinado
pelo
atributo columns.
Possui
verso
mscaras,
do
para
PrimeFaces
que
recebeu
valor
digitado
suporte
obedea
um pattern;
html
PUBLIC
"-//W3C//DTD
XHTML
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:t="http://myfaces.apache.org/tomahawk">
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{modeloBean.modelo}" />
1.0
Strict//EN"
<h2>Cadastrar Modelo</h2>
29
30
<p:panelGrid columns="3">
31
32
required="true"
requiredMessage="Campo nome obrigatrio" />
33
34
35
<p:selectOneMenu
id="marca"
value="#{modeloBean.modelo.marca}"
var="m" converter="marcaConverter"
required="true" requiredMessage="Campo marca
obrigatrio">
37
<f:selectItems value="#{modeloBean.listaMarcas}"
var="marca"
itemLabel="#{marca.nome}" itemValue="#{marca}" />
38
39
<p:column>
40
<p:graphicImage value="/imagens/logos/#{m.imagem}"
width="40" />
41
</p:column>
42
<p:column>
43
44
</p:column>
45
</p:selectOneMenu>
46
47
48
49
<p:column>
50
<p:inputText
id="motorizacao"
value="#{modeloBean.modelo.motorizacao}" required="true"
requiredMessage="Campo motorizao obrigatrio"
title="Exemplos: 1.0, 1.3, 1.5 turbo" />
51
<p:tooltip
id="tooltip"
for="motorizacao"
</p:column>
53
54
55
<p:outputLabel
for="qtdPassageiros"
value="Qtd.
Passageiros" />
56
<p:column>
57
passageiros" />
58
<h:inputHidden
id="qtdPassageiros"
value="#{modeloBean.modelo.qtdPassageiros}" />
59
<p:slider
id="qtdPassageirosSlider"
display="qtdPassageirosOutput" for="qtdPassageiros"
minValue="2" maxValue="7" displayTemplate="{value}
passageiros" />
60
</p:column>
61
62
63
<p:outputLabel for="dataLancamento"
value="Data de
Lanamento" />
64
yearRange="c-100:c+1" />
65
66
67
68
69
</h:form>
70
</ui:define>
71
</ui:composition>
72 </html>
Bean antes
de
chamarmos
mtodo
cadastraModelo().
Uma soluo para este problema seria utilizarmos o escopo de viso
(@ViewScoped)
do
JSF, mas
como
preferimos
escopo
de
que
componente
o OutputLabel est
associado;
Linhas 32 e 50: insere campos de entrada de texto InputText;
Linha 33, 46, 53, 61 e 65: define um componente Message para
cada componente de entrada de dados (observe o atributo for que
faz esta ligao). Eles foram colocados para exibir mensagens de erro
caso
qualquer
um
dos
componentes
de
entrada
de
no
dados
esteja
neste
componente
que
estamos
utilizando
ou
que
ele
no
pode
aceitar
manualmente
(readOnlyInput=true),
entrada
que
de
dados
usurio
pode
padro
de
data
(pattern=dd/MM/yyyy),
segue
formato
que
idioma
dia,
ms
utilizado
deve
ano
ser
Criando
as
pginas
cadastrar/listar avaliaes
Nosso
prximo
passo
ser
criar
as
pginas
para
do
fluxo
de
este
motivo,
teremos
que
gerar
dois
arquivos
XHTML.
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:f="http://java.sun.com/jsf/core"
05
xmlns:p="http://primefaces.org/ui"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
08
xmlns:t="http://myfaces.apache.org/tomahawk">
09
10
<ui:composition template="layoutBase.xhtml">
11
<ui:define name="corpo">
12
13
14
15
<h:form id="form">
16
<h2>Cadastrar/Listar Avaliaes</h2>
17
avaliaes.</h4>
18
19
<p:carousel
value="#{modeloBean.listaModelos}"
headerText="Modelos" var="m">
20
<p:panelGrid
columns="2"
style="width:
100%"
cellpadding="5">
21
<f:facet name="header">
22
<p:commandLink
oncomplete="PF('boxvideo').show();" ajax="true"
update=":form:boxvideo"
<p:graphicImage value="/imagens/filme.png"
width="40"
title="Ver Filme de Divulgao" />
24
<f:setPropertyActionListener
</p:commandLink>
26
<p:graphicImage
value="/imagens/logos/#{m.marca.imagem}"
title="#{m.marca.nome}" height="40" />
27
</f:facet>
28
29
<h:commandLink
style="font-weight:
bold"
value="#{m.nome}"
action="#{avaliacaoBean.listaAvaliacoesDoModelo}">
31
<f:setPropertyActionListener
</h:commandLink>
33
34
35
36
37
38
39
40
41
42
43
44
<h:outputText value="#{m.dataLancamento}">
45
46
</h:outputText>
47
</p:panelGrid>
48
49
<f:facet name="footer">
50
<h:outputText
value="Total
#{fn:length(modeloBean.listaModelos)}" />
51
</f:facet>
52
</p:carousel>
53
54
de
modelos:
55
<f:facet name="inline">
56
<p:media
value="#{modeloBean.modelo.linkVideo}"
</f:facet>
58
</p:lightBox>
59
</h:form>
60
</ui:define>
61
</ui:composition>
62 </html>
do
veculo
possui
um
vdeo
de
divulgao.
que
logo
aps
atualizao
instruo update=:form:boxvideo;
da div realizada
pela
determine
que
ela
seja
mostrada.
crie
pasta src/main/webapp e
altere
cdigo
gerado
pelo
da
Eclipse,
elemento
que
funciona
em
conjunto
com
insere
exibida
para que
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:f="http://java.sun.com/jsf/core"
05
xmlns:p="http://primefaces.org/ui"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
11
12
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{modeloBean.modelo}" />
13
<h:form id="form">
14
15
16
<h2>Listar Avaliaes</h2>
17
<h4>Avaliaes
do
modelo
#{modeloBean.modelo.nome}
#{modeloBean.modelo.motorizacao}</h4>
18
19
widgetVar="painelAvaliacao"
toggleable="true" collapsed="true">
20
21
22
23
24
<p:editor
id="opiniao"
value="#{avaliacaoBean.avaliacao.texto}" />
26
27
update="@form"
oncomplete="PF('painelAvaliacao').toggle();" />
28
29
</h:panelGrid>
</p:panel>
30
31
<br />
32
33
34
<h:outputText
value="Nenhuma
avaliao
cadastrada"
rendered="#{empty
modeloBean.modelo.listaAvaliacoes}" />
35
<p:dataScroller
empty
modeloBean.modelo.listaAvaliacoes}">
36
37
38
<h:outputText
style="font-weight:
bold"
value="#{a.nome}" />
39
ajax="true" update="@form">
40
<f:setPropertyActionListener
<p:graphicImage value="/imagens/excluir.png"
</p:commandLink>
44
</h:panelGroup>
45
46
47
</p:panelGrid>
48
<p:separator />
49
</p:dataScroller>
50
51
<p:confirmDialog global="true">
52
<p:commandButton
value="Sim"
type="button"
value="No"
type="button"
styleClass="ui-confirmdialog-yes"
icon="ui-icon-check" />
53
<p:commandButton
styleClass="ui-confirmdialog-no"
icon="ui-icon-close" />
54
</p:confirmDialog>
55
</h:form>
56
</ui:define>
57
</ui:composition>
58 </html>
estado
dos
Os
respectivamente,
cabealho
mensagem
que
Linha
46:
mostra
texto
da
avaliao.
Observe
atributo escape com o valor false. 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 componente Separator;
Linhas 51 a 54: define a div flutuante a ser exibida pedindo a
confirmao do usurio quando ele clicar no CommandLink de
excluso da avaliao. Pelo fato de CommandLink poder ter mais de
uma ocorrncia na pgina (ser exibido em cada avaliao),
precisamos colocar o atributo global=true para 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 menu Modelos de Carros
> Cadastrar/Listar Avaliaes, e clique em uma das opes para
poder gravar uma avaliao e visualizar as j cadastradas. A Figura
5 exibe como ficou a pgina listarAvaliacoesPasso2.xhtml.
tambm
assim,
crie
primeira
das
nossas
pginas,
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:f="http://java.sun.com/jsf/core"
05
xmlns:p="http://primefaces.org/ui"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
11
12
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{modeloBean.modelo}" />
<t:saveState value="#{modeloBean.listaModelos}" />
13
14
<h:form id="form">
15
<h2>Cadastrar Anncio</h2>
16
17
18
<p:dataTable id="listaModelos"
value="#{modeloBean.listaModelos}" var="m"
19
paginator="true"
paginatorPosition="bottom"
20
paginatorTemplate="{CurrentPageReport} {FirstPageLink}
{PreviousPageLink} {PageLinks}
{NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
21
currentPageReportTemplate="({currentPage} de
{totalPages})">
22
23
<p:graphicImage
value="/imagens/logos/#{m.marca.imagem}"
title="#{m.marca.nome}" height="40" />
24
</p:column>
25
<p:column headerText="Nome">
26
value="#{m.nome}" />
27
</p:column>
28
<p:column headerText="Marca">
29
30
</p:column>
31
<p:column headerText="Motorizao">
32
33
</p:column>
34
35
36
</p:column>
37
38
<h:outputText value="#{m.dataLancamento}">
39
40
</h:outputText>
41
</p:column>
42
center">
43
<p:commandLink action="cadastrarAnuncioPasso2.xhtml"
ajax="false">
44
<f:setPropertyActionListener
<p:graphicImage value="/imagens/selecionar.png"
</p:commandLink>
47
</p:column>
48
</p:dataTable>
49
</h:form>
50
</ui:define>
51
</ui:composition>
52 </html>
mensagem
deve
ser
mostrada
se
no
houver
dados
pgina; paginatorPosition,
que
determina
posio
do
passo.
Sendo
assim,
gere
uma
pgina
chamada
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:p="http://primefaces.org/ui"
05
xmlns:f="http://java.sun.com/jsf/core"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
11
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{modeloBean.modelo}" />
12
13
14
15
16
<h:form id="form">
<h2>Cadastrar Anncio de #{modeloBean.modelo.marca.nome}
#{modeloBean.modelo.nome}
#{modeloBean.modelo.motorizacao}</h2>
17
18
19
20
21
<p:inputText id="titulo"
value="#{anuncioBean.anuncio.titulo}" />
22
23
24
25
/>
26
<p:inputMask id="anoFabricacao"
28
<p:inputMask id="anoModelo"
31
<p:selectOneMenu id="uf"
value="#{anuncioBean.anuncio.uf}">
32
33
34
<p:ajax update="cidade"
listener="#{anuncioBean.atualizaCidadesPelaUF}" />
35
</p:selectOneMenu>
36
37
<p:selectOneMenu id="cidade"
value="#{anuncioBean.anuncio.cidade}">
38
39
40
</p:selectOneMenu>
41
42
43
<p:selectBooleanCheckbox id="precoFixo"
value="#{anuncioBean.anuncio.precoFixo}">
44
45
</p:selectBooleanCheckbox>
46
47
<p:inputText id="valor"
value="#{anuncioBean.anuncio.valor}"
disabled="#{!anuncioBean.anuncio.precoFixo}" />
48
</h:panelGrid>
49
50
<p:editor id="descricao"
obrigatrio" />
53
54
<p:commandButton value="Cadastrar"
</h:form>
56
</ui:define>
57
</ui:composition>
58 </html>
que
ser
que
o SelectOneMenu de
Pelo
fato
da
instruo
estar
dentro
do
(id
valor)
seja
atualizado
aps
invocao
do
indicado
na
seo Links e
substitua
os
valores
classe FileUploadEvent,
pertencente
ao
pacote
gravar
imagem
em
disco
em
uma
subpasta
de
imagens_anuncios.
Isto posto, para conseguirmos efetuar o upload das imagens no
sistema, coloque o cdigo da Listagem 9 dentro de AnuncioBean.
Listagem
9.
Trecho
de
cdigo
ser
adicionado
na
classe
AnuncioBean.
01
02
UploadedFile uf = event.getFile();
03
04
try {
05
06
imagemAnuncio.setAnuncio(anuncio);
07
imagemAnuncio.setNome(uf.getFileName());
08
anuncioService.salvaImagemAnuncio(imagemAnuncio);
09
10
11
fm.setSeverity(FacesMessage.SEVERITY_INFO);
12
FacesContext.getCurrentInstance().addMessage(null, fm);
13
} catch (IOException e) {
14
e.printStackTrace();
15
16
17
fm.setSeverity(FacesMessage.SEVERITY_ERROR);
18
FacesContext.getCurrentInstance().addMessage(null, fm);
19
20
21
22
24
InputStream is = null;
25
String diretorioImagem =
FacesContext.getCurrentInstance().getExternalContext().getRealPath("/i
magens_anuncios");
26
idAnuncio);
27
diretorio.mkdir();
28
try {
29
is = upload.getInputstream();
30
nomeDoArquivo));
31
int read = 0;
32
33
34
35
out.write(bytes, 0, read);
36
37
} finally {
38
try {
39
is.close();
40
out.flush();
41
out.close();
42
} catch (IOException e) {
43
e.printStackTrace();
44
45
46
da
pasta
src/main/webapp.
O seu cdigo apresentado na Listagem 10, que tem como nico
componente novo do PrimeFaces ainda no comentado no artigo,
o FileUpload, que viabiliza duas opes de envio de arquivos para o
servidor: utilizando o upload nativo 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 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
02 <html xmlns="http://www.w3.org/1999/xhtml"
03
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:p="http://primefaces.org/ui"
05
xmlns:f="http://java.sun.com/jsf/core"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
11
12
13
14
15
16
17
#{modeloBean.modelo.marca.nome}
#{modeloBean.modelo.nome}
#{modeloBean.modelo.motorizacao}</h2>
18
abaixo.</h4>
19
20
<p:panelGrid columns="4">
21
22
value="#{anuncioBean.anuncio.titulo}" />
23
24
25
value="#{anuncioBean.anuncio.anoFabricacao}/#{anuncioBean.anuncio.anoM
odelo}" />
26
</p:panelGrid>
27
28
29
30
<p:fileUpload
fileUploadListener="#{anuncioBean.processaArquivoDeAnuncio}"
31
mode="advanced" dragDropSupport="false"
multiple="true" update=":form:msgsflutuantes"
32
(gif|jpe?g|png)$/"
33
uploadLabel="Enviar" cancelLabel="Cancelar"
label="Pesquisar"
34
permitido."
35
arquivos." />
36
</h:form>
37
38
39
40
<h:form>
41
</h:form>
43
</ui:define>
44
</ui:composition>
45 </html>
as
seguintes
o upload nativo
instrues
que
no
do
deve
ser
navegador;
arquivos
atravs
de
operaes
de
arrastar
soltar;
sucesso
tamanho
ou
mximo
de
cada
arquivo
enviado
1Mb
que
(1048576
fim,
como
dito
anteriormente,
instruo
fileUploadListener="#{anuncioBean.processaArquivoDeAnunc
io}" especifica
que
mtodo processaArquivoDeAnuncio(),
primeira
delas.
Sendo
assim,
crie
uma
pgina
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:f="http://java.sun.com/jsf/core"
05
xmlns:p="http://primefaces.org/ui"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
11
12
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{anuncioBean.anuncio}" />
<t:saveState value="#{anuncioBean.listaAnuncios}" />
13
14
<h:form id="form">
15
<h2>Listar Anncios</h2>
16
17
18
<p:dataTable id="listaAnuncios"
value="#{anuncioBean.listaAnuncios}" var="a"
19
20
21
paginatorTemplate="{CurrentPageReport} {FirstPageLink}
{PreviousPageLink}
{PageLinks} {NextPageLink}
{LastPageLink} {RowsPerPageDropdown}"
22
currentPageReportTemplate="({currentPage} de
{totalPages})">
23
24
<p:graphicImage value="/imagens_anuncios/sem-imagem.jpg"
rendered="#{empty a.imagensAnuncio}" height="40" />
25
<p:graphicImage
value="/imagens_anuncios/#{a.id}/#{a.imagensAnuncio[0].nome}"
rendered="#{not empty a.imagensAnuncio}" height="40" />
26
27
</p:column>
<p:column headerText="Produto">
28
value="#{a.titulo}" />
29
</p:column>
30
31
32
33
34
<h:outputText
value="#{a.anoFabricacao}/#{a.anoModelo}" />
35
</p:column>
36
37
<p:graphicImage value="/imagens/preco-fixo.png"
title="Preo Fixo" rendered="#{a.precoFixo}" height="40"
/>
38
<p:graphicImage value="/imagens/leilao.png"
title="Leilo"
rendered="#{!a.precoFixo}" height="40" />
39
40
</p:column>
<p:column headerText="Preo Atual">
41
value="#{a.precoFixo ?
a.valor : a.valorLanceAtual}">
42
locale="pt_BR"
maxFractionDigits="2" minFractionDigits="2" />
43
</h:outputText>
44
</p:column>
45
center">
46
ajax="false">
<p:commandLink action="detalharAnuncio.xhtml"
47
<f:setPropertyActionListener
<p:graphicImage value="/imagens/selecionar.png"
</p:commandLink>
50
</p:column>
51
</p:dataTable>
52
</h:form>
53
</ui:define>
54
</ui:composition>
55 </html>
9 exibe
como
ficou
tela,
acessada
atravs
do
em src/main/webapp vamos
detalharAnuncio.xhtml
gerar
implementar
seu
o
cdigo
arquivo
conforme
a Listagem 12.
Alm de outras tags existentes na pgina, os componentes novos do
PrimeFaces na Listagem 12 que ainda no foram comentados no
artigo so:
Galleria: exibe um conjunto de imagens no formato de uma
galeria.
componente
deve
receber
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 no back-end da aplicao.
Listagem 12. Cdigo da pgina detalharAnuncio.xhtml.
01 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
02 <html xmlns="http://www.w3.org/1999/xhtml"
03
xmlns:h="http://java.sun.com/jsf/html"
04
xmlns:f="http://java.sun.com/jsf/core"
05
xmlns:p="http://primefaces.org/ui"
06
xmlns:ui="http://java.sun.com/jsf/facelets"
07
xmlns:t="http://myfaces.apache.org/tomahawk">
08
09
10
11
<ui:composition template="layoutBase.xhtml">
<ui:define name="corpo">
<t:saveState value="#{anuncioBean.anuncio}" />
12
13
14
15
<h:form id="form">
<h2>#{anuncioBean.anuncio.titulo}</h2>
16
<p:galleria var="img"
value="#{anuncioBean.anuncio.imagensComoListaDeStrings}"
panelWidth="500" panelHeight="313"
rendered="#{not empty
anuncioBean.anuncio.imagensAnuncio}">
17
<p:graphicImage
value="/imagens_anuncios/#{anuncioBean.anuncio.id}/#{img}"
alt="#{img}" title="#{img}" width="500" />
18
19
</p:galleria>
<p:graphicImage value="/imagens/sem_imagens.jpg"
height="220"
rendered="#{empty anuncioBean.anuncio.imagensAnuncio}" />
20
21
style="margin-top: 15px;">
22
<p:commandButton value="Comprar"
rendered="#{anuncioBean.anuncio.precoFixo
and !anuncioBean.anuncio.vendido}"
actionListener="#{anuncioBean.efetuaCompra}"
23
update="painelCompra" global="false">
24
</p:commandButton>
26
color: red"
rendered="#{anuncioBean.anuncio.precoFixo
and anuncioBean.anuncio.vendido}" />
27
anuncioBean.anuncio.precoFixo}"
actionListener="#{anuncioBean.efetuaLance}"
28
update="agrupamentoValor" global="false">
29
for="painelValor" />
30
31
</p:commandButton>
</h:panelGroup>
32
33
34
<h:panelGrid columns="2">
<p:panelGrid columns="6" id="painelDetalhes">
35
36
value="#{anuncioBean.anuncio.modelo.marca.nome}
#{anuncioBean.anuncio.modelo.nome}" />
37
38
39
40
value="#{anuncioBean.anuncio.anoFabricacao} /
#{anuncioBean.anuncio.anoModelo}" />
41
42
value="#{anuncioBean.anuncio.uf}" />
43
44
value="#{anuncioBean.anuncio.cidade}" />
45
46
47
</p:panelGrid>
48
49
'Valor Atual'}">
50
<h:panelGroup id="agrupamentoValor">
51
value="#{anuncioBean.anuncio.precoFixo ?
anuncioBean.anuncio.valor :
anuncioBean.anuncio.valorLanceAtual}">
52
locale="pt_BR"
maxFractionDigits="2" minFractionDigits="2" />
53
54
</h:outputText>
</h:panelGroup>
55
</p:panel>
56
</h:panelGrid>
57
58
59
<p:confirmDialog global="true">
<p:commandButton value="Sim" type="button"
styleClass="ui-confirmdialog-yes"
icon="ui-icon-check" />
60
styleClass="ui-confirmdialog-no"
icon="ui-icon-close" />
61
62
</p:confirmDialog>
63
global="false"
rendered="#{!anuncioBean.anuncio.precoFixo}" />
64
</h:form>
65
</ui:define>
66
</ui:composition>
67 </html>
colocadas
no
componente
actionListener="#{anuncioBean.efetuaCompra}",
que
so:
que
indica
ser
(lembre-se
que
colocamos
um
no
componente
so:
ser
executado
Linha
63:
se
componente
for
do
tipo
leilo
rendered=#{!anuncioBean.anuncio.precoFixo}),
(instruo
coloca
do
anncio
ver
efeito
de
tremida
disparado
pelo