Você está na página 1de 286

JAVA Level 2

11-4427-4579
11-9903-3218
Sobre o autor

Prof. Nelson Goncalves


, de Oliveira

,
Cientista da Computacão pelo IMES-SCS,
,
Especialista em Telecomunicacões pela
FAAP-SP, mestrando em ciência da
,
computacão pela UFAbc-sp.

Iniciou a carreira como desenvolvedor de


software em 1987, especializando-se em
COBOL para Mainframes IBM.

Professor universitário Desde 2000,


leciona diversas disciplinas nos cursos de
,
Ciência da Computacão e Informática.

fundou a Grande Porte em 2008 com o


objetivo de difundir essa experiência para
nelson@grandeporte.com.br o mercado.

“o número de aplicacões web só aumenta.


com java é possível desenvolver
aplicacões robustas de forma simples e
rápida. Saber fazê-lo abrirá várias portas
no mercado de trabalho.”

Versão 2.1.1 – PDF liberado em 13/07/2015

Fique atento para novas versões em nosso site.


Parte

É uma plataforma de programação para


servidores na linguagem de programação Java,
fornece uma API e um ambiente de tempo de
execução para o desenvolvimento e execução de
softwares corporativos, incluindo serviços de
rede e web, e outras aplicações de rede de larga
escala, multicamadas, escaláveis, confiáveis e
seguras.
Versão 2.1.1
Parte 1 3

1
Preparation

Trocando Ideias É agora que você fala !!

Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na


capa desta parte. Isso é importante para que seu instrutor e seus colegas
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe ?


 O que você não sabe ?
 Porque é importante conhecer estes tópicos ?
 Quais são os seus temores ?
 O que você considera difícil ?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


4 Parte 1

Presentation

Teoria Introducão
, ao java ee

O curso Java Level 2 é focado nas aplicações Java para a Web, mais
precisamente nas aplicações que se utilizam do Container Web do Servidor JavaEE.
Não se preocupe com os termos, pois eles serão abordados com a devida
profundidade nos capítulos subsequentes.

O ambiente da World Wide Web consagra-se a cada dia como o maior


repositório de informações e aplicações existente. A cada dia mais e mais empresas
delegam seus sistemas e dados para sistemas na web. Os usuários ao redor do
mundo passam cada vez mais horas de seus dias conectados, buscando informações,
interatividade, produtos e soluções no ambiente da Internet. É nesse mundo que a
plataforma Java consagrou-se e exerce maior influência. Hoje o ambiente Java para a
Web é o nicho com mais oportunidades para o desenvolvedor: a cada dia mais
empresas buscam criar ou migrar seus sistemas para a plataforma Java, seja pelos
benefícios de performance e escalabilidade, seja pela facilidade de ter recursos
poderosos à disposição, sem precisar vincular-se a esta ou aquela empresa, ou seja,
libertar-se do chamado vendor lock-in.

O mundo Java oferece milhares de oportunidades e grande potencialidade para


quem quer alto padrão de desenvolvimento e diversidade de possibilidades, entretanto,
a liberdade para a criação de aplicativos Java para a Web não é tarefa tão trivial como
se poderia imaginar. Na verdade, exige-se um bom conhecimento da linguagem e de
diversas APIs relacionadas. Algumas técnicas, ou melhor dizendo: dicas, são
essenciais para se obter um bom rendimento no aprendizado e são discutidas a seguir,
mas antes veremos os pré-requisitos para um bom entendimento e desempenho no
curso.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 5

Pré-requisitos

A proposta para o Treinamento Java Level 2 supõe que o aluno tenha cursado
previamente, ou possua conhecimento equivalente, ao seguinte conteúdo, todos
oferecidos pela Grande Porte como cursos independentes:
1
 Lógica de Programação;
 HTML e;
 Java - Level 1.

É importante frisar que não haverá tempo hábil para esclarecimento de dúvidas
relacionadas à linguagem, orientação a objetos ou mesmo relativas à composição de
blocos essenciais de código, como laços de repetição e desvios condicionais. Dessa
forma, caso o aluno conclua que já possua o conhecimento por meios equivalentes,
fica a dica para relembrar e recuperar tais conceitos, pois serão primordiais no
desenrolar das aulas.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


6 Parte 1

Teoria Como aprender java para web

A questão sobre como aprender Java, ou ainda: qual a melhor forma de


aprender Java, por diversas vezes tem ocupado fóruns e bate-papos e realmente não
é algo fácil de ser respondido. Contudo, algumas dicas facilitarão o aprendizado e
devem ser primordiais para o aluno, pois fixarão o conhecimento e esclarecerão
pontos que à primeira vista parecem sombrios.

A tecnologia Java, por si só, é bastante didática e de fácil acesso. A maior


parte do ferramental necessário para se aprender Java é gratuito! Os itens que fogem
a essa regra possuem alternativas confiáveis e estáveis no mundo open source.

Dicas para um bom aproveitamento:

 Procure ler a teoria constante da apostila ANTES da aula - Dessa forma, o que
será dito não será completamente desconhecido pelo aluno e ele poderá
inclusive já vir com perguntas formuladas sobre a matéria;
 Procure resolver TODOS os exercícios. Eles são feitos de forma a consolidar
conceitos e, por que não afirmar: é a única forma de aprender a lidar com
erros!
 Arrisque, teste novas maneiras de chegar ao mesmo ponto. O desenvolvimento
de software e criação de código é algo potencialmente técnico e pessoal e o
resultado da implementação feita por um desenvolvedor pode não ser claro
para outros profissionais, por mais que existam regras de boas práticas e
convenções. A única forma de compreender código alheio é testando soluções
semelhantes e procurando entender padrões conhecidos no meio Java;
 Os Apêndices contém informação valiosa e terão suas leituras indicadas
durante o curso, pelo professor, nos momentos em que tal conhecimento será
utilizado. Quando receber a indicação, LEIA TODO O CONTEÚDO DOS
APÊNDICES no momento descrito, para poder aproveitar a oportunidade de
esclarecer dúvidas e agregar novas técnicas;
 No momento da montagem do ambiente e compreensão dos passos de
configuração em sala de aula, observe atentamente as medidas do professor e
procure montar um ambiente parecido em casa ou em seu computador
particular. Tenha sempre em mãos um ambiente pronto para que novas ideias
sejam testadas de imediato;
 Tome notas - seja com uma caneta ou em um aplicativo gráfico - anote o que
puder e sempre que possível. Quanto mais experiências forem anotadas,
menor a probabilidade de erros futuros.

E, por fim,

 Divirta-se! Criar aplicativos com Java é divertido e prazeroso. Ouse com novas
soluções e arrisque-se! O resultado só pode ser positivo!

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 7

Teoria o que é java ee


1
A plataforma Java, após quase duas décadas de maturidade, atingiu níveis de
grande escala e possui soluções que vão desde um pequeno Java Card embutido em
cartões de crédito, identificação pessoal, etc., até sistemas distribuídos em grandes
Companhias como Banco do Brasil, Receita Federal em âmbito nacional e Nasa,
Google, por exemplo, de atuação mundial. Nessa enorme variedade, é comum que
um desenvolvedor especialize-se em determinada área da plataforma Java e lá
permanece por diversos anos, tendo em vista a enorme variedade de ferramentas à
sua disposição para entender e aplicar.

Para efeitos didáticos, a seguinte distribuição pode ser feita nas versões da
plataforma Java, conforme suas clássicas aplicações:

Esquema das distribuições Java em divisão didática

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


8 Parte 1
Nesse gráfico, pode-se denotar a presença das três grandes áreas de
aplicação da tecnologia Java, J2SE, J2ME e J2EE, cada qual representando um
conjunto de APIs aplicáveis conjunta ou separadamente conforme explicitado na figura.

São elas:

 J2SE:termo que refere-se ao nome descritivo Java Standard Edition. É o ramo


principal, representa o núcleo da plataforma. Contém todas as bibliotecas
fundamentais e é base para a divisão Enterprise Edition (J2EE) e para parte da
divisão Micro Edition (J2ME).

 J2EE: termo que refere-se ao nome descritivo Java Enterprise Edition. É sem
dúvida o maior ramo da plataforma Java e engloba as tecnologias Web e
Enterprise (Sistemas Distribuídos). baseia-se na versão J2SE e acrescenta
uma grande quantidade de APIs específicas ao seu propósito. É o foco deste
curso.

 J2ME: termo que refere-se ao nome descritivo Java Micro Edition. É a menor
versão das divisões da plataforma Java e abrange todas as APIs utilizadas em
dispositivos móveis e embarcados, como celulares, tablets e equipamentos
dedicados como controladores e robôs. Parte de sua arquitetura baseia-se na
JVM como todas as outras versões porém abrange algumas tecnologias não
baseadas na Java Virtual Machine como MIDP e CLDC.

O objeto de estudo deste curso são as APIs relacionadas com a tecnologia


Web da plataforma Java, ou seja, a porção da divisão Java Enterprise Edition
(J2EE)utilizada em aplicações Web. Sempre que possível serão apresentadas as
relações existentes com as demais tecnologias envolvidas no Container Web do
Servidor Java EE de forma que o aluno possa compreender a potencialidade das
ferramentas e suas aplicações.

A plataforma J2EE e APIs

A plataforma Java Enterprise Edition é composta por uma grande quantidade


de APIs que representam tecnologias diversas à disposição do desenvolvedor para a
construção de software robusto, performático e escalável. Algumas dessas APIs são
exclusivamente opcionais e outras são fundamentalmente obrigatórias. Veremos
abaixo uma lista das APIs disponíveis na plataforma J2EE, sem esgotar o rol:

 Servlet;
 Java Server Faces (JSF);
 Java Server Pages (JSP);
 EL (Expression Language);
 Java Persistence (JPA);
 Java Message Service (JMS);
 Web Services (JAX-WS, JAX-RS);
 BeanValidation;
 EJB;
 EJB Lite;
 JavaMail;

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 9

 Java Transaction (JTA);

1
 Interceptors;

... entre outras.

Dentre a lista acima denotada, os itens em vermelho serão os vistos no curso


Java Level 2. As demais APIs podem ser utilizadas em algumas aplicações web,
porém destinam-se essencialmente a aplicações enterprise com necessidades de
maior preocupação com escalabilidade, distribuição e performance. Serão alvo de um
outro curso.

Servidores Web, Servidores de Aplicação e Containers

As aplicações web em geral tem algumas necessidades para que possam ser
implementadas, seja qual for a tecnologia utilizada. Essas dependências podem variar
conforme a plataforma de desenvolvimento mas, em geral, algumas são comuns. A
existência de um servidor de aplicações é uma realidade que permeia todas as
tecnologias de desenvolvimento web. Um servidor de aplicações trabalha
conjuntamente com um servidor web (Servidor HTTP) para responder a requisições de
usuários e clientes.Veja um exemplo esquemático abaixo.

Relacionamento existente dentro do Servidor de Aplicações Java EE:

Esquema de relacionamentos no Servidor Java EE

No modelo apresentado, as requisições provindas da web são recebidas por


um servidor HTTP (servidor web), que mapeia o endereço solicitado e encaminha a
chamada para o programa registrado como responsável; no caso da arquitetura Java
pra o Container Web.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


10 Parte 1

Dessa forma, dentro do container web, novo redirecionamento é feito para o


componente registrado para responder às requisições feitas naquele endereço.
Comumente, esse componente é um Java Servlet, que pode resolver a requisição de
forma isolada ou repassá-la para outros componentes que farão trabalho útil.

Finalmente, a resposta é montada dinamicamente e redirecionada ao usuário


em formato HTML, sendo interpretado e renderizado pelo navegador web instalado na
máquina do usuário.

Mas, dentre todos os conceitos, como definir o que é o servidor? E o container?

Um servidor, para o mundo dos profissionais de infra-estrutura de TI pode


significar o conjunto de equipamentos, por vezes distribuídos e escaláveis, que
compõem o hardware e software utilitários, sediados geralmente em um datacenter,
que correspondem ao conceito de servidor físico ou virtual, provendo acesso a
arquivos, impressão, aplicativos, web, banco de dados, etc. É efetivamente o que
chamamos, por vezes, de servidor físico, administrado por uma equipe de Engenharia
de Redes, com características como memória, espaço em disco e capacidade de
processamento.

O conceito de servidor de aplicações supõe apenas um software, um programa


de computador, sendo executado em um servidor físico, que responde a chamadas
em determinada(s) porta(s) de comunicação. Podem atender a chamadas por diversos
protocolos de rede, como TCP, HTTP, HTTPS, FTP, entre outros.

Dentro do servidor de aplicações, na plataforma Java, a especificação da


plataforma prevê a existência de dois "containers", para conformação com a definição
de um servidor Java EE Completo: o Container Web e o Container EJB. Sob a idéia de
container, pode-se imaginar um ambiente independente onde se alocam componentes
funcionalmente interligados para um determinado fim. Um espaço feito para alocar
outros componentes que sejam específicos para as funcionalidades de Web
(Container Web) e componentes de negócios (Container EJB).

Útil faz-se dizer que a diferenciação entre os conceitos de servidor de


aplicações por vezes pode não ser algo simples. Alguns autores preferem unificar o
conceito entre os dois para fins didáticos no início do aprendizado.

Assim como existem requisitos para um Servidor Java EE Completo, existem


requisitos para servidores que apenas conformam-se com a especificação do
Container Web, especificação essa chamada de "Web Profile", antes pela Sun
Microsystems e agora pela Oracle, após a aquisição daquela por esta.

É exatamente nesse campo em que este curso será desenvolvido. Será


utilizado um dos servidores que concentra apenas o Container Web da plataforma
Java EE 6, o Apache Tomcat, largamente utilizado no mundo, dada sua performance,
baixa necessidade de recursos para funcionamento e facilidade para instalação e
configuração. Outro ponto importante: é open source e gratuito.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 11

Para que o aluno possa conhecer o universo de servidores de aplicação

1
existentes para a plataforma java, segue uma lista dos mais utilizados:

Full Profile:

 Oracle GlassFish Server - disponível em versão Open Source gratuita e


comercial;
 Oracle WebLogic Server - somente em versão comercial;
 JBoss Application Server - Red Hat, disponível nas versões Open Source e
Comercial;
 IBM WebSphere Application Server - disponível nas versões Community
Edition e Comercial;
 Apache Geronimo - Apache Software Foundation - Open Source.

Web Profile:

 GlassFish Server Open Source Edition;


 JBoss Application Server - Red Hat;
 Caucho Resin;
 Apache TomEE (Versão entre o Tomcat e o Geronimo).

Enfim, a lista é exemplificativa e existem diversas outras distribuições.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


12 Parte 1

Teoria Arquitetura web

A Realidade Web é Stateless

Uma primeira importante conclusão sobre aplicativos para a web é exatamente


como o fluxo de informações ocorre. O conceito de Stateless surge nesse cenário e
significa exatamente o que a primeira impressão demonstra: não há manutenção de
estado no mundo web. Mas o que isso significa?

A cada requisição do usuário, geralmente feita por um browser ou por outro


aplicativo, as informações passadas ou recebidas restringem-se somente àquela única
requisição. O servidor desconhece a identidade ou o histórico das requisições feitas
anteriormente por aquele cliente ou outros. A cada pedido ou clique dado, o servidor
inicia novamente seu percurso para atender ao pedido, mas sem lembranças de
pedidos anteriores.

Quer dizer que não há como manter um estado persistente de conversação


entre o cliente e o servidor? Sim, há diversas formas de fazer isso, mas é exatamente
esse o ponto a se chamar atenção: o desenvolvedor terá que lidar com essa
necessidade e preocupar-se a todo momento com esse estado de conversação,
utilizando das ferramentas que possui. Fique calmo! Essa característica é fundamental
para aplicações web e existem a cada dia formas mais poderosas e elegantes de se
gerenciar o estado dos dados e requisições dos clientes.

As formas mais comuns de se realizar tal tarefa são por meio de sessões e
cookies, mas não se preocupe. Esses conceitos serão vistos mais à frente.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 13

Demonstração da característica Stateless do protocolo HTTP

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


14 Parte 1
Requisições e Respostas

O mecanismo de requisições e respostas é o cerne da compreensão das


aplicações web. Toda a definição do protocolo HTTP define-se sobre esse conceito. A
interação do usuário com o aplicativo será feita por meio dessas duas instâncias,
portanto estudaremos como se dá esse mecanismo em geral e, posteriormente, na
plataforma Java.

Inicialmente, a solicitação por uma página ou clique feito pelo usuário em uma
página web já aberta, gera uma requisição a um servidor web que possui o seguinte
formato simplificado, para o método GET:

GET /index.html HTTP/1.1

Host: www.exemplo.com.br

Header de requisição GET

Ao receber a requisição acima, o servidor retorna com a resposta, que possui o


seguinte cabeçalho exemplificativo:

HTTP/1.1 200 OK

Date: Fri, 23 Mar 2012 22:38:34 GMT

Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)

Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT

Etag: "3f80f-1b6-3e1cb03b"

Accept-Ranges: bytes

Content-Length: 438

Connection: close

Content-Type: text/html; charset=UTF-8

Header de resposta do servidor

Além do exemplo usado acima, que refere-se ao método GET, o desenvolvedor


web deve saber que existem outros métodos de requisição HTTP que podem ser
utilizados. Dentre todos eles, o de maior importância e que merece tanto destaque
quanto o GET é o método POST, cuja requisição está delineada abaixo:

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 15

1
POST /index.html HTTP/1.1

Accept: text/html

If-modified-since: Fri, 23 Mar 2012 19:43:31 GMT

Content-Type: application/x-www-form-urlencoded

Content-Length: 41

Nome=AlunoGrandePorte&Idade=23&Curso=JavaLevel2

Header e corpo de requisição POST

Abaixo, uma breve descrição dos métodos HTTP:

GET: usado para solicitar algum recurso como uma página ou um componente
de servidor identificado por meio da URL. Utilizado para passar parâmetros via URL ao
servidor no formato exemplificativo:

http://www.exemplo.com.br/teste?Nome=AlunoGrandePorte&Idade=23&C
urso=JavaLevel2

POST: Possui a principal função de enviar dados ao servidor, de um formulário,


por exemplo. Nesse método, os dados são passados no corpo da requisição e não na
URL, como no caso do GET, provendo maior segurança no trâmite de informações.
Veja o exemplo da Lista 2.3.

HEAD: Variação do GET usado para obter metadados, informações por meio
do header da resposta, sem necessidade de recuperar o conteúdo de retorno.

PUT: Envio de algum recurso. Pouco usado no protocolo HTTP. É


tradicionalmente usado com FTP.

DELETE: Analogamente ao anterior, é utilizado para excluir um recurso


qualquer.

TRACE: Utilizado em grande parte para debug de forma a se obter um eco do


pedido e para analisar o que está sendo alterado no pedido pelos servidores
intermediários na rota até o recurso pedido.

OPTIONS: Obtém os métodos HTTP aceitos pelo servidor.

CONNECT: Usado para tunelamento SSL, geralmente realizado por um proxy


com finalidade de utilizar conexão segura.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


16 Parte 1
Em um servidor Java EE, o mecanismo de tratamento das requisições e
respostas HTTP passa por um processo inicial de montagem pelo Container Web para,
somente após, repassar o controle para o desenvolvedor, via Servlet ou JSP, que
tratará o pedido e formará a resposta ao cliente.

Basicamente, a sequência a seguir ilustra o mecanismo realizado pelo Servidor


Web e Container Web Java.

Requisição:

Tratamento da Requisição HTTP pelo Container Web

Após a requisição do usuário, o Servidor Web identifica que a requisição é


endereçada ao Container Web e repassa o pedido. Uma vez chegada a requisição, o
Container identifica o Servlet mapeado para tratar o pedido e cria dois objetos que
encapsulam os dados do pedido: Request e Response destinados a transportar os
dados, respectivamente, da requisição e da resposta.

Em seguida, é criada uma nova thread sobre a instância do Servlet


responsável e os dois objetos são "injetados" no método Java que trata o respectivo
método HTTP (GET, POST, etc). A partir deste ponto, a lógica necessária é executada
para produção da resposta, que será encapsulada no objeto Response e retornado ao
cliente via Container.

O Container transforma a resposta em HTML e retorna ao usuário.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 17

Consistente

Resposta, passo 1:
1

1º Passo do tratamento da Resposta HTTP pelo Container Web

Resposta, passo 2:

2º Passo do tratamento da Resposta HTTP pelo Container Web

Finalizado tratamento da requisição, como primeiro passo, o objeto Response é


tratado pelo Container e o código HTML é retornado ao Servidor Web, que o
encaminha ao usuário.

Em um segundo passo, o Container Web elimina os recursos utilizados para


atender à requisição: a thread criada e os objetos Request e Response, aguardando
as próximas requisições e então todo o ciclo se reinicia.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


18 Parte 1

Teoria Arquitetura em camadas

A arquitetura das aplicações Java EE possui diversas possibilidades de


configuração, conforme o objetivo e porte da aplicação a ser desenvolvida. Em muitas
situações, as empresas já possuem sistemas legados ou Bancos de Dados em uso
(chamados EIS - "Enterprise Information Services") e o sistema a ser desenvolvido
deve conformar-se com essa realidade. É nessa análise de implantação que define-se
a arquitetura a ser usada.

Em uma abordagem completa, a arquitetura Java EE 6 pode ser descrita pelo


diagrama:

Arquitetura Java EE 6 Completo

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 19

Na arquitetura esquematizada acima, pode-se observar quatro camadas bem

1
definidas: a Camada Cliente, a Camada Web, a Camada Business e a Camada EIS.

Cabe notar que as camadas são independentes e podem alocar-se de diversas


configurações sendo, por vezes, até opcionais. Para o já mencionado “Web Profile”,
utilizado para aplicações web em Java e foco do nosso curso, o desenho das camadas
se reajustaria, de forma que a camada cliente seria formada pelo browser do usuário e
não existiria a camada J2EE Business. Nessa situação, toda a lógica de negócio é
manipulada por objetos Java simples.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


20 Parte 1

Montando seu ambiente


Teoria
de desenvolvimento

Para montagem do ambiente de desenvolvimento Java EE, serão necessários:

 Um JDK (Java Development Kit), versão 1.6 ou superior;


 Um Sistema de Desenvolvimento Integrado (IDE);
 Um Container Web Java.

Considerando que o aluno já possui condições de instalar e configurar o JDK e


o IDE Eclipse (que será usado por padrão), prosseguiremos com o download e
“instalação” do Apache Tomcat7 como Container Web padrão.Ele será utilizado
durante todo o curso.

Como forma de manter-se atualizado, dê preferência para versões do Eclipse


iguais ou superiores à versão 3.6 (Helios) e sempre na versão Java EE. Os plug-
ins provindos nesta versão do eclipse são adequados ao desenvolvimento web. Da
mesma forma, ao utilizar o Apache Tomcat, o aluno deve utilizar a versão 7, tendo em
vista a compatibilidade com a plataforma Java EE 6, ministrada durante o curso.

Instalando o Apache Tomcat7

Para instalar o Tomcat, o único passo necessário de atenção é o seu download


da página da Apache Software Foundation, por meio do endereço:

http://tomcat.apache.org/

Página inicial do Apache Tomcat na web

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 21

Clicando no item Tomcat 7.0 na Seção Download do lado esquerdo da página,

1
o usuário é levado a uma nova página para a escolha de uma das formas de download
possíveis, como zip, tar.gz e versões específicas para o Sistema Operacional
Windows, conforme imagem abaixo:

Página de Downloads do Apache Tomcat

Dentre as versões existentes, escolha aquela que corresponde ao seu Sistema


Operacional. Ao término você terá um arquivo compactado, com exceção do instalador
Windows, que instala o servidor como um serviço.

Descompacte o arquivo no diretório C: caso esteja utilizando o S.O. Windows.


Caso esteja utilizando um sistema Unix-likecomo Linux ou MacOS, faça a
descompactação dentro do diretório /home de sua máquina.

Ao final, você deverá ficar com a seguinte estrutura, na pasta recém-


descompactada:

Árvore de arquivos do Apache Tomcat

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


22 Parte 1

E essa é toda a instalação necessária para se iniciar a trabalhar com o Apache


Tomcat7. À data da última atualização dessa apostila, a versão estável mais recente
do Apache Tomcat era a 7.0.26. Caso exista alguma atualização estável mais recente,
sinta-se à vontade para baixá-la e utilizá-la.

Configurando o Apache Tomcat7 no Eclipse

Uma vez baixada, descompactada e alocada em um local do computador, o


Eclipse já estará “instalado” e pronto para ser executado.

Com um duplo clique no seu executável, obtemos a seguinte configuração de


desktop inicial:

Página inicial do Eclipse

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 23

Observe a aba “Servers” na view inferior da janela. É nela que faremos a

1
configuração do Apache Tomcat.

Com o mouse no interior dessa view, clique com o botão direito e siga clicando
na sequência:  New  Server.

Janela inicial de configuração de servidores no Eclipse

Você será direcionado para uma primeira janela de configuração, conforme


figura acima, onde deverá escolher qual o servidor a ser instalado, seu nome de “host”
e o nome da instância que desejar.

Escolha Apache Tomcat7 e clique em “Next”. Você será direcionado para a


próxima janela de configuração do seu novo servidor no Eclipse:

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


24 Parte 1

Janela seguinte para configuração do Apache Tomcat no Eclipse

Clique no botão “Browse” existente de forma a apontar ao S.O. onde está


localizada a pasta-raiz do Apache Tomcat. Você também pode inserir o caminho
manualmente no campo respectivo, caso prefira. Ao finalizar, clique em “Finish”.

Seu servidor já é reconhecido pelo Eclipse.

Como última etapa, dê dois cliques no servidor agora existente dentro da view
“Servers”. O eclipse apresentará na janela principal, uma página específica para
configuração do Apache Tomcat:

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 25

Janela de configurações adicionais do servidor instalado

Para que, finalmente terminemos a configuração, execute os seguintes passos


nessa janela:

 Na Seção Server Locations, clique no radio button do meio, o que diz: “Use
Tomcat installation (takes control of Tomcat installation)”;

 Altere o nome da pasta já existente no campo “Deploy path” de wtpwebapps


para webapps;

 Salve o arquivo.

OK. Agora finalizamos a configuração inicial do Apache Tomcat e estamos


prontos para iniciá-lo.

Novamente na aba “Servers”, clique sobre o servidor com o botão direito do


mouse e selecione “Start”. Você também pode clicar no ícone circular verde com o
símbolo “play”.

Verifique no seu navegador que o servidor está rodando e pronto para aceitar
conexões, digitando a seguinte URL:

http://localhost:8080

Configuração de usuários e privilégios no Apache Tomcat7

Ao tentar acessar os recursos do Tomcat, como o Server Status ou o Manager


App, o aluno se deparará com a solicitação do servidor por um login e uma senha.
Faremos agora a configuração de login e senha para acessar os recursos do servidor
e analisar suas possibilidades.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


26 Parte 1
O Tomcat utiliza-se de um arquivo de configuração para definir seus usuários:
o “tomcat-users.xml” localizado na pasta conf, dentro da raiz da instalação do servidor.
Possui basicamente o seguinte corpo:

<?xml version="1.0" encoding="UTF-8"?>


<tomcat-users>

<role rolename="tomcat"/>

<role rolename="role1"/>

<user username="tomcat" password="tomcat" roles="tomcat"/>

<user username="both" password="tomcat" roles="tomcat,role1"/>

<user username="role1" password="tomcat" roles="role1"/>

</tomcat-users>

Estrutura de template do arquivo tomcat-users.xml

Note que dentro do nó principal: <tomcat-users>, temos duas variações de


tags: <role> e <user> com seus devidos atributos. A primeira é usada para declarar
privilégios dos usuários no sistema e a segunda, usada para efetivamente declarar os
usuários com permissão de acesso em cada uma das “roles”.

As possíveis “roles” para acesso ao Tomcat são:

 manager-gui–permite acesso às interfaces gráficas HTML e à página de status;


 manager-script –permite acesso à interface de texto e à página de status;
 manager-jmx–permiteacessoao proxy JMX e à página de status;
 manager-status –permite acesso somente à página de status.

Vistas as regras, vamos editar esse arquivo para atribuir permissão de acesso
e privilégios para acesso ao servidor:

Edite o arquivo de forma que ele fique com a seguinte estrutura(substitua os


campos em negrito por seus dados pessoais):

<?xml version="1.0" encoding="UTF-8"?>


<tomcat-users>

<role rolename="manager-gui"/>

<user username="aluno" password="tomcat" roles="manager-gui"/>

</tomcat-users>

Estrutura final do arquivo tomcat-users.xml após alteração

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 27

A seguir, reinicie o servidor, acesse a url http://localhost:8080 no seu

1
navegador e, novamente, clique no botão Manager App, inserindo em seguida as
credenciais que cadastrou no arquivo de configuração.

Dessa vez, o acesso é franqueado e é possível administrar as aplicações por


meio da interface GUI web provida pelo Apache Tomcat.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


28 Parte 1

Practice

Atividade Revisão aos pares

Desenhe um esquema de requisições e


respostas HTTP, voltadas à plataforma Java.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte 1 29

Performance
1

Atividade Trabalho em dupla

Monte o ambiente de desenvolvimento Java


EE em seu computador.

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


30 Parte 1

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579 (11) 9 9903-3218


Parte

O MySQL é um sistema de gerenciamento de banco de dados


(SGBD), que utiliza a linguagem SQL como interface. É atualmente
um dos bancos de dados mais populares , com mais de 10 milhões
de instalações pelo mundo.
Versão 2.1.1
Parte 2 3

Preparation 2

Trocando Ideias É agora que você fala !!

Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na


capa desta parte. Isso é importante para que seu instrutor e seus colegas
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe?


 O que você não sabe?
 Porque é importante conhecer estes tópicos?
 Quais são os seus temores?
 O que você considera difícil?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


4 Parte 2

Presentation

Teoria Banco de dados e jdbc

O que são e para que servem os Bancos de Dados

Ilustração Banco de Dados

Assim como os aplicativos criados para os mais diversos fins, Bancos de


Dados são essenciais para a automatização ou a criação de soluções
informatizadas.

Os programas em geral precisam de dados para trabalhar e, com


enfoque ainda maior, precisam criar, gravar, alterar e apagar dados, conforme
as interações do aplicativo com o usuário. Não é fácil pensar em uma aplicação
sequer que não produza ou consuma dados.

Nesse contexto é que entram os Bancos de Dados. Podemos encontrá-


los nas mais diversas formas e arquiteturas, como por exemplo: bancos
hierárquicos, relacionais, servidores, embutidos (embedded), rodando
localmente ou remotamente, binários, orientados a objetos, textuais, etc. A lista
pode se estender por diversas páginas e ainda assim faltarão descrições
precisas da variedade existente.

Em aplicações web, a arquitetura mais comumente usada é a que


envolve os SGBDs (Sistemas Gerenciadores de Bancos de Dados) servidores,
podendo estar localmente instalados ou em servidores remotos. A
comunicação comumente usada para conexão com esses bancos, via

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 5

aplicativos web, é o HTTP. Mas também podemos encontrar outras formas


como SOCKETs, WebServices (ainda assim sobre HTTP) e outros.

Arquitetura de conexão com o SGBD

É fundamental ao desenvolvedor Java conhecer os detalhes necessários


para criar seu repositório de dados, conectar-se a ele, realizar operações de
inserção, atualização e remoção de dados de forma fluente, utilizando-se das
APIs existentes e, dessa forma, entregar um sistema funcional e sem erros.

De forma a não deixar o aluno assustado em primeira mão, vale dizer


que esse conhecimento será relativamente superficial, ou seja, não preocupe-
se em tornar-se um verdadeiro DBA nos mais diversos SGBDs existentes.
Essa tarefa é algo impraticável e, por que não arriscar-se em dizer: quase
impossível! O conhecimento necessário deve focar-se na modelagem dos
dados a serem trabalhados e nas operações básicas de operação do Banco de
Dados.

Neste curso, utilizaremos o SGBD Open Source e gratuito MySQL, hoje


de propriedade da empresa Oracle (que adquiriu a Sun Microsystems em 2009).
Nossa escolha baseia-se no grande respaldo que o MySQL possui no mundo
em aplicações dos mais variados portes e nas mais variadas aplicações, por
ser um SGBD robusto e confiável. Além disso, é possível de se encontrar
diversos aplicativos para o MySQL também gratuitos na Internet.

Alguns SGBDs de maior destaque no mercado:

Free e Open Source:

MySQL http://www.mysql.com;
PostgreSQL http://www.postgresql.org.br;
Firebird http://www.firebirdsql.org;
Sqlite http://www.sqlite.org.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


6 Parte 2
Free, porém proprietários:

Microsoft SQL Server 2008 Express - Possui limitação de tamanho.


Oracle Database 11g Express Edition - Possui limitação de tamanho.
IBM DB2 Express-C

Comerciais:

Oracle Database Enterprise / Standard Edition


Microsoft SQL Server
IBM DB2 Database

Um Resumo sobre modelagem de dados

Modelar dados é uma atividade inerente ao desenvolvimento de


qualquer sistema de informações. Em aplicações web, onde a utilização de
Banco de Dados é uma prática constante, modelar dados de forma inteligente e
concisa pode ser um requisito definitivo para o sucesso.

A priori, algumas observações fazem-se importantes:

Quando nos referirmos a Bancos de Dados, estaremos fazendo alusão


ao Sistema Gerenciador de Banco de Dados e não ao conjunto físico de
arquivos que compõem o Banco de Dados propriamente;

Daqui por diante, utilizaremos o MySQL como Banco de Dados


(referindo-nos ao SGBD, conforme tópico anterior) padrão e, toda a
modelagem e comandos SQL feitos são direcionados a ele;

Não há como aprofundar o aluno em toda a linguagem SQL e seus


pormenores. Para esse fim, indicaremos o curso Modelagem de Dados da
Grande Porte, que levará o interessado a um nível mais detalhado de
compreensão nessa área nesse quesito;

O Banco de Dados apresentado na teoria será implementado na


Atividade 1 deste Capítulo então aproveite para assimilar os conceitos e fazer
anotações. Na parte prática será exercitada a implementação real.

Todo Banco de Dados moderno e relacional desenvolve-se sobre a


estrutura de tabelas e relacionamentos. É essa estrutura que permite o
manuseio dos dados de forma tão sofisticada e flexível pelas aplicações em
geral.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 7

Inicialmente, façamos um estudo sobre essas duas entidades:

Tabela

Uma tabela pode ter sua estrutura didaticamente comparada à de uma


planilha do MS Excel, por exemplo: 2

Planilha de dados

Tabela de Banco de Dados

Note a disposição das colunas e dados na planilha acima desenhada e o


diagrama representativo de uma tabela no banco de dados. Na planilha é
possível inserir dados sem a preocupação momentânea de definir o tipo dos
dados. Já no banco de dados a tipificação dos dados é um dos fatores de
dimensionamento mais importantes e pode impactar em todo o
desenvolvimento do sistema que o operará.

Tabelas essencialmente são os componentes que armazenarão os


dados em formato de registros, exatamente como na planilha. Cada registro, ou
tupla, representa um ente ou objeto a ser controlado e a quantidade de colunas,
ou ainda, que tipo de dados devem ser usados é decisão que cabe ao
desenvolvedor ou ao DBA envolvido no projeto.

No mundo relacional dos bancos de dados, a principal forma de se


operar comandos é por meio da linguagem SQL (Structured Query Language).
SQL é utilizada como padrão mundial em bancos de dados e seu
conhecimento é de extrema importância para o desenvolvimento de bancos de
dados.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


8 Parte 2
A linguagem SQL, apesar de possuir um núcleo de comandos comuns,
vem com o tempo se distinguindo em dialetos independentes conforme a
evolução dos bancos de dados se processa, especialmente nas versões
comerciais. Como exemplo, o Banco de Dados Oracle, utiliza-se de um dialeto
chamado PL-SQL, enquanto o Microsoft SQL Server opera sob um dialeto
chamado Transact-SQL. Independente das diferenças sintáticas e semânticas
existentes entre as diferentes implementações comerciais, os comandos
comuns de acesso a dados são muito semelhantes e não costumam causar
muita estranheza aos desenvolvedores.

Falando em comandos, vejamos brevemente os principais, que devem


ser de conhecimento do desenvolvedor:

DDL - Linguagem de definição de dados:

CREATE TABLE
ALTER TABLE
DROP TABLE
CREATE VIEW
DROP VIEW

DML - Linguagem de manipulação de dados:

INSERT
UPDATE
SELECT
DELETE

DQL - Linguagem de consulta a dados:


FROM
WHERE
GROUP BY
HAVING
ORDER BY
DISTINCT

Serão discutidos durante a aula os principais pontos de utilização de


cada um dos comandos descritos.

O segundo ponto fundamental para a compreensão dos bancos de


dados são os relacionamentos. Passaremos a entender como agem os
relacionamentos de forma a dar sentido aos dados armazenados e como as
tabelas podem correlacionar-se de forma a abstrair um conjunto de
informações contíguas ou complementares.

Os relacionamentos também são utilizados com foco em outros


requisitos como performance, pois criam relações indexadas entre dados
aparentemente independentes; segurança, pois evitam a distorção de um dado
dependente, evitando corrupção na informação como um todo; funcionalidade,

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 9

pois podem relacionar quaisquer tipos de dados, ainda que de naturezas


divergentes, conforme a necessidade do aplicativo ou do objetivo do repositório.

2
Comumente, representamos um banco de dados pelo seu Diagrama
Entidade-Relacional (DER), também chamado de Modelo Entidade-Relacional
(MER). Para nossa compreensão, analisemos o MER abaixo, que também será
utilizado na Atividade 1 deste capítulo:

MER contendo três tabelas relacionadas.

Inicialmente, é possível identificar-se três tabelas relacionadas que


armazenam dados, respectivamente, das entidades "aluno", "curso" e
"professor". Em cada tabela, note que existem diferentes atributos,
relacionados com a entidade que representam. Após o nome de cada atributo,
existe o TIPO de dado físico, delineado no banco de dados para
armazenamento do respectivo dado. Esse TIPO é definido pelo desenvolvedor
do repositório e pode variar conforme a necessidade da implementação.

Mais importante que essa percepção é o entendimento de como os


relacionamentos funcionam. Nesse mérito, podemos destacar os tipos de
relacionamento existentes:

UM para UM 11
UM para MUITOS 1n
MUITOS para UM n1
MUITOS para MUITOS nn

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


10 Parte 2
No diagrama acima, temos dois relacionamentos de UM para MUITOS.
Perceba que as tabelas aluno e professor não se relacionam diretamente, mas
por meio da tabela curso, seus dados estão referenciados, possibilitando a
obtenção de uma consulta entre elas de forma transparente.

Os conceitos relativos a cada tipo de relacionamento serão discutidos


em sala de aula.

JDBC

Todas as plataformas de desenvolvimento proporcionam,


invariavelmente, alguma forma de gravar dados em Bancos de Dados. Na
plataforma Java, o nome da biblioteca (ou API) de persistência de dados em
bancos de dados relacionais é chamada de JDBC (Java Database
Connectivity). Passaremos a utilizar as classes fundamentais de gravação em
Bancos de Dados para persistir nossos dados, mas antes vejamos como essa
API funciona.

A API JDBC abstrai o acesso ao Banco de Dados de suas


peculiaridades individuais por distribuição. Isso quer dizer que o desenvolvedor
não tem que se preocupar em conhecer os protocolos individuais de cada
distribuição ou ainda, a arquitetura em que essa implementação é baseada.
Essas peculiaridades ficam a cargo de cada fabricante ou entidade
mantenedora em fornecer, conforme as especificações JSR da API.

Diagrama de interfaces da API JDBC.

A interface de comunicação e seus componentes, mostrada no diagrama


acima, encontra-se no pacote java.sql e, dentre elas, a mais importante é a
Connection, que disponibiliza métodos para a execução de queries nos bancos
de dados. Essa conexão é feita por meio de Drivers fornecidos por cada
fabricante e são esses componentes que abstraem a complexidade específica
de cada implementação.

A classe DriverManager é a responsável pela comunicação com os


Drivers utilizados. Essa conexão exige uma String, chamada de String de
Conexão JDBC (ou URL de conexão) e possui a seguinte característica, para o
banco MySQL:

jdbc:mysql://<domínio>:<porta>/<nome do banco>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 11

Como trabalhar com JDBC

Veremos agora o conteúdo teórico da última atividade, entendendo o

2
que foi feito no código e os conceitos envolvidos.

A API JDBC consiste de uma interface de programação Java para


bancos de dados genéricos e permite que programadores Java criem
aplicações independentes de modelo ou tipo de SGBD, usando uma interface
única.

Essa API consiste de classes e interfaces para o estabelecimento de


conexões com Banco de Dados, execução de comandos SQL nos Bancos de
Dados, processamento do resultado dos comandos SQL e obtenção de
metadados dos Banco de Dados.

Quatro interfaces básicas são necessárias para o desenvolvimento de


aplicações com Banco de Dados em java: Driver, Connection, Statement e
ResultSet.

Veja como se dá o relacionamento entre essas interfaces por meio do


diagrama abaixo:

Relação entre as interfaces básicas da API JDBC.

Vejamos os passos necessários adotados por um típico programa Java


que acessa um Banco de Dados, da forma mais básica possível:

1. Carregar os drivers:

Class.forName("ClasseDriverJDBC");

Drivers são classes Java, geralmente criadas pelos próprios


fabricantes dos Bancos de Dados, que abstraem a complexidade inerente às
particularidades de cada versão / distribuição de Banco de Dados.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


12 Parte 2
A partir da distribuição do Java 6 não há mais necessidade de se
carregar o driver do Banco de Dados explicitamente. Ainda assim
apresentamos o conceito acima para conhecimento do aluno pois nem todos os
drivers de Banco de Dados suportam essa funcionalidade. Lembrando-se de
carregar os Drivers, não haverá problema, independente do Banco que se
esteja conectando.

2. Estabelecer conexões:

Para se conectar a um Banco de Dados, usamos o método estático


getConnection (URLDoBancoDeDados) da classe DriverManager:

Connection conexao = DriverManager.getConnection


(URLDoBancoDeDados, usuário, senha);

Onde a URLDoBancoDeDados refere-se ao identificador único desse


banco na Internet. para o caso do MySQL, essa URL tem a sintaxe (já
apresentada anteriormente):

jdbc:mysql://<domínio>:<porta>/<nome do banco>

Em nosso, caso, essa URL, já utilizada na última atividade possuía a


configuração:

Connection conexao = DriverManager.getConnection


("jdbc:mysql://localhost:3306/grandeporte", "Seu usuário", "Sua senha");

A conexão estabelecida é representada pelo objeto do tipo Connection,


que usamos para, em seguida, disparar comandos SQL para execução no
Banco de Dados.

3. Criar Statements ou Comandos:

O objeto que usaremos agora, Statement, pode ser enxergado como um


veículo de transporte dos nossos comandos SQL para o Banco de Dados e do
resultado destes de volta para o nosso programa. Nós podemos obter objetos
Statement por meio do objeto Connection criado anteriormente:

Statement statement = conexao.createStatement();

4. Executando Statements ou Comandos

Um comando SQL DDL ou comando de update de forma genérica


(INSERT, UPDATE, DELETE) pode ser executado utilizando-se do método:
executeUpdate(String sql).

Uma consulta SQL pode ser executada utilizando-se do método


executeQuery(String sql). O retorno dessa query consiste em um objeto
ResultSet.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 13

Exemplo de um comando INSERT na tabela aluno, criada anteriormente,


de forma programática:

2
statement.executeUpdate("INSERT INTO aluno(nome, idade, curso)
VALUES (\"JOANA DARC\", 35, 1)");

Exemplo de um comando SELECT na mesma tabela, de forma


programática, recebendo um objeto do tipo ResultSet como resultado:

ResultSet resultSet = statement.executeQuery("SELECT * FROM


aluno");

5. Processando o ResultSet

O ResultSet é a representação da tabela retornada como resultado,


encapsulada em um objeto do tipo ResultSet.

O objeto mantém uma tabela em memória com um cursor que aponta


para o registro atual. A posição inicial da linha inicial é null. Utilizamos os
diversos métodos get...() existentes para obter os dados de uma linha nessa
tabela, e o método next() para mover o cursor uma linha adiante.

Veja abaixo, uma representação gráfica do ResultSet retornado pela


consulta feita com a linha (já delineada acima):

//Seleciona todos os registros da tabela aluno


ResultSet resultSet = statement.executeQuery("SELECT * FROM
aluno");

Representação gráfica do ResultSet retornado e o deslocamento do cursor com


next().

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


14 Parte 2
Exemplo de código que executa uma consulta, recebe um ResultSet
como retorno e itera em seus elementos imprimindo a saída no console:

1 String sql = "SELECT * FROM aluno";


2 ResultSet result = statement.executeQuery(sql);
3 while (result.next()){
4 System.out.println("ID: " + result.getString("idaluno") + ", Nome: " +
5 result.getString("nome") + ", Idade: " + result.getString("idade") +
6 ", Curso: " + result.getString("curso"));
7 } //fim while

Código de consulta SQL via JDBC e processamento do ResultSet.

Observe que utilizamos os métodos getString(“nome da coluna”) para


obter o valor do registro para essa coluna e o método next() de ResultSet para
iterar sobre a coleção de dados recebidos.

Vejamos agora um exemplo completo de consulta ao Banco de Dados e


iteração sobre o ResultSet recebido:

1 import java.sql.*;
2
3 public class TesteJDBC {
4 public static void main (String [] args){
5 try {
6 String url = "jdbc:mysql://localhost:3306/grandeporte";
7 String user = <seu usuário>;
8 String password = <sua senha>;
9 Class.forName("com.mysql.jdbc.Driver");
10 Connection connection = DriverManager.getConnection(url, user,
11 password);
12 Statement statement = connection.createStatement();
13 String sql = "SELECT * FROM aluno";
14 ResultSet result = statement.executeQuery(sql);
15 while (result.next()){
16 System.out.println("ID: " + result.getString("idaluno") +
17 ", Nome: " + result.getString("nome") + ", Idade: " +
18 result.getString("idade") + ", Curso: " +
19 result.getString("curso"));
20 } //fim while
21 connection.close();
22 } catch (ClassNotFoundException e) {
23 e.printStackTrace();
24 } catch (SQLException e) {
25 e.printStackTrace();
26 }
27 }

Código completo para conectar ao Banco de Dados e realizar uma consulta.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 15

Practice 2
Atividade Trabalho em dupla

Instalando, criando e realizando operações no


banco de dados grandeporte no MySQL

Nessa atividade, instalaremos o Banco de Dados MySQL, criaremos o


Banco de Dados que utilizaremos para o exercício e inseriremos alguns dados
para utilização das operações básicas.

O nosso banco de dados tem a estrutura do MER mostrada


anteriormente e refere-se a uma fictícia aplicação de cadastro utilizada na
Grande Porte para controle de seus alunos e cursos.

1. Faça o download do "bundle" Mysql no site http://www.mysql.com


para Windows e instale na sua máquina. Essa versão de instalador inclui, além
do servidor de Banco de Dados, uma série de ferramentas para o
desenvolvedor:

 Todos os conectores suportados e criados pela Oracle

 MySQL Workbench (Ferramenta gráfica de design e controle do


Banco de Dados), além de modelos de exemplo

 Bancos de Dados de exemplo (World e Sakila)

 Documentação.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


16 Parte 2
Página de download:

Página de download do MySQL

2. Prossiga com a instalação do MySQL e escolha a instalação como


Serviço do Windows, seguindo as orientações do instrutor;

3. Terminada a instalação, o seu servidor de Banco de Dados já deverá


estar rodando. Se não estiver, será preciso iniciá-lo por meio do aplicativo
Serviços do Windows.

4. Abra um MySQL 5.5 Command Line Client por meio do caminho:

Menu Iniciar  Todos os Programas  MySQL  MySQL Server 5.5 


MySQL 5.5 Command Line Client

5. Faça seu login com a senha escolhida;

6. Execute o comando "show databases;" para obter uma lista dos


bancos de dados criados nesta instância do MySQL. O resultado deverá ser
como mostrado abaixo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 17

Tela após execução do comando show databases;

7. A seguir criaremos nosso banco de dados que se chamará


"grandeporte" e daremos o comando "use grandeporte" para que o MySQL
saiba que queremos trabalhar com esse banco. Esse comando garante que
todos os comandos seguintes serão aplicados a ele especificamente e não a
qualquer outro banco existente.

Tela com os comandos de criação e seleção do banco de dados "grandeporte";

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


18 Parte 2
8. A seguir, seguiremos para a criação de nossas tabelas, conforme o
schema abaixo. Para tanto, entre com os comandos sequenciais abaixo, na
ordem apresentada e conforme mostrado nas imagens do console:

CREATE TABLE professor (


idprofessor INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(100) NOT NULL
)

Comando DDL para criação da tabela "professor".

Tela com o comando de criação da tabela "professor".

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 19

CREATE TABLE curso (

2
idcurso INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
descricao VARCHAR(70) NOT NULL ,
professor INT NOT NULL ,
CONSTRAINT fk_curso_professor
FOREIGN KEY (professor)
REFERENCES professor(idprofessor)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)

Comando DDL para criação da tabela "curso".

Tela com o comando de criação da tabela "curso".

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


20 Parte 2

CREATE TABLE aluno (


idaluno INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(100) NOT NULL ,
idade SMALLINT NOT NULL ,
curso INT NOT NULL,
CONSTRAINT fk_aluno_curso
FOREIGN KEY (curso)
REFERENCES curso(idcurso)
ON DELETE NO ACTION
ON UPDATE NO ACTION
)

Comando DDL para criação da tabela "aluno".

Tela com o comando de criação da tabela "aluno".

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 21

9. Nesse passo, aproveitaremos para conferir a estrutura de nossas


tabelas no MySQL com o comando "DESCRIBE":

Tela com o resultado dos comandos "describe".

Perceba os campos apresentados e os tipos definidos. São exatamente


aqueles que inserimos nos comandos anteriores.

10. Faremos agora a inserção de alguns dados nas três tabelas de


forma que já as deixaremos preparadas para a segunda parte de nosso estudo
de Banco de Dados. para tanto, execute os comandos INSERT abaixo
definidos na ordem em que aparecem:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


22 Parte 2
Inserindo dados nas três tabelas:

INSERT INTO professor(nome) VALUES (


'Rodrigo Mastropietro'
);

INSERT INTO curso(descricao, professor) VALUES (


"JAVA LEVEL 2", 1
);

INSERT INTO aluno(nome, idade, curso) VALUES(


"JOAO DA SILVA", 23, 1
);

Lista com os comandos DML de inserção de dados nas tabelas.

Ao término seus comandos deverão estar dessa forma no console em


caso de sucesso:

Tela com os comandos "INSERT".

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 23

11. Faremos agora uma consulta nos dados cujas tabelas acabamos de
atualizar:

SELECT * FROM professor;

SELECT * FROM curso;


2
SELECT * FROM aluno;

Comandos DML de consulta às tabelas.

E o resultado...

Resultado das consultas executadas no Banco de Dados.

12. Como tarefa final desta atividade, insira mais três registros em cada
tabela com os dados que você desejar. Faça um esboço abaixo dos dados
inseridos nas tabelas:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


24 Parte 2

Atividade Revisão aos pares

Conectando ao Banco de Dados com JDBC

Nessa primeira tarefa, iremos conectar ao Banco de Dados usando


JDBC de forma a compreender os componentes utilizados, seguindo a
sequência de ações descritas nos passos abaixo:

1. Crie um novo projeto JAVA no Eclipse com o nome TesteJDBC:

Criação do projeto no Eclipse.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 25

2. Em seguida, configure o Build Path de seu projet o e inclua o jar do


MySQL Connector, nossa API que possibilitará a conexão:

Adicionando a API do Conector MySQL ao projeto.

Clique em Add External JARs, localize o arquivo JAR do conector MySQL e o


adicione ao projeto. Ao final, você deverá estar com o seu Package Explorer dessa
maneira:

Composição estrutural do projeto após adição do Conector MySQL.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


26 Parte 2
3. Crie uma nova Classe Java com o nome TesteJDBC e marque o checkbox
para criar o método public static void main (String [] args). Defina como pacote, o
caminho: com.grandeporte.jdbc:

Criação da Classe Java no projeto.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 27

4. Adicione o código abaixo na nova classe, prestando atenção nas Interfaces e


Classes utilizadas:

2
package com.grandeporte.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TesteJDBC {

public Connection getConnection(){


try{
String url = "jdbc:mysql://localhost:3306/grandeporte";
String usuario = "<SEU USUÁRIO>";
String senha = "<SUA SENHA>";
Connection con = DriverManager.getConnection(url,
usuario,
senha);
return con;
}catch(SQLException e){
throw new RuntimeException();
}
}

public static void main(String[] args) {

TesteJDBC teste = new TesteJDBC();


Connection con = teste.getConnection();
System.out.println("Conectou ao Banco de Dados!");

}
}

Código da Classe de Conexão JDBC com o Banco de Dados.

5. Por fim, execute o seu programa como "Java Application" e observe o


resultado:

Saída do console após a conexão bem sucedida.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


28 Parte 2

Performance

Atividade Trabalho em dupla

Prática com Banco de Dados e JDBC:

1. Atualize as tabelas do banco de dados grandeporte criadas na aula


anterior, de forma que fiquem com os dados iguais aos mostrados abaixo
(Execute os INSERTS, UPDATES e DELETES necessários):

Como auxílio inicial, seguem exemplos de comandos UPDATE e


DELETE, que não vimos até o momento

UPDATE:
UPDATE aluno SET nome = “King Arthur” WHERE idade = 35;

DELETE:
DELETE FROM aluno WHERE idade >= 34;

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 29

Tabelas:

curso: professor:

2
aluno:

Crie um novo projeto no Eclipse e execute o código da atividade anterior.


Certifique-se de que o MySQL, após as atualizações feitas acima, esteja
rodando. Analise o resultado.

Altere seu código de forma a executar um comando SELECT na tabela


“curso” usando a cláusula: WHERE descricao LIKE ‘%Java%’. Imprima o
resultado da mesma forma feita no código do item anterior.

2. Nesse item, aplicaremos os comandos INSERT e UPDATE usando


uma Interface diferente e de grande utilidade, indispensável ao desenvolvedor
Java. Trata-se do PreparedStatement, que substituirá o Statement (na verdade
é uma subinterface de Statement) que temos usado até o momento. Veremos
as vantagens dessa estratégia na prática. Para tanto, crie outro projeto Java no
Eclipse e uma classe de nome TestePreparedStatement com o seguinte
conteúdo:

1 import java.sql.*;
2 import javax.swing.JOptionPane;
3 public class TestePreparedStatement {
4 public static void main (String [] args){
5 try {
6 //Configuração da conexão
7 String url = "jdbc:mysql://localhost:3306/grandeporte";
8 String user = "root";
9 String password = "RMP7838-";
10 Class.forName("com.mysql.jdbc.Driver");
11 Connection connection = DriverManager.getConnection(url, user,
12 password);
13
14 //Leitura dos parâmetros passados pelo usuário
15 String nome = JOptionPane.showInputDialog("Entre " +
16 com o nome do aluno para gravar no Banco de Dados: ");
17 String idade = JOptionPane.showInputDialog("Entre " +

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


30 Parte 2
18 com o idade do aluno para gravar no Banco de Dados: ");
19 String curso = JOptionPane.showInputDialog("Entre " +
20 com o cód. do curso para gravar no Banco de Dados: ");
21
22 //Comando Insert utilizando-se de placeholders
23 String insert = "INSERT INTO aluno (nome, idade, curso) VALUES " +
24 (?, ?, ?)";
25
26 //Declarando e definindo os valores a serem colocados no lugar
27 //dos '?' na String insert
28 PreparedStatement statement = connection.prepareStatement(insert);
29 statement.setString(1, nome);
30 statement.setInt(2, Integer.parseInt(idade));
31 statement.setInt(3, Integer.parseInt(curso));
32
33 //Executando o INSERT
34 statement.executeUpdate();
35
36 //Consultando a tabela e verificando o resultado do INSERT feito
37 String query = "SELECT * FROM aluno";
38 ResultSet result = statement.executeQuery(sql);
39 while (result.next()){
40 System.out.println("ID: " + result.getString("idaluno") +
41 ", Nome: " + result.getString("nome") + ", Idade: " +
42 result.getString("idade") + ", Curso: " +
43 result.getString("curso"));
44 } //fim while
45 connection.close();
46 } catch (ClassNotFoundException e) {
47 e.printStackTrace();
48 } catch (SQLException e) {
49 e.printStackTrace();
50 }
51 }

Exemplo completo com PreparedStatement

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 31

Procure conhecer uma terceira Interface da API Java, localizada no pacote


java.sql, chamada CallableStatement. Essa Interface é utilizada para a execução
de Stored Procedures nos Bancos de Dados em geral, uma tarefa de grande
utilização no mercado atual. Se você não conhece as Stored Procedures,
2
aproveite a oportunidade e pesquise sobre o assunto, você certamente precisará
vez ou outra!

3. Até o momento, fizemos uso de apenas uma classe para fazer a


conexão com o Banco de Dados, disparar comandos SQL e tratar dos
resultados recebidos por meio de um ResultSet. Abordaremos agora uma visão
mais POO para esse mesmo problema, utilizando-se de dois Design Patterns
muito conhecidos no mercado Java: Factory e DAO. Além disso, faremos a
manipulação de nossos dados “de” e “para” o Banco de Dados por meio de
objetos Javabeans, ou seja, utilizaremos como modelo, objetos Javabeans.

Tendo em vista a extensão dessa tarefa ser maior - ao menos


maior do que foi feito até o momento - sua implementação será fixada como
tarefa para casa de forma individual. Para isso, você precisará:

 de um bom entendimento de orientação a objetos;


 do banco de dados grandeporte já criado;
 do conhecimento sobre como usar as interfaces JDBC já apresentadas;
 de um bom entendimento da arquitetura do projeto e dos designs
utilizados.

Você deverá construir o projeto delineado abaixo, que consiste


em um módulo de acesso a dados completo, utilizando-se de uma fábrica de
conexões, objetos Javabeans e o padrão DAO como interface pública de
acesso aos métodos utilitários.

Não se preocupe com as interfaces gráficas com o usuário para


operar esse módulo. Preocupe-se sim com a funcionalidade. Posteriormente,
em nosso curso, será dada a devida atenção às interfaces gráficas.

Tire todas as suas dúvidas com o professor antes de concluir por


caminhos errôneos.

A data de entrega e apresentação do projeto será definida pelo


professor.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


32 Parte 2
Como principais pontos a se notar nesse projeto e que devem chamar a
atenção do aluno, posso descrever:

As implementações de sua interface DAO deverão prover um conjunto


métodos comuns, previstos na Interface DAO e outros, caso sejam necessários,
de forma que atendam completamente às necessidades de acesso a dados
dos componentes clientes, como a classe Controle, nesse caso;

A conexão utilizada para acesso ao Banco de Dados deve ser


exclusivamente obtida por meio de sua classe ConnectionFactory;

Os dados deverão trafegar somente por meio de objetos Javabeans,


relativos às suas entidades de dados, nesse caso, representados pelas classes
Aluno, Professor e Curso.

Para tanto, analisaremos o diagrama de classes que se espera para


esse projeto, de forma superficial:

Diagrama de classes superficial do projeto de acesso a dados a ser construído

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 2 33

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


34 Parte 2

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte

Servlet (servidorzinho em tradução livre) é uma classe


Java usada para estender as funcionalidades de um servidor.
Apesar dos servlets poderem responder a quaisquer tipos de
requisições, eles normalmente são usados para estender as
aplicações hospedadas por servidores web, desta forma eles
podem ser imaginados como Applets Java que rodam em
servidores em vez de rodarem nos navegadores web. Estes
tipos de servlets são os equivalentes Java a outras
tecnologias de conteúdo Web dinâmico, como PHP e ASP.NET.
Versão 2.1.1
Parte 3 3

Preparation
3
Trocando Ideias É agora que você fala !!

Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na


capa desta parte. Isso é importante para que seu instrutor e seus colegas
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe?


 O que você não sabe?
 Porque é importante conhecer estes tópicos?
 Quais são os seus temores?
 O que você considera difícil?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


4 Parte 3

Presentation

Teoria servlet

Desde o primeiro capítulo do nosso curso, temos falado sobre os Servlets e


sobre sua função nos aplicativos web Java e no Servidor de Aplicações Java. Como
forma de consolidar em poucas palavras o conceito desse componente tão importante,
podemos conceituá-lo como:

Servlet é um componente (ou programa) Java executado dentro de um


Container Web (lembra-se da arquitetura Java EE?) responsável por
processar as requisições recebidas pela web e de coordenar as respostas a
serem enviadas ao cliente.

Como dica inicial, procure retomar os conceitos e fluxos apresentados lá na


primeira aula sobre os Servlets, de forma a ter em mente todo o workflow envolvido no
mecanismo de requisições e respostas.

Basicamente, o Servlet recebe a requisição do usuário, seja qual for o método


HTTP utilizado (GET, POST, etc), executa o processamento necessário para a
obtenção dos dados necessários à montagem da resposta, monta enfim a página de
resposta e a retorna ao cliente solicitante. Desde a chegada da requisição, já estão à
disposição do Servlet os objetos Request e Response, utilizados para o
processamento da requisição, montagem e retorno da resposta.

Todas as páginas dinâmicas criadas com Java são manuseadas, em certa


instância, direta ou indiretamente com o uso de Servlets, portanto empenhe-se em
conhecer bem esse componente, que desde já iniciaremos o estudo.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 5

A Classe HTTPServlet

Essa classe é, efetivamente, o único recurso necessário para a criação de um


Servlet. Basta estendê-la (herdá-la) que obtemos um Servlet pronto para utilizar.

Analisemos os métodos existentes nessa classe e aqueles herdados das

3
Classes e Interfaces existentes em sua árvore de herança:

Método Descrição
doGet() Executado quando a requisição recebida é HTTP GET.
doPost() Executado quando a requisição recebida é HTTP POST.
doPut() Executado quando a requisição recebida é HTTP PUT.
doDelete() Executado quando a requisição recebida é HTTP DELETE.
doHead() Executado quando a requisição recebida é HTTP HEAD.
doTrace() Executado quando a requisição recebida é HTTP TRACE.
init() Método executado uma única vez quando o Servlet é inicializado
pelo Container.
service() Método usado para gerenciar por meio de uma única entrada, todas
as requisições recebidas, independentes de método HTTP.
Raramente deverá ser sobrescrito.
destroy() Chamado quando o Container inicia o processo de destruição do
Servlet. Após sua chamada, esse objeto é coletado pelo GC
(GarbageCollector).

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


6 Parte 3
Diagrama hierárquico de um Servlet:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 7

O ciclo de vida de um Servlet

O ciclo de vida do Servlet é bem simples de ser compreendido: existe apenas


um estado principal: inicializado. Se o Servlet não está inicializado, então ou ele está
sendo inicializado (seu construtor ou método init() sendo executados), sendo destruído
(seu método destroy() sendo executado) ou ele simplesmente não existe.

Ciclo de vida de um Servlet.

Uma importante observação a ser feita e que deve estar constantemente sob
atenção do desenvolvedor é que o Container cria somente uma instância de cada
Servlet declarado. Para cada requisição é criada uma nova thread sobre a mesma
instância do Servlet. Logo, Servlets NÃO CONSTITUEM UM BOM LUGAR PARA SE
GUARDAR DADOS REFERENTES A USUÁRIOS EM PARTICULAR, DADA QUE A
INSTÂNCIA É COMPARTILHADA ENTRE AS REQUISIÇÕES. ALÉM DISSO NÃO HÁ
COMO SE OBTER UMA REFERÊNCIA DO SERVLET. SEU CONTROLE RESIDE NO
CONTAINER APENAS.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


8 Parte 3
Deployment Descriptor

Denomina-se de Deployment Descriptor o arquivo xml utilizado em aplicações


web Java para a configuração e descrição de componentes e características da
aplicação, de forma a nortear o Container Web com as informações necessárias.

Desde a versão Java EE 6, lançada em Dezembro/2009 pela recém adquirida


Sun Microsystems, o arquivo web.xml é opcional. Com o advento e propagação do uso
das anotações, o arquivo xml para configuração deixou de ser obrigatório.

Ocorre que essa versão ainda hoje não é largamente aplicada nas empresas,
vigorando, por vezes em grande escala, as versões que se utilizam do Java EE 5 e,
nesse caso, o aluno deve conhecer o Deployment Descriptor com uma certa liberdade
pois, independente do porte da aplicação, esse arquivo estará, invariavelmente,
presente na raiz da aplicação.

Em uma versão básica, o arquivo web.xml de uma aplicação com apenas um


Servlet criado tem a seguinte estrutura:

<?xmlversion="1.0"encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.s
un.com/xml/ns/javaee/web-
app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-
app_2_5.xsd"id="WebApp_ID"version="2.5">
<display-name>GrandePorteWebProject</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>GrandePorteServlet</display-name>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>br.com.grandeporte.servlet.GrandePorteServlet</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>GrandePorteServlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
</web-app>

Exemplo de Deployment Descriptor em uma aplicação simples.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 9

Basicamente, para cada Servlet que possuirmos em nossa aplicação, teremos


o seguinte conjunto de tags no DD para descrevê-lo:

<servlet>

<description></description><!-- OPCIONAL -->

3
<display-name>GrandePorteServlet</display-name>

<servlet-name>GrandePorteServlet</servlet-name>

<servlet-class>

br.com.grandeporte.servlet.GrandePorteServlet

</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>GrandePorteServlet</servlet-name>

<url-pattern>/servlet</url-pattern><!-- Nunca se esqueça da barra /-->

</servlet-mapping>

Tag Descrição
<servlet> Tag raiz que abre o bloco de declaração para cada Servlet da
aplicação
<servlet-name> Nome dado ao Servlet que serve somente para referenciá-lo no
próprio web.xml. Esse nome será usado como referência para o
Servlet na tag<servlet-mapping>
<servlet-class> Nome totalmente qualificado da classe que representa o respectivo
Servlet. Utiliza a mesma sintaxe que o utilizado para importar
classes em Java.
<servlet-mapping> Tag utilizada para mapear um determinado Servlet a um padrão de
URL, utilizando para tanto, a tag<servlet-name> que identifica o
servlet específico.
<url-pattern> Tag usada dentro da anterior para mapear um padrão de URL a ser
atendida por um determinado Servlet.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


10 Parte 3
Requisição e Resposta

Neste item, estudaremos a estrutura e o funcionamento dos objetos request e


response, já vistos e estudados superficialmente desde a introdução do curso.

Os referidos objetos são descritos por duas interfaces que os representam:

HttpServletRequest e HttpServletResponse.

A interface HttpServletRequest

Métodos Descrição
getAttribute(name:String):Object Retorna um Object que representa um atributo
gravado na Request.
getAttributeNames():Enumeration Retorna uma Enumeration com todos os nomes
dos atributos contidos na request.
setAttribute(name:String, Armazena um atributo na Request, recebendo seu
value:Object):void nome e valor.
removeAttribute(name:String):void Remove o atributo da Request cujo nome é
passado por parâmetro.
getParameter(name:String):String Retorna o valor String de um parâmetro cujo
nome seja o passado para o método, ou null.
getParameterMap():Map Retorna um mapa com todos os parâmetros dessa
request.
getParameterValues(name: Retorna um array de Strings contendo o valor de
String):String[] cada um dos parâmetros passados a essa Request,
ou null.
getParameterNames():Enumeration Retorna uma Enumeration de objetos String com
o nome de cada um dos parâmetros passados à
Request.
getMethod():String Retorna o nome do método HTTP usado para essa
requisição.
getHeader(name:String):String Retorna o valor em String do header especificado
por parâmetro
getCookies():Cookie[] Retorna um array com os objetos Cookie
provindos do cliente na Request.
getInputStream():InputStream Retorna um InputStream - os dados constantes do
corpo da Request como dados binários.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 11

getContextPath():String Retorna a porção da URI que indica o contexto da


Request.
getQueryString():String Retorna a porção da URI que representa os
parâmetros passados por GET, se existirem.
getRequestURI():String Retorna a porção desta URL que corresponde ao
caminho iniciado após a definição

3
getRequestURL():StringBuffer Retorna a URL completa usada para realizar a
Request.
getServletPath():String Retorna a porção da URL usada para chamar o
Servlet

Chamamos a atenção do aluno para o método getContextPath():String que é


comumente usado para fazer referência a caminhos relativos da aplicação e, dessa
forma, tornar o endereçamento dinâmico, evitando problemas caso ocorram mudanças
no Context Root da aplicação.

A interface HttpServletResponse

Métodos Descrição
setContentType(len:String):void Envia o MIME Type ao navegador do
solicitante de forma a alertá-lo sobre o tipo
de conteúdo sendo enviado.
getWriter():PrintWriter Retorna um objeto PrintWriter, um stream
pronto para enviar texto ao cliente.
getOutputStream(): Retorna um objeto ServletOutputStream, um
ServletOutputStream stream necessário para envio de dados
binários ao cliente
encodeURL(url:String):String Recebe uma URL e a retorna codificada com
o ID da sessão, se necessário.
sendRedirect(location:String):void Redireciona a response para o cliente,
encaminhando-o para a URL passada.
addCookie(cookie:Cookie):void Adiciona um cookie na Response do cliente.
addHeader(name:String, Adiciona um header na Response com o
value:String):void nome e valor especificados.
containsHeader(name:String): Verifica se existe na Response um header
boolean com o nome passado e retorna um boolean.
sendError(sc:int [, msg:String]):void Envia um erro para a Response com o status
especificado.
setStatus(sc:int):void Define o código de Status para essa
Response.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


12 Parte 3
Redirecionamento e Encaminhamento

A navegação entre componentes é tarefa extremamente importante em toda


Aplicação Web. A todo momento será preciso encaminhar uma requisição para outro
Servlet ou JSP que se encarregue de resolver o problema e retornar ao cliente. Essa
comunicação pode ser feita com a preservação dos dados passados na Request pelo
usuário e será chamada daqui adiante de encaminhamento ou Forward.

Por vezes, pode ser necessário apenas encaminhar o usuário a uma outra URL,
absoluta ou relativa, que aponte para um endereço em nossa própria aplicação ou
mesmo em outro servidor. Esse tipo de comunicação é chamado de Redirecionamento
ou Redirect e não preserva os dados passados por parâmetro na Request.

As formas de se realizar um Forward ou um Redirect são diferentes e as


veremos em breve.

Vejamos os dois métodos de forma esquemática:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 13

Forma de se realizar um Forward:

RequestDispatcher dispatcher = request.getRequestDispatcher("/servlet");

dispatcher.forward(request, response);

3
Forma de se realizar um Redirect:

response.sendRedirect("http://www.google.com.br");

Parâmetros de inicialização do Servlet

Além dos parâmetros de Request, passados por requisições como GET e


POST que podem ser enviados para um Servlet conforme Atividades anteriores, os
Servlets podem ser configurados com parâmetros de inicialização, ou init-params,
como são comumente chamados. Vejamos como ocorre essa declaração:

No Deployment Descriptor:

<servlet>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>
br.com.grandeporte.servlet.GrandePorteServlet2
</servlet-class>

<init-param>
<param-name>email</param-name>
<param-value>aluno@grandeporte.com.br</param-value>
</init-param>

</servlet>

No Servlet, de forma a recuperar o valor do parâmetro:

String email = getServletConfig().getInitParameter("email");


out.println("Email: " + email);

Os init-params dos Servlets são lidos somente uma única vez durante a
inicialização do Servlet e depois não mais. Ficam disponíveis única e exclusivamente
aos Servlets que os possuem.

Não há como acessá-los de qualquer lugar senão no Servlet que os contém.


Para criar e acessar atributos de inicialização que sejam globais, utilizamos os
Parâmetros de Inicialização do Contexto ou context-params, como são conhecidos.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


14 Parte 3
Parâmetros de Inicialização do Contexto

Parâmetros de contexto ficam disponíveis para toda a aplicação e não somente


a um determinado Servlet. Devem ser usados para valores globais de inicialização.

Como ocorre essa declaração:

<servlet>
<servlet-name>GrandePorteServlet</servlet-name>
<servlet-class>
br.com.grandeporte.servlet.GrandePorteServlet2
</servlet-class>
</servlet>

<context-param>
<param-name>email</param-name>
<param-value>aluno@grandeporte.com.br</param-value>
</context-param>

No Deployment Descriptor:

No Servlet, de forma a recuperar o valor do parâmetro:

String email = getServletContext().getInitParameter("email");


out.println("Email: " + email);

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 15

Atributos e Listeners

Atributos

Nas Atividades que fizemos até o momento não precisamos passar nenhum
valor entre diferentes componente de nossa aplicação pois utilizamos apenas Servlets

3
simples e, na maior parte das vezes, único.

Analisemos agora um problema muito comum que apresenta-se em grande


parte das situações no desenvolvimento de aplicações web: a passagem de atributos /
objetos entre diferentes Servlets ou ainda, a disponibilização de dados para acesso de
outros componentes da aplicação. Note que PARÂMETROS NÃO SÃO ATRIBUTOS!

Atributos Parâmetros
Tipos Application/context Application/contextinit
Request Request
Session Servletinit
Método setter setAttribute(Stringname, Somente via DD!
Objectvalue)
Tipo de Retorno Object String
Método getter getAttribute(Stringname) getInitParameter(Stringname)

Os três escopos de trabalho:

Context/
Request Session Application

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


16 Parte 3
Métodos da API de Atributos, presente nas interfaces: ServletContext,
HttpServletRequest e HttpSession:

 getAttribute(String)
 setAtribute(String, Object)
 removeAttribute(String)
 getAttributeNames()

Listeners

Listeners são objetos com a capacidade de serem notificados quando uma


ação ocorre com a aplicação web. São usados para a execução de código
customizado quando algum evento ocorre. Mas que tipo de eventos podem ser
almejados por um Listener?

Alguns deles: inicialização e destruição de um Context, adição ou remoção de


um atributo no Context, Request ou Session, etc.

São ao total oito interfaces Listeners à disposição do desenvolvedor Java:

 javax.servlet.ServletContextAttributeListener;
 javax.servlet.http.HttpSessionListener;
 javax.servlet.ServletRequestListener;
 javax.servlet.ServletRequestAttributeListener;
 javax.servlet.http.HttpSessionBindingListener;
 javax.servlet.http.HttpSessionAttributeListener;
 javax.servlet.ServletContextListener;
 javax.servlet.http.HttpSessionActivationListener;

Para criar um Listener, são necessárias, basicamente, duas ou três classes


Java e o Deployment Descriptor:

1) O Listener:

public class MeuListener implements ServletRequestListener {

public void requestDestroyed(ServletRequestEvent arg0) {


System.out.println("Request Destruída!");
}
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("Nova request feita!");
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 17

2) Um Servlet:

public class TestandoListener extends HttpServlet {

protected void doGet(HttpServletRequest request,


HttpServletResponse response) throws ServletException,

3
IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();

out.println("<HTML>");
out.println("<HEAD><TITLE>Testando listeners!</TITLE>" +
"</HEAD>");
out.println("<BODY>");
out.println("<h1>Grande Porte - Java Level 2</h1>");
out.println("<hr><br /><br>");
out.println("<h4>Veja no console do Servidor se o " +
"listenerouviuessa Request</h4>");
out.println("</BODY>");
out.println("</HTML>");
}
}

3. O Deployment Descriptor

<listener>
<listener-class>
br.com.grandeporte.listeners.MeuListener
</listener-class>
</listener>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


18 Parte 3

Teoria Java server pages

Até o momento estivemos usando Servlets diretamente para a montagem


dinâmica de páginas para o retorno ao cliente. Esse processo, como vimos, pode ser
bastante entediante e limitador, dada a complexidade para se inserir as enormes
quantidades de texto necessárias em métodos println().

As JSPs surgiram por meio da ideia de realizar processo produtivo inverso: ao


invés de inserir HTML em código Java para a geração das páginas, por que não inserir
Java em uma página HTML?

Na realidade, toda JSP é convertida em Servlet pelo Container nos bastidores.


Um Servlet que não é escrito pelo desenvolvedor, mas sim pelo Container e, portanto,
não deve ser alterado diretamente pelo desenvolvedor. Esse Servlet é criado e
compilado no primeiro acesso realizado à página e, posterior a esse acesso, o
Container utiliza-se da instância já compilada.

Vejamos um primeiro exemplo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 19

<%@page language="java" contentType="text/html; charset=ISO-8859-1"


pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>

3
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Minhaprimeira JSP</title>
</head>
<body>
<h1>Primeiroteste com JSPs</h1>
<br/>

<%
out.println("Imprimindo em HTML por meio de comandos" +
" Java!");
%>

<h3>Obtendo a data completa do dia de hoje:</h3>


<h4>
<%out.println(new java.util.Date()); %>
</h4>

</body>
</html>

Observe no exemplo acima que usamos a notação <% ... %> para inserir
código Java na página HTML. Esse trecho de código inserido é chamado de scriptlet e
pode aparecer quantas vezes forem necessárias na página, podendo inclusive ter sua
abertura e fechamento permeada por código HTML.

Note também que utilizamos o out.println() sem instanciar um objeto PrintWriter


como fazíamos com os Servlets. Ocorre que esse objeto já vem instanciado por
padrão no ato da construção da JSP pelo Container, estando lá disponível para uso do
desenvolvedor.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


20 Parte 3
Usando Expressions

Quando escrevendo JSPs, torna-se muito comum o uso de out.println().Além


disso, no ciclo de desenvolvimento para a web é muito comum ocorrer a intervenção
de um designer para o desenho gráfico de sua página e identidade visual que NÃO
conhece Java. Por esses e outros motivos, existem "atalhos" para uso nas JSPs que
facilitam a interação com designers e agilizam a vida do desenvolvedor.

Um desses recursos são as Expressions:

Código em Scriptlets:

<%
out.println("Imprimindo em HTML por meio de comandos Java!");
%>

Código em Expressions:

<%=newjava.util.Date() %>

Note que o código é incluído em um bloco de sintaxe muito mais enxuto. É


muito simples de compreender:

<%= O que estiver aqui será argumento de um out.println() e impresso na tela! %>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 21

Practice
3
Atividade Revisão aos pares

Criando o primeiro projeto Java Web com Servlets

1. Crie um novo projeto do tipo Dynamic Web Project no Eclipse de nome


GrandePorteWebProject. Como estamos trabalhando agora na versão Java
EE, verifique se o seu Eclipse está com a perspectiva Java EE selecionada. A
opção para alterar a perspectiva da IDE está localizada no canto superior
direito da área de trabalho do Eclipse:

Seletor de perspectivas do Eclipse.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


22 Parte 3
Ao ser apresentada a tela de configuração inicial do seu projeto, esteja certo de
que as suas configurações estejam na forma abaixo apresentada, tendo o Apache
Tomcat 7 como Target Runtime. Selecione, nesta primeira versão, o Dynamic Web
Module version como 3.0. Posteriormente discutiremos as implicações e opções
disponíveis neste item. Mantenha as demais configurações com os valores default e
clique em Next duas vezes.

Criação de um novo Dynamic Web Project.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 23

2. Você receberá em seguida a tela para configuração do Context Root, parte


importantíssima de seu projeto. O Context Root é exatamente a porção da
URL que será utilizada para a identificação de seu projeto. Utilizaremos a
palavra "web" em vez de aceitar o padrão do Eclipse, que é o próprio nome do
projeto.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


24 Parte 3
3. Tome um tempo para analisar a estrutura de arquivos do seu projeto. Essa
estrutura contempla algumas pastas das quais discorreremos e utilizaremos
durante todo ocurso:

Project Explorer do projeto web criado.

4. Crie um novo Servlet em seu projeto, clicando no item de menu


FileNewServlet ou clicando com o botão direito/secundário do mouse no
nome do projeto e escolhendo NewServlet. Dê o nome de
GrandePorteServlet, conforme a configuração mostrada na imagem abaixo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 25

Criação de um novo Servlet

Perceba que o Servlet nada mais é do que uma classe Java que tem como
superclasse HttpServlet. Note também que estamos utilizando como pacote o padrão
de domínio invertido, como fizemos nos capítulos anteriores.

Em seguida, clique em Next duas vezes para obter a próxima janela auxiliar de
configuração do Servlet. Essa janela refere-se a itens de configuração presentes no
Deployment Descriptor, o arquivo web.xml presente em seu projeto.

Dentre os itens apresentados, um de grande importância é a configuração de


URL Mappings, os mapeamentos de URL para esse Servlet especificamente. É nesse
item que configuramos o endereço de URL para o qual esse componente responderá,
conforme o método usado.

Usaremos neste nosso projeto, o padrão "/servlet". Por padrão o Eclipse


sugere o mapeamento: "/<Nome do Servlet>", que em nosso caso tornar-se-ia um
endereço muito extenso. Note a presença do caractere " / ". Se a barra não estiver
presente nesse mapeamento, você obterá um erro.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


26 Parte 3

Configuração de parâmetros do Servlet, como "URL Mapping".

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 27

5. Criado seu Servlet, veja o código padrão gerado pelo Eclipse e, neste
momento, apague todos os comentários e javadoc existentes, de forma a
manter-se apenas com o código essencial para o template. Digite o seguinte
código em seu novo Servlet e preste atenção em cada linha e trecho de código.

1 @WebServlet("/servlet")

3
2 public class GrandePorteServlet extends HttpServlet {

3 protected void doGet(HttpServletRequest request, HttpServletResponse

4 response) throws ServletException, IOException {

5 response.setContentType("text/html");

6 PrintWriter out = response.getWriter();

7 out.println("<HTML>");

8 out.println("<HEAD><TITLE>Grande Porte - MeuprimeiroServlet " +

9 <"/TITLE></HEAD>");

10 out.println("<BODY>");

11 out.println("<h1>Grande Porte - Java Level 2</h1>");

12 out.println("<hr><br /><br>");

13 out.println("<h2>Vocêacessou o Servlet+

14 GrandePorteServlet!</h2><br />");

15 out.println("Horárioatual: " + new Date());

16 out.println("</BODY>");

17 out.println("</HTML>");

18 }

19 protected void doPost(HttpServletRequest request, HttpServletResponse

20 response) throwsServletException, IOException {

21 }

Código completo do ServletGrandePorteServlet.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


28 Parte 3
6. Agora execute seu programa, clicando com o botão direito/secundário do
mouse e escolhendo RunAsRunon Server. Observe a URL na barra de
endereços do navegador. Ela deve estar com o seguinte endereço, dada a
configuração que criamos:

http://localhost:8080/web/servlet:

Janela do navegador com a saída após execução do programa.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 29

Revisão aos pares

3
Atividade

Prática com os métodos da interface


HttpServletRequest.

1. Crie um novo projeto no Eclipse com o nome GrandePorteRequestMethods e,


dentro desse projeto, crie um Servlet com o nome de RequestMethodsServlet.
Digite o seguinte código em seu novo Servlet:

1 @WebServlet("/servlet")
2 public class RequestMethodsServlet extends HttpServlet {
3 protected void doGet(HttpServletRequest request, HttpServletResponse
4 response) throws ServletException, IOException {
5 response.setContentType("text/html");
6 PrintWriter out = response.getWriter();

7 out.println("<HTML>");

8 out.println("<HEAD><TITLE>Grande Porte - Java Level 2" +

9 "</TITLE></HEAD>");

10 out.println("<BODY>");
11 out.println("<h1>Grande Porte - Java Level 2</h1>");

12 out.println("<hr><br />");

13 out.println("<h2>Métodos da Interface HttpServletRequest" +

14 "</h2><br />");

15 out.println("getMethod(): " + request.getMethod() + "<br / >");

16 out.println("getContextPath(): " + request.getContextPath()+"<br/ >");

17 out.println("getQueryString(): "+ request.getQueryString() +"<br / >");

18 out.println("getRequestURI(): " + request.getRequestURI() + "<br / >");

19 out.println("getRequestURL(): "+ request.getRequestURL() +"<br / >");

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


30 Parte 3
20 out.println("getServletPath(): "+ request.getServletPath() +"<br / >");

21 out.println("getServerName(): "+ request.getServerName() +"<br / >");

22 out.println("getServerPort(): " + request.getServerPort() + "<br / >");

16 out.println("</BODY>");

17 out.println("</HTML>");
18 }

19 protected void doPost(HttpServletRequest request, HttpServletResponse

20 response) throws ServletException, IOException {

21 }

2. Analise a saída de cada método e compare o resultado com a URL original


para compreender a função da API desta Interface

3. Veja que, em seu resultado, o retorno do método getQueryString() aparece


como null. Na verdade, em nenhuma de nossas chamadas para esse projeto
passamos qualquer argumento para o servidor, portanto não há query string.

Acrescente ao final da nossa URL (logo após o nome do Servlet sem barra final
"/") o trecho:

?id=1&nome=Aluno&sobrenome=GrandePorte

e veja que agora o método getQueryString() possui um retorno:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 31

Atividade Trabalho em dupla

Passagem de parâmetros com formulários. 3

Nesta atividade, exploraremos o envio de parâmetros por meio do método


POST a um Servlet e a montagem de uma nova página com os parâmetros recebidos.

Na primeira requisição, o Container devolve uma página HTML estática ao


usuário, com um formulário HTML para ser preenchido.

Quando o usuário clica em Enviar, uma nova requisição é enviada ao servidor


com os parâmetros do formulário sendo passados por meio do método HTTP POST.
Esses dados então são usados para montar a nova página que é devolvida ao usuário.
Veja um esquema emblemático dessa segunda requisição abaixo:

1. Crie um novo projeto web no Eclipse com o nome de GrandePorteWebProject2.


Lembre-se de configurar seu projeto para que use o Dynamic web module
version 2.5 logo na primeira janela de configuração do seu projeto, pois iremos
utilizar o Deployment Descriptor na forma XML:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


32 Parte 3
2. Crie uma página HTML no seu projeto, clicando sobre o projeto com o botão
direito do mouse e escolhendo New  HTML File. Certifique-se de que o
arquivo seja criado na raiz da pasta WebContent e dê o nome de index.html.
Digite o seguinte conteúdo em sua nova página:

<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01


Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cadastro de Alunos</title>
</head>
<body>
<h1>Bemvindo ao Cadastro de Alunos!</h1>
<hr>
<h3>Entre com seus dados abaixo:</h3>
<form action="servlet" method="post">
<label for="nomeAluno">Nome: </label>
<input type="text"name="nomeAluno"id="nomeAluno"size="50">
<br/>
<br/>
<label for="seletorCurso">Curso: </label>
<select id="seletorCurso"name="seletor">
<option>...</option>
<option>Lógica de Programação</option>
<option>Java Level 1</option>
<option>Java Level 2</option>
<option>Cobol Level 1</option>
</select>
<br/>
<br/>
<input type="submit"value="Cadastrar"/>
<br/>
<br/>
<hr/>
</form>
</body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 33

Essa página possui um formulário simples com alguns controles que receberão
dados do usuário e os enviarão ao servidor como parâmetros. Note que na tag<form>
configuramos o método de envio como "post" e o action como "servlet". O atributo
"action" deve receber o ServletPath para chamada. Em nosso caso, esse valor será o
"url-pattern" que configurarmos em nosso arquivo web.xml.

3. Crie um servlet em sua aplicação com o nome de GrandePorteServlet2 em um


pacote denominado br.com.grandeporte.servlet e certifique-se de que ele
possua o código abaixo:
3
package br.com.grandeporte.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GrandePorteServlet2 extends HttpServlet {


private static final long serialVersionUID = 1L;

protected void doPost(HttpServletRequest request,


HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");

String nomeDoAluno = request.getParameter("nomeAluno");


String cursoDoAluno = request.getParameter("seletor");

PrintWriter out = response.getWriter();


out.println("<HTML>");
out.println("<HEAD><TITLE>Grande Porte Java Level " +
"2</TITLE></HEAD>");
out.println("<BODY>");
out.println("<h1>Grande Porte - Java Level 2</h1>");
out.println("<hr><br /><br>");
out.println("<h2>Aluno Cadastrado com sucesso!</h2> " +
<br />");
out.p"rintln("Nome do aluno: " + nomeDoAluno + "<br />");
out.println("Curso do aluno: " + cursoDoAluno);
out.println("</BODY>");
out.println("</HTML>");
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


34 Parte 3
Note, no código acima que estamos recuperando ou obtendo o valor de dois
parâmetros passados por essa requisição e armazenando-os em variáveis locais:

String nomeDoAluno = request.getParameter("nomeAluno");

String cursoDoAluno = request.getParameter("seletor");

Recuperamos o valor por meio do atributo "name" utilizado no HTML e aqui


passado como parâmetro para o método getParameter(String name) como localizador.

4. Verifique o resultado de ambas as páginas criadas e a interação com o usuário:

Página Inicial:

Página Final:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 35

Atividade Trabalho em dupla

Testando Listeners. 3

1. Crie um novo projeto no Eclipse chamado GrandePorteTesteListeners. Crie


nesse projeto um novo Listener e um novo Servlet conforme listas do exemplo acima.

2. Teste sua execução e observe a saída no Console do Servidor.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


36 Parte 3

Performance

Atividade Todos juntos

Projeto web de maior complexidade com


redirecionamento e encaminhamento, utilizando-se de
Servlets e JSPs.

1. Crie um novo projeto Web no Eclipse de nome


GrandePorteWebProject3 e lembre-se de manter o seu Dynamic Web Module version
em 2.5.

2. Crie um novo JSP com o nome de index.jsp e adicione o seguinte conteúdo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 37

<%@page language="java"contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>

3
<meta http-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>Formulário Inicial</title>
</head>
<body>
<h1>Bemvindo ao Cadastro de Alunos!</h1>
<hr>
<h3>Entre com seus dados abaixo:</h3>
<form action="captura" method="post">
<label for="nomeAluno">Nome: </label>
<input type="text"name="nomeAluno"id="nomeAluno"size="50">
<br/>
<br/>
<label for="seletorCurso">Curso: </label>
<select id="seletorCurso"name="seletor">
<option>...</option>
<option>Lógica de Programação</option>
<option>Java Level 1</option>
<option>Java Level 2</option>
<option>Cobol Level 1</option>
</select>
<br/>
<br/>
<label for="group1">Sexo: </label>
<input type="radio"name="group1"value="masculino">Masculino
<input type="radio"name="group1"value="feminino"checked>Feminino
<br/>
<br/>
<inputtype="submit"value="Cadastrar"/>
<br/>
<hr/>
</form>

</body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


38 Parte 3

3. Crie um novo Servlet chamado CapturaDados, mapeado para o


endereço/captura com o seguinte código:

packagebr.com.grandeporte.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CapturaDadosextendsHttpServlet {

protected void doPost(HttpServletRequest request,


HttpServletResponse response) throws ServletException,
IOException {

String nome = request.getParameter("nomeAluno");


Int idade =
Integer.parseInt(request.getParameter("idadeAluno"));
String curso = request.getParameter("seletor");
String sexo = request.getParameter("group1");

if (idade< 18 || idade> 65){


response.sendRedirect(request.getContextPath() +
"/erro.jsp?erro=idade");
} else {
request.setAttribute("nome", nome);
request.setAttribute("idade", String.valueOf(idade));
request.setAttribute("curso", curso);
request.setAttribute("sexo", sexo);

RequestDispatcher dispatcher =
request.getRequestDispatcher("/exibeDados.jsp");
dispatcher.forward(request, response);
}
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 39

4. Crie duas páginas jsp: uma chamada erro.jsp e outra chamada exibeDados.jsp

erro.jsp:

<%@page language="java"contentType="text/html; charset=ISO-8859-1"


pageEncoding="ISO-8859-1"%>

3
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01
Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=ISO-
8859-1">
<title>Erro no formulário</title>
</head>
<body>
<h1>Erro nos dados passados!</h1>
<br/>
<p><h3>Descrição: </h3>
Você inseriu dados inválidos para
<%=request.getParameter("erro") %>.
<br/>
<br/>
</body>
</html>

exibe Dados.jsp

<%@pagelanguage="java"contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01
Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type"content="text/html; charset=UTF
-8">
<title>Insert title here</title>
</head>
<body>
<h1>Cadastro efetuado com sucesso!</h1>
Nome: <%=request.getAttribute("nome") %>
<br/>
Idade: <%=request.getAttribute("idade") %>
<br/>
Curso: <%=request.getAttribute("curso") %>
<br/>
Sexo: <%=request.getAttribute("sexo") %>
<br/>
<br/>
</body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


40 Parte 3
5. Rode o programa e veja o Forward / Redirect em funcionamento, conforme a
idade inserida no campo de texto correspondente.

6. Adicione um parâmetro de inicialização ao Servlet que mostre o e-mail do


administrador e o apresente junto com os demais dados na página exibe Dados.jsp.

7. Refatore sua aplicação para que ela trabalhe com um objeto javabean em
vez de usar atributos primitivos. Altere o código onde for necessário.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 3 41

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


42 Parte 3

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte

JavaServer Pages (JSP) é uma tecnologia que ajuda os


desenvolvedores de software a criarem páginas web geradas
dinamicamente baseadas em HTML, XML ou outros tipos de
documentos. Lançada em 1999 pela Sun Microsystems, JSP é
similar ao PHP, mas usa a linguagem de programação Java.
Versão 2.1.1
Parte 4 3

Preparation

Trocando Ideias É agora que você fala !! 4


Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na
capa desta parte. Isso é importante para que seu instrutor e seus colegas
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe ?


 O que você não sabe ?
 Porque é importante conhecer estes tópicos ?
 Quais são os seus temores ?
 O que você considera difícil ?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


4 Parte 4

Presentation

Teoria filtros

Filtros são componentes especiais introduzidos à API Servlet em sua versão


2.3. Compõem um mecanismo de interceptação de Requests ou Responses, de forma
que o desenvolvedor possa realizar ações nesses eventos.

Efetivamente, os filtros interceptam e disponibilizam a request ou a response


antes que sejam encaminhadas aos seus respectivos destinos: servlet ou usuário.

O Container é quem gerencia a criação e extinção desses componentes,


cabendo ao desenvolvedor apenas delinear suas aplicações e encaminhamentos de
forma eficaz.

Filtros podem ser encadeados, sendo este um recurso muito útil quando
quisermos separar as funções de cada filtro aplicados a uma mesma Request.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 5

Algumas possíveis aplicações para os filtros:

 Autenticação: é possível verificar se o usuário solicitante está autenticado ou


não antes de encaminhar a request para o servlet correspondente, tomando
ação diversa quando necessário;
 Log: caso haja interesse, um filtro pode ser usado para criar um log de todas
as requests recebidas ou responses encaminhadas;

4
 Validação: existe a possibilidade de validar dados provindos na request, como
parâmetros e encaminhar o usuário para diferentes servlets, dependendo de
suas escolhas;
 Conexão: é possível realizar uma conexão com o Banco de Dados assim que
a request chegar e repassar após ao servlet, já com a configuração de acesso
ao Banco de Dados feita. Essa não é uma prática muito recomendada, mas
ainda assim fica a lembrança.

A interface Filter

Para criarmos um filtro, precisamos criar uma classe que implemente a


interface Filter e, portanto todos os seus métodos.

Analisando os métodos da interface Filter:

Métodos Descrição
init(fc:FilterConfig):void throws Método chamado somente uma vez,
ServletException quando da subida do Container.
destroy():void Método executado somente quando o
Container é desativado.
doFilter(request:ServletRequest, Método principal onde reside a lógica do
response:ServletResponse, filtro. Chamado a cada interceptação feita.
chain:FilterChain):void

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


6 Parte 4
Declaração no Deployment Descriptor

Assim como os Servlets, os filtros devem ser declarados no web.xml para que
sejam mapeados e controlados pelo Container.
Da mesma forma que os Servlets, os filtros podem ser declarados por meio de
anotações na classe que os implementam desde a versão Java EE 6:

@WebFilter(...parâmetros...)

Tag Descrição
<filter> Tag raiz que abre o bloco de declaração para cada filtro da
aplicação
<filter-name> Nome dado ao filtro que serve somente para referenciá-lo no
próprio web.xml. Esse nome será usado como referência
para o filtro na tag <filter-mapping>
<filter-class> Nome totalmente qualificado da classe que representa o
respectivo filtro. Utiliza a mesma sintaxe que o utilizado para
importar classes em Java.
<filter-mapping> Tag utilizada para mapear um determinado filtro a um padrão
de URL, utilizando para tanto, a tag <filter-name> que
identifica o filtro específico.
<url-pattern> ou Tag usada dentro da anterior para mapear um padrão de
<servlet-name> URL ou um servlet de destino/origem a ser atendido por um
determinado filtro.
<dispatcher> Tag usada para identificar quais origens de solicitações
deverão ser interceptadas. Possibilidades: REQUEST,
FORWARD, INCLUDE e ERROR.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 7

Um exemplo do bloco de tags no arquivo web.xml que representa um filtro:

<filter>
<display-name>MeuFiltro</display-name>
<filter-name>MeuFiltro</filter-name>
<filter-class>br.com.grandeporte.filter.MeuFiltro</filter-class>
</filter>
<filter-mapping>
<filter-name>MeuFiltro</filter-name>

4
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

Como se parece um filtro:

package br.com.grandeporte.filter;

import java.io.IOException;
import java.util.Date;
import javax.servlet.http.*;
import javax.servlet.*;

public class MeuFiltro implements Filter {

public void destroy() {


System.out.println(new Date() + " - Filtro sendo destruído!");
}

public void doFilter(ServletRequest request,


ServletResponse response, FilterChain chain)
throws IOException, ServletException {

System.out.println(new Date() + "Filtro sendo executado após" +


" uma request!");
HttpServletRequest req = (HttpServletRequest)request;
System.out.println("URL interceptada pelo filtro: " +
req.getRequestURI());

//prossegue na chamada ao Servlet devido ou ao próximo filtro


chain.doFilter(request, response);
}

public void init(FilterConfig fConfig) throws ServletException {


System.out.println(new Date() + " - Filtro sendo criado!");
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


8 Parte 4

Teoria Trabalhando com cookies

Grande parte das pessoas com alguma experiência em navegação na web já


ouviu uma vez ou outra falar em Cookies. Mas o que são Cookies?

Cookies nada mais são do que pequenas porções de dados que são
armazenados na máquina do usuário da aplicação, podendo ser manipulados pelo
aplicativo web, caso haja permissão do usuário para tanto.

Esses pequenos conjuntos de dados são muito usados para se obter alguma
informação útil acerca do usuário logado ou acessando a aplicação web como, usuário
e senha, código de identificação da sessão do usuário, algum texto que represente as
preferências daquele usuário acerca de algum assunto ofertado na aplicação web,
entre outras tantas.

Em Java, esses "pequenos conjuntos de dados" são representados por um


objeto específico, uma instância da classe javax.servlet.http.Cookie. Esses objetos
podem ser enviados para o cliente por meio do já conhecido objeto
HttpServletResponse e recuperados por meio de um objeto HttpServletRequest.

Esse acesso é feito por meio dos métodos:


 na classe HttpServletRequest:
o getCookies():Cookies[] - Retorna um array de todos os objetos Cookie
que o cliente enviou na requisição;

 na classe HttpServletResponse:
o addCookie(cookie:Cookie):void - Adiciona o cookie passado como
parâmetro na resposta.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 9

A Classe javax.servlet.http.Cookie

Exemplo da utilização de Cookies em um Servlet:

Métodos Descrição
getComment():String Métodos de acesso do atributo comment, que
setComment(comment:String):void descreve o Cookie e seu propósito

4
getDomain():String Métodos de acesso que define o domínio onde
setDomain(domain:String):void todos os componentes terão acesso ao cookie
getMaxAge():int Métodos de acesso para o tempo de vida do
setMaxAge(maxAge:int):void Cookie, em segundos. -1 significa que o
cookie deve expirar assim que o browser for
fechado.
getName():String Métodos de acesso ao atributo name do
setName(name:String):void cookie, usado como identificador.
getPath():String Métodos de acesso à URL de onde todos os
setPath(path:String):void componentes poderão acessar o cookie.
getSecure():boolean Define se será utilizado https para acesso ao
setSecure(secure:boolean):void Cookie.
getValue():String Métodos de acesso ao atributo value do
setValue(value:String):void Cookie, efetivamente o dado que esse cookie
carrega consigo.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


10 Parte 4

package br.com.grandeporte.servlet;

import java.io.*;
import javax.servlet.ServletException;
import javax.servlet.http.*;

public class CookiesServlet extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse


response) throws ServletException, IOException {
doService(request, response);
}

protected void doPost(HttpServletRequest request,


HttpServletResponse response) throws ServletException, IOException {
doService(request, response);
}

protected void doService(HttpServletRequest request,


HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");

String usuario = "";


String senha = "";

Cookie[] cookies = request.getCookies();

if (cookies != null) {
for (int i = 0; i < cookies.length; i++){
if (cookies[i].getName().equals("usuario")) {
usuario = cookies[i].getValue();
}

if (cookies[i].getName().equals("senha")){
senha = cookies[i].getValue();
}
}
}

PrintWriter out = response.getWriter();


out.println("<HTML>");
out.println("<HEAD><TITLE>Autenticação com
Servlets</TITLE></HEAD>");
out.println("<BODY>");
out.println("<h1>Grande Porte - Cookies</h1>");
out.println("<h3>Usuário: " + usuario + "</h3> <br />");
out.println("<h3>Senha: " + senha + "</h3> <br />");
out.println("</BODY>");
out.println("</HTML>");
out.close();
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 11

Teoria Gerenciando sessões

Desde o início do curso vem sendo dito que o protocolo HTTP não mantém
estado assim como as aplicações web. Isto é, não o faz automaticamente, sendo esta

4
tarefa do desenvolvedor.

Imagine, caso não houvesse solução razoável para a manutenção do estado,


na seguinte situação: o usuário insere seu login e senha e clica em "Acessar". Neste
momento, o servidor, pesquisando seus dados, encontra o cadastro e o fornece a
página desejada mas, a cada nova requisição, o usuário seria instado a interpor seu
usuário e senha novamente.

Para que esse problema seja contornado, torna-se necessário colocar dados
como os do exemplo acima em uma área da aplicação que seja acessível por outros
componentes e que persista entre as requisições dos clientes. Essa área é
denominada de sessão e representa uma área de armazenamento persistente
enquanto durar a estada do usuário na aplicação.

Algumas considerações fazem-se necessárias agora, mas serão


complementadas com mais algumas até o fim do capítulo:

 As sessões são individuais, existe uma para cada cliente conectado;


 As sessões persistem a diversas requisições mas, uma vez encerrada, seus
dados se perdem caso não sejam persistidas em um Banco de Dados, arquivo
físico ou transferidas para um contexto maior, como o de aplicação (Context).

O container utiliza-se de um identificador único para localizar e mapear os


usuários e suas respectivas sessões. Esse identificador é encaminhado via Response,
armazenado no cliente via Cookie (geralmente, mas nem sempre) e recuperado via
Request. O formato desse identificador varia conforme o Container Java / Servidor de
Aplicações sendo utilizado. Para o caso do Apache Tomcat, esse identificador parece-
se com algo como:

JSESSIONID=AS435H878JG12477

Ocorre que as estratégias para gerenciamento da identificação do usuário são


variadas e dependem da situação de acesso permitido pelo usuário e das preferências
do Container:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


12 Parte 4
Estratégia Descrição
Cookies Cookies, já estudados, são trocados pelo header da request e
response.
Reescrita de Nessa estratégia, o ID de identificação da sessão é acoplado à
URL URL de todas as requisições e links nas páginas.
Campos O servidor insere campos ocultos nos FORMs como maneira de
Escondidos manter controle da sessão.
(Hidden fields)
SSL (Secure As chaves de sessão geradas pelo SSL em conexões HTTPS
Sockets Layer) podem ser usadas como identificação para a sessão do usuário.

Uma sessão em Java, é representada pela classe


javax.servlet.http.HttpSession, que possui alguns métodos que devem ser de
conhecimento do desenvolvedor, apresentados daqui adiante.

Método Descrição
getSession():HttpSession Retorna a sessão já existente com essa
request ou cria uma nova, caso não
exista nenhuma.
getSession(create:Boolean):HttpSession Retorna a sessão já existente com essa
request, ou cria uma nova se não existir
uma e o argumento create for igual a
true. Caso o argumento seja false e não
exista nenhuma sessão associada,
retorna null.

Criada a sessão, podemos obter a data de criação e o Id dela por meio dos
métodos:

Método Descrição
getId():String Retorna uma String com o identificador único da sessão
criado pelo Container.
getCreationTime():long Retorna a data de criação da sessão em milisegundos que
podem ser convertidos em um objeto Date.

Métodos relacionados com a utilização de atributos na sessão:

Método Descrição
getAttribute(name:String):Object Retorna o objeto associado ao nome
passado.
getAttributeNames():Enumeration Retorna uma Enumeration com os nomes
dos atributos existentes na sessão.
setAttribute(name:String, Adiciona o objeto na sessão, associado ao
valor:Object) nome passado no parâmetro do método
removeAttribute(name:String):void Remove o objeto especificado.
Invalidando uma sessão

Uma sessão deve ser invalidada quando não estiver mais em uso, de forma a
preservar recursos no servidor. Comumente, ocorre quando o usuário clica no botão

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 13

"Sair" da sua aplicação ou quando permanece muito tempo inativo. Podemos nos
utilizar de duas formas para invalidar sessões:

 Explicitamente, utilizando-se do método invalidate():void;


 Pela configuração do tempo máximo de inatividade antes de invalidar
automaticamente a sessão. Nesse caso, podemos usar o método
setMaxInactiveInterval(interval:int):void ou configurar esse tempo no
Deployment Descriptor, como veremos a seguir.

Método
invalidate():void
Descrição
Invalida a sessão e desassocia todos os objetos
que possuía.
4
setMaxInactiveInterval(interval:int): Atribui o valor máximo que a sessão poderá
void ficar inativa antes que seja invalidada. Esse
valor é definido em segundos.
getLastAccessedTime():long Retorna a representação em long da data da
última requisição deste cliente.

Nó que configura o timeout da sessão. Esse nó deve estar diretamente na raíz


do web.xml, subordinado diretamente ao nó <web-app></web-app>. Ao contrário do
método equivalente delineado acima, setMaxInactiveInterval(interval:int):void,
nesse caso o tempo deve ser passado em MINUTOS.

<session-config>

<session-timeout>10</session-timeout>

</session-config>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


14 Parte 4
Métodos relacionados com o Gerenciamento da Sessão sem Cookies:

Método Descrição
encodeURL(url:String):String Adiciona o id da sessão se necessário, ou seja, se a
recepção de cookies estiver desabilitada na
máquina do usuário.
encodeRedirectURL(url:String) Equivalente ao método acima para ser usado em
caso de sendRedirect().

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 15

Teoria Mais jsp

Usando comentários

Comentários em JSP podem ser feitos utilizando-se a sintaxe HTML ou a

4
sintaxe própria da JSP:

<!-- Este é um comentário HTML e não será processado -->

<%-- Este é um comentário JSP e não será processado --%>

A diferença entre eles é que o HTML aparece na página enviada ao browser e


o JSP não, fica no servidor.

Usando Declarações

Declarações em JSP são blocos de código Java que podem conter declarações
de variáveis e métodos que serão utilizados no escopo da classe.

Quando o JSP é convertido em um Servlet, as declarações transformam-se em


atributos e métodos.

São declaradas entre as tags: <%! ... %>

Exemplo:

<%! String teste = "Este será um atributo de instância";


public String getTeste(){
return teste;
}
%>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


16 Parte 4
Usando Diretivas

São instruções de configuração JSP em geral. São usadas para importar


classes, configurar o tipo de saída, incluir componentes ou outros arquivos, etc.

 Diretivas Page:

O que torna esta diretiva um pouco complicada é que ela possui onze atributos
diferentes. Observe primeiro como é a sua sintaxe:

<%@ page atributo1=”valor1” atributo2=”valor2” atributo3=”valor3” ... %>

Por possuir múltiplos atributos, é permitido que se declare várias diretivas


numa mesma página, porém o único atributo que pode ser repetido é o import, que
veremos mais a diante.

o Atributo Info

Usado para inserir informações sumarizadas da página, não havendo


restrições ao seu tamanho. Exemplo:

<%@ page info=”Estudo sobre Diretivas JSP, Prof. Cristiano Neves, 2006” %>

o Atributo Language

Usado, em geral, para especificar Java como a linguagem de criação de script


para a página. Exemplo:

<%@ page language=”java” %>

o Atributo ContentType

Este atributo indica qual o tipo MIME (Multipurpose Internet Mail Extensions) da
resposta está sendo gerada pela JSP.

<%@ page contentType=”text/html” %>

o Atributo Extends

Serve para indicar a super classe que será usada pelo container no momento
de tradução da página em um Servlet Java.

<%@ page extends=”com.taglib.jsp.primeirapagina” %>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 17

o Atributo Import

Com o atribuo import, diferente do extends, é capaz de estender um conjunto


de classes Java que poderão ser usadas nas páginas JSPs.

<%@ page import=”java.util.List” %>

o Atributo Session

Session é do tipo boolean, indica se a página está participando ou faz parte do

4
gerenciamento de sessão.
<%@ page session=”true” %>

o Atributo Buffer

Responsável por controlar a saída bufferizada para uma página JSP. Se for
modificado para “none” o conteúdo de uma JSP é passado instantaneamente à
resposta HTTP. O tamanho do buffer é descrito em kilobytes.

<%@ page buffer=”12kb” %> ou <%@ page buffer=”none” %>

o Atributo AutoFlush

Semelhante ao Buffer, também é responsável por controlar a saída buferizada,


mais exatamente o comportamento do container JSP quando já esteja cheio o Buffer
de saída. Neste caso é esvaziado automaticamente o Buffer de saída e o conteúdo
enviado para o servidor HTTP que transmite para o Browser responsável pela
solicitação.

<%@ page autoFlush=”true” %>

o Atributo isThreadSafe

Quando uma página JSP é compilada em um Servlet, ela deve ser capaz de
atender a múltiplas solicitações. Para isso deve-se utilizar o atributo isThreadSafe,
caso contrário é necessário defini-lo como “false”.

<%@ page isThreadSafe=”false” %>

o Atributo errorPage

ErrorPage indica uma página alternativa que será exibida caso aconteça um
erro não previsto durante o processamento de uma página JSP no container.

<%@ page errorPage=”/trabalho/paginas/erro.jsp” %>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


18 Parte 4
o Atributo isErrorPage

Responsável por definir uma página JSP que servirá como a página de erro
padrão para um grupo de páginas JSP.

<%@ page isErrorPage=”true”%>

 Diretiva Include

Coloca o conteúdo de um arquivo em outro. Não há limites para inclusões,


podendo ter várias em uma mesma página. A diretiva se substitui pelo conteúdo
indicado.

<%@ include file=”URLdoArquivo” %> ou <jsp:directive.include file=”URLdo


Arquivo” />

 Diretiva Taglib

Se usada esta diretiva em uma página, um conjunto de tags personalizadas


estará a sua disposição.

<%@ taglib uri=”URLdaBibliotecadeTags” prefix=”PrefixodaTag” %>

Objetos Implícitos

 request: objeto que implementa a interface javax.servlet.http.ServletRequest,


assim possui todas as funcionalidades típicas, como: request.getAttribute(),
request.getParameter() e etc;

 response: similar ao objeto acima, porém implementa a interface


javax.servlet.http.ServletResponse;

 out: representa a instância da classe java.servlet.jsp.JspWriter e é usada para


imprimir caracteres na página html (equivalente ao PrintWriter dos Servlets);

 session: é a instância da classe javax.servlet.http.HttpSession, podendo


controlar a sessão do usuário;

 config: é a referência ao objeto da interface javax.servlet.ServletConfig, que


representa o objeto de configuração do Servlet JSP que foi ajustado no
deploymet descriptor (web.xml);

 application: é a referência a interface javax.servlet.ServletContext que


representa o contexto da aplicação;

 page: objeto que referencia a classe java.lang.Object, assim, este possui a


informação da página corrente;

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 19

 pageContext: é a referência ao objeto javax.servlet.jsp.PageContext,


proporcionando acesso a todos os escopos disponíveis no JSP e para vários
atributos de página úteis, como o pedido atual e resposta, o ServletContext,
HttpSession e ServletConfig;

 exception: é a instância do objeto java.lang.Throwable, representando uma


exceção e estará presente em páginas de erros na aplicação;

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


20 Parte 4

Practice

Atividade Trabalho em dupla

Prática com Cookies.

Implemente e teste o código anterior sobre cookies .

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 21

Performance

Atividade Todos juntos 4


Validação de login e senha de usuário utilizando o
objeto Session

A atividade será composta por páginas JSP e Servlets que se comunicam


mediante encaminhamentos e passagem de parâmetros e compartilham atributos.

Façamos uma análise gráfica de como será construída a aplicação:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


22 Parte 4
O fluxo acima demonstra o caminho percorrido pela Aplicação quando o
usuário acessa a página pela primeira vez, sendo direcionado pelo Container à página
index.jsp e, a partir desse ponto, encaminhado até o servlet Aplicação, quando clica
em logout e então o sistema invalida sua sessão, redirecionando-o à página inicial.

Utilizamos páginas JSP onde poderiam ter sido utilizados Servlets e vice-versa
de forma a mostrar ao aluno que as tecnologias são intercambiáveis tendo, cada qual,
sua especialidade e vantagens de atuação.

1. Vejamos agora, um a um, a estrutura e código dos nossos componentes,


mas antes, crie um projeto web dinâmico no Eclipse, de nome
GrandePorteJSP.

2. Crie uma página JSP com o nome de index.jsp e com o seguinte


conteúdo:

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Página de Login</title>
</head>
<body>
<% String msg = (String)request.getAttribute("msg"); %>
<form method="post" action="<% out.println(request.getContextPath() +
"/validaLogin.jsp"); %>" >
<table width="30%">
<%if (msg != null && !msg.equals("")){ %>
<tr><td colspan="2">
<%
out.println(msg);
out.println("</td></tr>");
}
%>
<tr>
<td>Usuário</td>
<td><input type="text" name="userName" size="10"></td>
</tr>
<tr>
<td>Senha</td>
<td><input type="password" name="password" size="10"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">Entrar</button></td>
</tr>
</table>
</form>
</body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 23

3. Crie uma segunda página, chamada validaLogin.jsp, com o seguinte


código:

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8" import="beans.Cliente"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

4
<title>Validação de Login</title>
</head>
<body>
<%
String usuario = request.getParameter("userName");
String senha = request.getParameter("password");
String msg = "";
String urlDestino = "/index.jsp";

if ((usuario == null) || (usuario.equals(""))){


msg = "Por favor, digite o usuário.";
} else if ((senha == null)||(senha.equals(""))){
msg = "Por favor, digite a senha.";
} else {
if (usuario.equals("gp") &&
senha.equals("javalevel2")){
Cliente cliente = new Cliente();
cliente.setUsuario(usuario);
cliente.setSenha(senha);
request.getSession().setAttribute("usuario",
cliente);
msg = "Usuário autenticado!";
urlDestino = "/aplicacao";
} else {
msg = "Usuário e senha inválidos!";
}

}
request.setAttribute("msg", msg);
RequestDispatcher dispatcher =
request.getRequestDispatcher(urlDestino);
dispatcher.forward(request, response);
%>

</body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


24 Parte 4
4. Criaremos agora a classe javabean que usaremos como modelo de dados
do usuário. Crie, primeiramente um pacote denominado beans. Dentro
desse pacote, crie a classe Cliente e com o seguinte código:

package beans;

public class Cliente {

private String usuario;


private String senha;

public String getUsuario() {


return usuario;
}
public void setUsuario(String usuario) {
this.usuario = usuario;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 25

5. Crie um servlet de nome Aplicacao e, durante a criação, modifique o url-


pattern desse servlet para "/aplicacao". Esse componente deverá ter o
seguinte código:

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;

4
import javax.servlet.http.HttpServletResponse;
import beans.Cliente;

public class Aplicacao extends HttpServlet {

protected void doGet(HttpServletRequest request,


HttpServletResponse response) throws ServletException,
IOException {
doPost(request, response);
}

protected void doPost(HttpServletRequest request,


HttpServletResponse response) throws ServletException,
IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
Cliente usuario =
(Cliente)request.getSession().getAttribute("usuario");
out.println("<html>");
out.println("<head><title>Bem Vindo ao Sistema!</title>");
out.println("<body>");
out.println("<h2>" + request.getAttribute("msg") +
"</h2><br />");
out.println("<h2>" + usuario.getUsuario());
out.println("Seja bem vindo à nossa loja online!");
out.println("</h2>");
out.println("<br /><br />");
out.println("<a href='logout'>Logout</a>");
out.println("</body>");
out.println("</html>");
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


26 Parte 4
6. O último componente a ser criado em nossa aplicação é o servlet Logout,
que será composto pelo seguinte código:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class Logout extends HttpServlet {


protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
doPost(request, response);
}

protected void doPost(HttpServletRequest request,


HttpServletResponse response) throws ServletException,
IOException {
HttpSession session = request.getSession(false);
if (session != null){
session.invalidate();
}
response.sendRedirect(request.getContextPath() +
"/index.jsp");
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 4 27

Por fim, mostra-se abaixo o código do Deployment Descriptor que, a essa


altura já é familiar ao aluno e não mais causa espanto:

<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

4
id="WebApp_ID" version="2.5">
<display-name>GrandePorteJSP</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description></description>
<display-name>Aplicacao</display-name>
<servlet-name>Aplicacao</servlet-name>
<servlet-class>Aplicacao</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Aplicacao</servlet-name>
<url-pattern>/aplicacao</url-pattern>
</servlet-mapping>
<servlet>
<description></description>
<display-name>Logout</display-name>
<servlet-name>Logout</servlet-name>
<servlet-class>Logout</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
</web-app>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


28 Parte 4

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte

JavaServer Faces (JSF) é um framework MVC


baseado em Java para a construção de interfaces de
usuário baseadas em componentes para aplicações
web. Possui um modelo de programação dirigido a
eventos, abstraindo os detalhes da manipulação dos
eventos e organização dos componentes, permitindo
que o programador se concentre na lógica da
aplicação.
Versão 2.1.1
Parte 5 3

Preparation

Trocando Ideias É agora que você fala !!

Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na


capa desta parte. Isso é importante para que seu instrutor e seus colegas
saibam como está seu conhecimento sobre o assunto e se você precisa ou
5
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe?


 O que você não sabe?
 Porque é importante conhecer estes tópicos?
 Quais são os seus temores?
 O que você considera difícil?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


4 Parte 5

Presentation

Teoria Java server faces

Estivemos desde o início do curso utilizando Servlets e JSP como tecnologia


única para a construção de aplicações web com Java, entretanto, existem diversos
web application frameworks disponíveis, grande parte deles gratuitos e open source.
Mas o que são web application frameworks?

Em uma definição mais genérica podemos conceituar framework como um


conjunto de teorias largamente aceitas de forma suficiente para servirem como
princípios dentro de uma determinada disciplina.

Trazendo o termo para o mundo do desenvolvimento de software,


especificamente na área de desenvolvimento web, um framework pode ser
conceituado como um conjunto reutilizável de classes e bibliotecas voltadas para a
criação de aplicações web, páginas web dinâmicas ou ainda web services em
determinada plataforma tecnológica, em nosso caso, a plataforma Java.

Dentre as dezenas de frameworks web para Java disponíveis no mercado hoje


em dia, JSF 2.1 é um dos que tem grande aceitação de mercado e grande variedade
de bibliotecas e componentes livres para uso.

Veja, além do JSF, alguns dos mais conhecidos frameworks web disponíveis
hoje no mundo Java:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 5

JSF e os padrões MVC e Front Controller

O framework JSF faz extenso uso dos padrões MVC e Front Controller em sua
arquitetura e por esse motivo vale a pena um olhar um pouco mais atento sobre esse
assunto de forma que o aluno entenda melhor como trabalhar com JSF 2.1.

MVC ou Model-View-Controller

Nesse padrão, largamente adotado hoje em dia por quase todos os frameworks
web, procura-se separar as três camadas que compõem qualquer aplicação, de forma
a obter-se algumas vantagens como:




Separação de responsabilidades;
Organização de código;
Baixo acoplamento, facilitando a extensão e alteração de componentes;
5
 Integração entre diferentes áreas de desenvolvimento, como designers e
desenvolvedores;
 Segurança;
 Facilidade de manutenção;
 Agilidade na customização, entre outros.

Basicamente, o padrão MVC prevê a arquitetura separada em três grandes


camadas, denominadas de Model (Modelo), View (Apresentação ou Visão) e
Controller (Controlador):

 Modelo: encapsula os dados e as funcionalidades da aplicação. Pode ser


desde um simples atributo de instância, até um conjunto de classes ou até
mesmo um outro MVC. Geralmente conterá os componentes utilizados com
exclusividade para a cesso a dados, que pode ser desde um arquivo
serializado até Sistemas Gerenciadores de Banco de Dados em geral;

 Apresentação: é responsável pela exibição de informações, pelas telas,


interfaces gráficas com o usuário. Prevê a implementação da lógica de telas e
atualização das informações exibidas, cujos dados são obtidos do modelo.

 Controlador: recebe as requisições do usuário quando este interage com os


componentes visuais, coordena a comunicação entre as camadas e gerencia o
escopo em que é aplicado.

Nesse padrão, a comunicação entre camadas somente ocorre via Controlador,


ou seja, a camada Modelo somente se comunica com a camada Controlador e o
mesmo se aplica à Apresentação, sendo fechada a possibilidade de comunicação
direta entre Apresentação e Modelo.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


6 Parte 5

Front Controller

O padrão Front-Controller, apesar de possuir diversas decorrências que


merecem um maior aprofundamento e por ser necessário conhecermos basicamente
seu conceito, deixaremos maior detalhes do assunto para o aluno interessado,
indicando como fonte de referência o livro:

Patterns of Enterprise Application Architecture


Martin Fowler
Editora Addison-Wesley

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 7

Assim como o MVC, esse padrão é bastante relacionado a aplicações web e


pode ser encontrado em diversas implementações de frameworks, como o próprio
Spring MVC e JSF. Outras plataformas também o usam, como o Zend Framework e
CodeIgniter do PHP e o ASP.NET MVC Framework da Microsoft na plataforma .NET.

Basicamente, a ideia do Front Controller é prover uma interface centralizada


para todas as requisições dos usuários.

Na plataforma Java, já aprendemos que os componentes responsáveis por


lidar com as requisições em um Container Web são os Servlets (englobando nesse
conceito as JSPs que tornam-se Servlets posteriormente no fluxo de execução do
Container) e no JSF 2.1 teremos exatamente esse padrão: um único Servlet que

5
controlará todas as requisições chegadas do usuário que atenderem ao padrão
necessário para a chamada da aplicação.

Uma Primeira Aplicação com JSF

Construiremos agora uma aplicação inicial com JSF, de forma a demonstrar o


ambiente de configuração e em seguida analisaremos alguns componentes envolvidos.

1. Inicialmente, crie um projeto Java web no Eclipse de nome


"GrandePorteJSF".

Um projeto web JSF nada mais é do que um projeto Java web, que se utiliza de
Servlets, dos recursos Java EE e dos padrões de arquitetura acima descritos,
principalmente. Respeita a API de Servlets e qualquer outro componente já visto
durante a fase do curso relativa à Servlets, também se aplica da mesma forma em
projetos JSF.

2. Após criado o projeto, temos algumas tarefas de configuração a cumprir,


descritas abaixo:

 Ao criar o projeto, marcar a caixa de seleção para gerar o Deployment


Descriptor web.xml. Precisaremos dele para customizar a configuração do JSF.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


8 Parte 5
O Deployment Descriptor deverá ficar com o seguinte código de declaração do
Servlet que será o Front Controller do Framework:

<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID"
version="3.0">
<display-name>GrandePorteJSF</display-name>
<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>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

</web-app>

 Importação da biblioteca (arquivo jar) que representa a implementação


escolhida de JSF 2.1. para o nosso projeto. Em nosso curso, utilizaremos a
implementação Mojarra 2.1.9., que é a distribuída pela Oracle e presente no
servidor Glassfish, porém é possível utilizar-se de outras, como MyFaces Core
2.1. Project da Apache. As implementações descritas podem ser obtidas em:

o Mojarra: http://javaserverfaces.java.net/download.html

o Apache MyFaces Core: http://myfaces.apache.org/core21/index.html

o Para tanto, faça download da última versão estável (à época em que


esse conteúdo estava sendo escrito a versão mais recente era a 2.1.9)
e cole o arquivo baixado (javax.faces-2.1.9.jar) na pasta WEB-INF/lib de
seu projeto.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 9

 Criação do arquivo faces-config.xml dentro da pasta WEB-INF (no mesmo local


onde fica o arquivo web.xml), com o seguinte conteúdo inicial:

<?xml version="1.0" encoding="UTF-8"?>


<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
</faces-config>

5
Repare que esse último arquivo está somente com a tag inicial <faces-config>.
Esse arquivo poderá ser palco de muitas configurações dentro de nossa aplicação. Na
verdade ele será o "Painel de Controle" da aplicação JSF.

3. Como próximo passo, criaremos nosso "Managed Bean" ou Bean


Gerenciado, que conterá o modelo de nossa aplicação. Não se preocupe com as
definições por enquanto, elas serão bem melhor explicadas em breve. Crie uma nova
classe Java em um pacote denominado beans de nome "Usuario". Nosso Managed
Bean terá o seguinte código:

package beans;
import java.util.Random;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Usuario {

private String nome;

public String getNome() {


String [] nomes = {"Bruce Springsteen", "Ozzy Osbourne",
"David Coverdale", "Neil Young", "Jimmy Hendrix"};
Random gerador = new Random();
int i = gerador.nextInt(5);
this.nome = nomes[i];
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


10 Parte 5
4. Criaremos, finalmente, nossa página index.xhtml, que será a página inicial
exibida e que se comunica diretamente com o Managed Bean Usuario que criamos no
passo anterior. Para tanto, crie uma nova página XHTML no Eclipse e entre com o
seguinte código:

<?xml version="1.0" encoding="UTF-8" ?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-
8"/>
<title>Primeira página JSF!</title>
</h:head>
<h:body>
<h1>Bem vindo à sua primeira aplicação JSF!</h1>
<h3>Exemplo de Formulário feito com tags JSF:</h3>
<h:form>
<h:outputText value="Nome Gerado: "/>
<!-- Isso é Expression Language! -->
<h:outputText value="#{usuario.nome}"/>
<br />
<h:commandButton value="Enviar" />
</h:form>
</h:body>
</html>

5. Lembre-se de que estamos rodando uma aplicação web e, para tanto, você já deve
estar com seu Container Web (estamos usando o Apache Tomcat) funcional. Após
toda a configuração e códigos prontos, devermos ter a seguinte estrutura de arquivos:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 11

6. Rodando a aplicação com sucesso, obtemos a saída no browser:

Clicando no botão, o formulário envia um novo Request ao servidor e a página


retorna com uma nova montagem, chamando o método getNome() do nosso Managed
Bean a cada Request.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


12 Parte 5
Entendendo a Aplicação Criada

Configuração:

A aplicação é criada e configurada no eclipse como qualquer outro projeto web


Java, recebendo a mais uma biblioteca que contém as classes do framework, um nó
de configuração do Servlet central do framework (que representa o Front Controller) no
arquivo web.xml e um arquivo chamado “faces-config.xml”, específico à configuração
do JSF, que fica localizado no diretório WEB-INF, mesmo local do Deployment
Descriptor.

Esse último arquivo inicia vazio, ou seja, somente com o nó principal da


aplicação. Posteriormente será editado e terá seu conteúdo incrementado. NÃO SE
PREOCUPE EM DECORAR O CABEÇALHO DOS ARQUIVOS DE CONFIGURAÇÃO!
Apenas copie se for necessário. Na grande parte das vezes, seu IDE fará isso para
você.

Note que a implementação Mojarra do JSF 2.1. utiliza o servlet


javax.faces.webapp.FacesServlet como Front Controller, que é definido e mapeado
no web.xml. A esse respeito é importante chamar a atenção do aluno para o
mapeamento realizado no nó <url-pattern> que será definitivo para a criação de
páginas e links na aplicação. Somente serão direcionadas para o framework JSF as
requisições que obedecerem ao padrão dessa tag e, por conseguinte, forem entregues
para o FacesServlet. Os padrões mais usados são:

 /faces/*
 *.jsf
 *.xhtml

É claro que infinitas combinações de padrão de URL podem ser feitas, portanto
atente para esse item!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 13

Managed Beans:

Em nossa aplicação, criamos apenas um Managed Bean, que atende aos


nossos propósitos introdutórios para uma primeira experiência.

Managed Beans são classes Java anotadas (ou declaradas no arquivo de


configuração faces-config.xml) que representam, conjuntamente, o modelo ou parte da
estrutura que irá compor o modelo (Camada Model) de nossa aplicação.

Nos Managed Beans é que colocaremos a lógica e o acesso a dados que


nossa aplicação precisará. Esses componentes serão acessados de dentro de nossas
páginas, por meio de atributos e métodos definidos. Utilizaremos a Expression

5
Language para acessar os Beans.

No caso específico do nosso primeiro exemplo, note que temos apenas um


atributo chamado nome, do tipo String e seus respectivos métodos Getters e Setters.
Toda a lógica de nosso código reside no método getNome(), que escolhe
aleatoriamente um dos nomes existentes no array nomes[ ] e o atribui ao nosso campo
respectivo:

String [] nomes = {"Bruce Springsteen", "Ozzy Osbourne", "David


Coverdale", "Neil Young", "Jimmy Hendrix"};
Random gerador = new Random();
int i = gerador.nextInt(5);
this.nome = nomes[i];
return nome;

A cada requisição, esse método é chamado indiretamente pela página


index.xhtml por meio da tag:

<h:outputText value="#{usuario.nome}"/>

Eis aí o primeiro trecho de Expression Language que vemos no curso. Essa


chamada ao Managed Bean é feita de uma forma diferente daquela ao qual estamos
acostumados:

#{nomeDoBean.nomeDoAtributoOuMétodo}

O nome do bean será por default o nome da classe começando com letra
minúscula. O nome do atributo ou método será sempre o nome do método getter ou
setter, sem os prefixos get ou set.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


14 Parte 5
Facelets:

Facelets são páginas XHTML que carregam tags JSF, mas também tags
XHTML padrão, sendo agora preferidas como forma de apresentação às anteriores
JSPs. Uma página Facelet tem tipicamente as tags HTML padrão substituídas por
aquelas específicas da JSF, contidas em seus namespaces padrão e até outras,
contidas em namespaces customizados.

Observe as tags abaixo:

<h:head>
<!-- … Código … -->
</h:head>
<h:body>
<h:form>
<h:outputText value="Nome Gerado: "/>
<!-- Isso é Expression Language! -->
<h:outputText value="#{usuario.nome}"/>
<br />
<h:commandButton value="Enviar" />
</h:form>
</h:body>

Note a existência de prefixos, como “ h: ”. Esses prefixos indicam a qual


namespace a tag pertence. Existem outros diversos como “ f: ”, “ ui: ”, entre outros.
Esses namespaces devem ser declarados no cabeçalho da página de forma a permitir
seu uso. Perceba a declaração no cabeçalho:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">

Cada um dos namespaces é declarado com um prefixo diferente de forma que


o Java identifique o local e o framework ao qual pertence cada tag.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 15

O Ciclo de Vida de uma requisição com Java Server Faces


A especificação JSF define seis fases bem distintas durante o ciclo de vida de
uma aplicação ao atender uma requisição:

1. Restore View
2. Apply Request Values
3. Process Validations
4. Update Model Values
5. Invoke Application
6. Render Response

Vejamos esse ciclo representado em um diagrama para melhor compreendê-lo


e, em seguida analisar cada uma das fases:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


16 Parte 5
1. Restore View: essa fase recupera a árvore de componentes para a página
requisitada ou constrói uma nova árvore caso a página esteja sendo solicitada pela
primeira vez por esse usuário. Em seguida, passa para a fase Apply Request Values,
mas verifica antes se existem dados sendo passados na requisição. Caso não haja
nenhum dado nessa requisição, passa direto à fase final, Render Response,
retornando imediatamente ao usuário. Isso acontece quando a página está sendo
exibida pela primeira vez;

2. Apply Request Values: Nessa fase, a implementação JSF itera sobre todos
os componentes inseridos na árvore montada anteriormente. Cada componente
verifica quais dos valores vindos na requisição lhes pertencem e os armazenam,
atualizam-se com as informações recebidas. Esses valores são chamados de valores
locais. Os eventos recebidos também são identificados nessa fase, porém somente
serão tratados em fase posterior;

3. Process Validations: Aqui, todos os validadores e conversores anexados


aos componentes são executados e, caso os valores locais, lidos na fase anterior,
estejam sem quaisquer erros de validação, o ciclo prossegue normalmente para a fase
seguinte. Caso exista algum erro de validação ou conversão, a implementação JSF
desloca-se para a fase Render Response diretamente, reexibindo a mesma página ao
usuário, de modo que ele tenha a chance de corrigi-la. Esse aspecto da especificação
JSF é bem curioso, em comparação com outros mecanismos de validação existentes
no mercado. O desenvolvedor deve acrescentar tags de exibição de mensagens para
capturar as mensagens de erro e exibir ao usuário quando as páginas são reexibidas.

4. Update Model Values: Assim que o ciclo sai da fase anterior, entende-se
que é seguro atualizar o modelo de dados. Nessa fase, os valores locais são utilizados
para atualizar os beans (propriedades) que estão conectados aos respectivos
componentes.

5. Invoke Application: Nessa fase é executado o método de ação, descrito no


atributo "action" do componente que gerou o evento resultante na presente requisição
(normalmente um botão ou um link). É comum que o método chamado retorne uma
String como retorno de navegação, levando o usuário a outras páginas, conforme as
regras de negócio e o mecanismo de navegação do JSF.

6. Render Response: Por fim, essa fase codifica a resposta e a encaminha ao


navegador do usuário. Quando o usuário clicar novamente em um link ou botão, o
ciclo reinicia desde a fase 1.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 17

Managed Beans
De acordo com a definição presente na especificação Javabeans, um Java
bean é um componente de software reutilizável que pode ser manipulado em uma
ferramenta de construção (build). Temos que admitir que essa definição é bem vaga,
mas em geral, é essa natureza que define um bean: sua vasta gama de aplicações.
Veremos que, em nosso caso, um Managed Bean tem propósitos bem definidos.

Nas aplicações JSF, beans armazenam o estado das páginas web. A


manipulação e controle dos beans reside sob controle da implementação JSF que
utilizamos. Essa implementação é responsável pelas seguintes ações:

 Cria e descarta beans conforme necessário (daí o termo “Managed Beans” ou


Beans Gerenciados);

5
 Lê propriedades dos beans quando exibindo em uma página;
 Atualiza propriedades dos beans quando um formulário é postado.

Considere nosso exemplo feito em aula anterior, em que a seguinte linha é


destacada na página inicial da aplicação, "index.xhtml":

<h:outputText value="#{usuario.nome}"/>

Nessa linha, a implementação JSF precisa localizar a classe adequada para o


bean de nome usuario. Em nosso exemplo, uma classe de nome Usuario foi declarada
da seguinte forma:

@ManagedBean(name="usuario")
@RequestScoped
public class Usuario {
… // Definição da classe
}

Um Managed Bean nada mais é do que uma classe Java com a anotação
@ManagedBean, que rotula nossa classe como um bean que deverá ser gerenciado
pela implementação JSF e pela anotação @RequestScoped, que delimita o escopo de
existência da classe, nesse caso específico, escopo de Requisição.

Perceba que o nome passado como atributo para a anotação @ManagedBean


corresponde ao nome utilizado para acessar o bean de dentro da página web. Esse
nome poderia ter sido omitido no exemplo e de fato foi. Nesse caso, o nome padrão a
ser utilizado pela implementação JSF é o nome da classe com a primeira letra
minúscula, seguindo o padrão "camelCase de iniciais minúsculas" para identificadores
Java, como já é usual.

Quando uma expressão como a descrita acima é encontrada, o JSF criará um


objeto da classe Usuario, que perdurará pelo tempo que durar a requisição (veja que o
escopo do bean é configurado para requisição). Dessa forma, vejamos quais são os
escopos existentes para a declaração de um Managed Bean.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


18 Parte 5
Criando Managed Beans com XML
Conforme visto acima, para se criar um Managed Bean, basta que
acrescentemos as anotações devidas a uma classe Java e a implementação JSF
cuida de gerenciá-lo adequadamente.

Ocorre que também podemos configurar nossos beans por meio de


declarações XML em um arquivo de configurações. Essa era a única maneira possível
antes da versão JSF 2.0. O local padrão para declarações e configurações no
framework JSF é o arquivo faces-config.xml, mas não é o único local permitido.
Utilizaremos esse arquivo como padrão e, caso o aluno deseje maiores informações,
sugerimos consultar a documentação do JSF no seguinte endereço:

http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html

Definir beans no arquivo faces-config.xml é trivial e, para tanto, fazemos uso da


tag <managed-bean> conforme exemplo abaixo:

<faces-config>
<managed-bean>
<managed-bean-name>usuario</managed-bean-name>
<managed-bean-class>beans.Usuario</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 19

Os Escopos de um Managed Bean

Escopo de Requisição (@RequestScoped)


O escopo de requisição é o que possui o menor tempo de vida útil. Inicia-se
quando o cliente submete uma requisição HTTP e termina quando a resposta é
enviada ao cliente. Um Managed Bean criado sob o escopo de Requisição (Request)
terá uma nova instância criada a cada requisição.
Este é o único escopo em que os beans são todos "Thread Safe", o que
significa que o container criará uma nova instância para cada requisição. Portanto é
seguro que você aloque dados em campos de MBs de Requisição sem preocupar-se
com acessos concorrentes ou sincronização desses dados.

Escopo de Sessão (@SessionScoped)


Relembre-se sobre quando falamos da natureza "Stateless" das aplicações
web. As sessões entram nesse assunto como uma solução para a persistência de
5
dados e informações do usuário no servidor. Como a cada requisição feita, nenhum
dado persiste, utilizamos sessões para guardar informações entre requisições do
mesmo usuário. Para a identificação e recuperação de sessões do usuário, a
implementação do JSF utiliza-se do mecanismo de Cookies, já estudado em aula
anterior. Caso o mecanismo de Cookies esteja desativado no navegador do usuário, o
JSF automaticamente faz as reescritas de URL, tornando esse mecanismo
completamente transparente para o desenvolvedor.
Um Managed Bean de sessão persiste durante o tempo de vida de uma sessão
e só é descartado quando o método invalidate() no objeto HttpSession é chamado ou
quando o tempo de vida da sessão expira (timeout).

Escopo de Aplicação (@ApplicationScoped)


O escopo de aplicação persiste por toda a duração da aplicação. Esse escopo
é compartilhado por todas as requisições e sessões. Managed Beans criados nesse
escopo serão acessíveis por todas as instâncias de uma aplicação web.
Beans criados no escopo de aplicação são instanciados pela primeira vez
quando recebem a primeira solicitação por algum componente da aplicação e são
descartados quando a aplicação é retirada do Container. O comportamento de
inicialização desse bean pode ser modificado utilizando-se a anotação eager quando
na declaração do escopo do Managed Bean, conforme exemplo abaixo:

@ManagedBean(eager=true)

Essa anotação demanda a criação do Managed Bean antes da primeira


requisição.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


20 Parte 5
Escopo de Visualização (@ViewScope)
Esse escopo foge às regras tradicionais de persistência vistos anteriormente e
relaciona-se à página sendo exibida. Um bean criado nesse escopo persiste enquanto
a mesma página JSF é reexibida. O termo view utilizado pela implementação JSF
refere-se à página (esse termo é usado por toda a documentação do framework).
Assim que usuário navega para outra página, o(s) bean(s) saem do escopo e são
descartados.
Esse escopo é particularmente útil para utilização em aplicações Ajax.

Escopo Customizado (@CustomScoped("#{expr}"))


Um escopo nada mais é do que um mapa que relaciona nomes a objetos. A
funcionalidade que realmente define um escopo é o seu tempo de vida útil, que recai
para todos os objetos existentes nos mapas. A implementação JSF toma conta dos
ciclos de vida dos quatro escopos padrão (requisição, sessão, aplicação e view).
Nesse caso, o desenvolvedor pode criar seu próprio escopo, porém também
deve responsabilizar-se por remover os objetos do escopo. Não entraremos em
detalhes nesse caso pois esse escopo é pouco utilizado e pode ser fonte de diversos
problemas.

Propriedades de um Managed Bean

Um bean, para ser assim considerado, segue uma série de padrões específicos
de programação para expor as propriedades e ações que oferecem. As propriedades
de um bean compõem o mais importante conjunto de funcionalidades disponíveis em
um componente desse tipo e podem ser definidas por meio da implementação dos três
itens abaixo listados:

 Um nome;
 Um tipo;
 Métodos de acesso e modificação (getters e setters).

Um bean DEVE expor um construtor sem argumentos - essa é talvez a única


demanda obrigatória da especificação acerca de uma classe bean.

Propriedades são simplesmente variáveis de instância ou atributos com seus


métodos getters e setters respectivos. É por meio desses métodos que a
implementação JSF acessará os dados de um Managed Bean.

A estrutura típica de um Managed Bean, já vista em exercícios anteriores, é a


seguinte:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 21

package beans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name="usuario")
@RequestScoped
public class Usuario {

private String nome;

5
public String getNome() {
return this.nome;
}

public void setNome(String nome) {


this.nome = nome;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


22 Parte 5
Anotações do ciclo de vida de um Managed Bean
No ciclo de vida de um Managed Bean, podemos usar as anotações
@PostConstruct e @PreDestroy para especificar métodos que são automaticamente
invocados pela implementação JSF respectivamente, logo após a criação do
componente e justamente antes do bean sair de escopo:

package beans;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class MeuBean {

@PostConstruct
public void inicializar(){
//Código a ser excutado na inicialização do bean
}

@PreDestroy
public void destruir(){
//Código a ser executado na destruição do bean
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 23

Injetando Managed Beans Como Propriedades


Beans JSF possuem um mecanismo básico de injeção de dependências: a
anotação @ManagedProperty.

Injeção de dependências refere-se a um termo (CDI) da especificação Java EE


6 que provê mecanismos de injeção de contextos e dependências de forma a prover
infra-estrutura e mecanismo adequado à construção de aplicações multicamadas com
baixo acoplamento e fácil manutenção. Basicamente, a anotação injeta uma instância
do referido bean na propriedade anotada do outro Bean.

Vejamos um exemplo, supondo a existência de um outro Managed Bean


chamado Usuario que possivelmente armazena os dados de login de um usuário do
sistema:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
5
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class MeuBean implements Serializable{

@ManagedProperty(value="#{user}")
private Usuario user;

public void setUser(Usuario user) {


this.user = user;
}
}

Neste exemplo, perceba a anotação @ManagedProperty sobre o campo user,


que é do tipo Usuario. Mesmo anotando o campo, é necessário prover um método
setter, nesse caso, setUser(Usuario user). Quando uma instância de MeuBean for
criada, a expressão #{user} é avaliada e o resultado é passado ao método setter.

Quando injetamos um Managed Bean dentro de outro, devemos nos certificar


de que seus escopos são compatíveis. O escopo do bean injetado NÃO PODERÁ
SER MENOR DO QUE O DO BEAN QUE O CONTÉM. Vejamos uma tabela que
representa esse relacionamento:

Ao definir um bean com esse Você poderá injetar como propriedades, beans
escopo...: deste escopo...:
nenhum nenhum
application nenhum, application
session nenhum, application, session
view nenhum, application, session, view
request nenhum, application, session, view, request

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


24 Parte 5

Internacionalização com Message Bundles


Na construção de aplicações web é essencial que o desenvolvedor preocupe-
se com a internacionalização de suas páginas, tendo em vista a integração mundial
dos negócios e a característica global da Internet. Nesse aspecto, a especificação JSF
provê a possibilidade da utilização de um repositório central para todas as Strings da
aplicação. Esse repositório nada mais é do que um arquivo texto criado com a já
reconhecida e utilizada extensão .properties.

Esse arquivo deverá ser composto unicamente por pares de chave=valor, que
serão referenciados no contexto de todas as páginas da aplicação. Deverá ser criado
no mesmo diretório onde são criadas as classes da aplicação, não importando em qual
subdiretório ou pacote, contanto que tenha a extensão .properties.

Um exemplo do conteúdo desse arquivo:

mensagem=Bem Vindo à aplicação Java


tipo=Escola de Informatica
curso=Java Level 2

Se quiser se aprofundar mais na classe Properties do Java, leia a


documentação da API dessa classe. Seu nome completamente qualificado é o
java.util.Properties.

Antes de ser utilizado em suas páginas é preciso declarar o Message Bundle e


isso pode ser feito de duas formas:

 via faces-config.xml (a configuração nesse caso é global e esse recurso fica


disponível a todas as suas páginas):

<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<resource-bundle>
<base-name>br.com.grandeporte.messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
</faces-config>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 25

 ao invés de usar uma declaração global, é possível adicionar a tag f:load-


bundle a cada página JSF que precisará acessar o bundle, dessa forma (essa
forma é menos eficiente que a anterior):

<f:loadBundle basename="com.corejsf.messages" var="msgs">

Em qualquer uma das formas, as mensagens ou atributos no arquivo properties


estão disponíveis por meio da variável do tipo mapa, chamada "msgs" e, a partir deste
ponto, para recuperar uma String desse arquivo basta usar uma expressão de valor
(EL será vista mais adiante): "#{msgs.tipo}". O retorno, nesse caso, será "Escola de
Informatica".

A internacionalização da sua aplicação será atingida pela criação de outros


arquivos properties que definem valores diferentes para as mesmas chaves, devendo

5
apenas observar o padrão utilizado para que a implementação JSF saiba qual arquivo
aplicar, dada a localidade em que está.

Por exemplo, para suportar o idioma inglês, dado que o arquivo de


propriedades esteja definido com o nome messages.properties, usaríamos outro
arquivo nomeado messages_en.properties, sendo o sufixo en característico do
idioma suportado. É possível ainda, além do idioma, especificar a localidade do
idioma, o que é bastante comum com o Brasil, cujo idioma diferencia-se bastante do
português nativo de Portugal. Como esse caso também é fato para o inglês norte-
americano, nosso arquivo poderia se chamar messages_en_US.properties,
referindo-se especificamente ao inglês norte americano.

Para conhecer a lista de códigos de duas ou três letras suportadas


internacionalmente, visite http://www.loc.gov/standards/iso639-2/.

Para que a implementação JSF saiba da existência do suporte a localidades, é


preciso definir a localização padrão da aplicação e declarar quais idiomas serão
suportados e isso pode ser feito de algumas formas diferentes:

 via arquivo faces-config.xml:

<faces-config>
<application>
<locale-config>
<default-locale>pt_BR</default-locale>
<supported-locale>en_US</supported-locale>
</locale-config>
</application>
</faces-config>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


26 Parte 5
 programaticamente, chamando o método setLocale do objeto UIViewRoot:

UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();


viewRoot.setLocale(new Locale("en"));

 configurando a localização individualmente, por página, utilizando a tag <f:view


.../>
o estaticamente: <f:view locale="en" />
o dinamicamente: <f:view locale="#{user.locale}" />
o Em ambos os casos acima, toda a página, incluindo os blocos <h:head> e
<h:body> devem ser postos dentro do bloco definido pela tag <f:view
...>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 27

Bibliotecas de Componentes / Tags do JSF 2


O desenvolvimento de aplicações web de sucesso, sem dúvida, passa pela criação de
componentes visuais e desenho da interação com o usuário de uma forma fácil, agradável e
intuitiva. Para tanto, o conhecimento de como usar e aplicar os componentes e tags do JSF é
essencial.

Desde a versão 1.2., o número de componentes do JSF aumentou de algumas dezenas


para o que hoje já se somam centenas. O que antes eram apenas duas bibliotecas de tags (na
versão 1.2. só existiam as bibliotecas core e HTML), hoje são seis com mais de 100 tags e com
promessa de crescimento.

Veremos grande parte dessas tags/bibliotecas e como podemos usá-las para a


construção de aplicações, mas não podemos deixar de citar a grande variedade de bibliotecas de
componentes terceirizadas, algumas proprietárias e comerciais, outras gratuitas e open source.
5
É impensável nos dias de hoje, construir uma aplicação sem qualquer apelo visual ou
um mínimo de recursos interativos que tornem a navegação mais agradável. Vivemos uma
época em que uso de AJAX e bibliotecas Javascript é quase que obrigatório. Nesse contexto,
diversas são as possíveis soluções para o desenvolvedor Java EE utilizando JSF 2:

Neste curso, analisaremos as tags nativas da implementação JSF 2 e o aluno é


encorajado a utilizar a biblioteca Primefaces para a construção de seu projeto final.
Caso o aluno deseje utilizar qualquer outra biblioteca é livre para tanto.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


28 Parte 5
Bibliotecas de Tags JSF
Vejamos abaixo, de forma analítica, quais são as bibliotecas de tags utilizadas
no JSF 2, denotando que as tags relativas a JSTL serão pouco utilizadas em nosso
curso, dado que utilizaremos os Facelets como idioma preferido de comunicação e
criação de páginas web.

Biblioteca Namespace Prefixo Número de


comumente tags
usado
Core http://java.sun.com/jsf/core f: 27
HTML http://java.sun.com/jsf/html h: 31
Facelets http://java.sun.com/jsf/facelets ui: 11
(JSF 2.0)
Composite http://java.sun.com/jsf/composite composite: 12
Components
(JSF 2.0)
JSTL Core http://java.sun.com/jsp/jstl/core c: 7
JSTL http://java.sun.com/jsp/jstl/functions fn: 16
Functions

Dentre as bibliotecas citadas acima, HTML será a mais usada em todas as


instâncias. Veremos abaixo, uma a uma de suas principais tags e em seguida
aplicaremos cada uma delas em uma situação real.

Biblioteca JSF HTML

Tag Descrição
head Renderiza o bloco <head> da página
body Renderiza o bloco <body> da página
form Renderiza um <form> HTML
outputStyleSheet Adiciona uma Folha de Estilos à página (Ex: CSS)
outputScript Adiciona um script à página (Ex: Javascript)
inputText Controle de entrada de texto em uma linha simples
inputTextArea Controle de entrada de texto em múltiplas linhas
inputSecret Controle de entrada de senhas / passwords
inputHidden Campo oculto, geralmente em formulários
outputLabel Controle de label para outro componente na página
(Acessibilidade)
outputLink Link para outra localidade na web
outputFormat Como outputText, mas formata as mensagens compostas
outputText Saída de texto em linha simples

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 29

commandButton Botão dos tipos submit, reset ou pushbutton


commandLink Link que age como um pushbutton
button Botão para encaminhar requisições GET
link Link para encaminhar requisições GET
message Exibe a mensagem mais recente para um componente
messages Exibe todas as mensagens
graphicImage Exibe uma imagem
selectOneListbox Caixa de seleção simples
selectOneMenu Menu de seleção simples
selectOneRadio
selectBooleanCheckbox
Conjunto de botões radio (Seleção simples)
Checkbox simples 5
selectManyCheckbox Conjunto de checkboxes
selectManyListbox Caixa de seleção múltipla
selectManyMenu Menu de seleção múltipla
panelGrid Layout tabular (Renderiza uma tabela simples)
panelGroup Dois ou mais componentes que são alocados como um
dataTable Controle de tabela com muitas funcionalidades
column Coluna em uma dataTable

Para cada componente exibido abaixo, será mostrado o código na


página .xhtml, o código correspondente no Managed Bean e o resultado no browser.
Todos os exemplos mostrados a seguir deverão ser implementados pelos alunos por
meio de uma aplicação de teste a ser explicada e direcionada pelo professor, que
implementa todas as funcionalidades mostradas abaixo.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


30 Parte 5
Rótulos e caixas de entrada de texto:
Os rótulos e caixas de entrada de texto (conhecidos como labels e textfields ou
mesmo textinputs) são os componentes de formulário mais comuns de se ver em uma
página na internet. Representam o meio mais usado de receber texto como entrada do
usuário e podem destinar-se a uma infinidade de tipos de dados, desde um nome ou
idade, por exemplo, até uma data mais complexa ou uma resposta que demande
milhares de caracteres.

 <h:inputText> e <h:outputLabel>

o index.xhtml:

<h:outputLabel value="Nome: " for="alunoNome" />


<h:inputText id="alunoNome" value="#{aluno.nome}"/>

o Managed bean "Aluno":

private String nome;


public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}

o Navegador:

 <h:inputTextarea>

o index.xhtml:

<h:outputLabel value="Endereço: " for="endAluno" />


<h:inputTextarea id="endAluno" value="#{aluno.endereco}" rows="5" />

o Managed Bean "Aluno":

private String endereco;


public String getEndereco() {
return endereco;
}
public void setEndereco(String endereco) {
this.endereco = endereco;
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 31

o Navegador:

 <h:inputSecret>

o index.xhtml:

<h:outputLabel value="Senha: " for="alunoSenha" />


<h:inputSecret id="alunoSenha" value="#{aluno.senha}"/> 5
o Managed Bean "Aluno":

private String senha;


public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}

o Navegador:

 <h:inputHidden>

o index.xhtml:

<h:inputHidden id="alunoOculto" value="#{aluno.oculto}"/>

o Managed Bean "Aluno":

private String oculto;


public String getOculto() {
return oculto;
}
public void setOculto(String oculto) {
this.oculto = oculto;
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


32 Parte 5
Controles de Seleção Simples

Esses controles são responsáveis por captar a interação do usuário para uma
dentre diversas escolhas, com exceção do Checkbox booleano. Para a exibição de
múltiplos itens disponíveis para escolha, esses componentes fazem uso de listas ou
coleções em geral, que devem ser criadas e controladas nas propriedades
responsáveis nos Managed Beans.

Começaremos com a exceção, o Checkbox booleano.

 <h:selectBooleanCheckbox>

o index.xhtml:

<h:outputLabel value="Aprovado: " for="alunoAprovado" />


<h:selectBooleanCheckbox id="alunoAprovado" value="#{aluno.aprovado}" />

o Managed Bean "Aluno":

private boolean aprovado;


public boolean isAprovado() {
return aprovado;
}
public void setAprovado(boolean aprovado) {
this.aprovado = aprovado;
}

o Navegador:

 <h:selectOneRadio> - Nesse caso estamos populando o componente de forma estática,


diretamente no componente através das tags <f:selectItem>

o index.xhtml:

<h:outputLabel value="Matérias (Usando selectOneRadio):" /> <br/>


<h:selectOneRadio value="#{aluno.materiaEscolhidaRadio}">
<f:selectItem itemLabel="Matemática" itemValue="Matemática"/>
<f:selectItem itemLabel="Português" itemValue="Português"/>
<f:selectItem itemLabel="Biologia" itemValue="Biologia"/>
<f:selectItem itemLabel="Física" itemValue="Física"/>
<f:selectItem itemLabel="Química" itemValue="Química"/>
</h:selectOneRadio>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 33

o Managed Bean "Aluno":

private String materiaEscolhidaRadio;


public String getMateriaEscolhidaRadio() {
return materiaEscolhidaRadio;
}
public void setMateriaEscolhidaRadio(String materiaEscolhidaRadio) {
this.materiaEscolhidaRadio = materiaEscolhidaRadio;
}

o Navegador:

5
 <h:selectOneMenu> - Nesse componente estaremos usando uma forma mista de
populá-lo: um item estaticamente, que corresponde ao valor da String "nenhum" e um
componente que referencia uma coleção controlada pelo Managed Bean

o index.xhtml:

<h:outputLabel value="Matérias (Usando selectOneMenu):" /> <br />


<h:selectOneMenu value="#{aluno.materiaEscolhidaMenu}">
<f:selectItem itemLabel="Nenhum" noSelectionOption="true"/>
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectOneMenu>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


34 Parte 5
o Managed Bean "Aluno":

private String materiaEscolhidaMenu;


private List<String> materiasEscolhidas;

public String getMateriaEscolhidaMenu() {


return materiaEscolhidaMenu;
}
public void setMateriaEscolhidaMenu(String materiaEscolhidaMenu) {
this.materiaEscolhidaMenu = materiaEscolhidaMenu;
}
public List<String> getMateriasEscolhidas() {
if (this.materiasEscolhidas == null){
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}

o Navegador

 <h:selectOneListBox> - Neste componente estamos usando somente a forma dinâmica


de capturar os dados para popular seus itens. Note que existe somente uma tag chamada
<f:selectItems> que conecta-se ao Managed bean para obter sua coleção de dados.

o index.xhtml:

<h:outputLabel value="Matérias (Usando selectOneListbox):" /> <br />


<h:selectOneListbox value="#{aluno.materiaEscolhidaListbox}">
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectOneListbox>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 35

o Managed Bean "Aluno"

private String materiaEscolhidaListbox;


private List<String> materiasEscolhidas;

public List<String> getMateriasListbox() {


return materiasListbox;
}
public void setMateriasListbox(List<String> materiasListbox) {
this.materiasListbox = materiasListbox;
}
public List<String> getMateriasEscolhidas() {
if (this.materiasEscolhidas == null){

5
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}

o Navegador:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


36 Parte 5
Controles de Seleção Múltipla

Esses controles, assim como os anteriores são responsáveis por captar a


interação do usuário dentre diversas escolhas, porém nessa categoria o usuário
poderá escolher mais de uma opção dentre as disponíveis. Para a exibição de
múltiplos itens disponíveis para escolha, esses componentes fazem uso de listas ou
coleções em geral, que devem ser criadas e controladas nas propriedades
responsáveis nos Managed Beans como temos feito até agora. Como novidade,
teremos que ter uma propriedade capaz de armazenar uma coleção de itens em nosso
bean, dado que agora o usuário poderá selecionar mais de uma opção em suas
interações.

 <h:selectManyCheckbox> - Componente populado de forma dinâmica por meio


de uma propriedade existente no bean e atrelado a uma outra propriedade
(coleção) que armazenará as opções do usuário para esse componente
(nenhuma, uma, ou mais de uma).

o index.xhtml:

<h:outputLabel value="Aprovações (Usando selectManyCheckbox):" /> <br />


<h:selectManyCheckbox value="#{aluno.aprovações}" >
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectManyCheckbox>

o Managed Bean "Aluno":

private List<String> aprovações;


private List<String> materiasEscolhidas;

public List<String> getAprovacoes() {


return aprovacoes;
}
public void setAprovações(List<String> aprovacoes) {
this.aprovacoes = aprovacoes;
}

public List<String> getMateriasEscolhidas() {


if (this.materiasEscolhidas == null){
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 37

o Navegador:

 <h:selectManyMenu>: Esse componente é dificilmente usado na prática e apresenta


renderizações diferentes nos diversos navegadores de mercado.

o index.xhtml:

<h:outputLabel value="Aprovações (Usando selectManyMenu):" /> <br />


5
<h:selectManyMenu value="#{aluno.materiasMenu}" >

<f:selectItems value="#{aluno.materiasEscolhidas}"/>

</h:selectManyMenu>

o Managed Bean "Aluno":

private List<String> materiasMenu;


private List<String> materiasEscolhidas;

public List<String> getMateriasMenu() {


return materiasMenu;
}
public void setMateriasMenu(List<String> materiasMenu) {
this.materiasMenu = materiasMenu;
}
public List<String> getMateriasEscolhidas() {
if (this.materiasEscolhidas == null){
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


38 Parte 5
o Navegador:

Google Chrome:

Mozilla Firefox:

 <h:selectManyListbox>: visualmente idêntico ao componente Listbox usado para


seleção simples, porém permite seleção múltipla usando as teclas SHIFT OU CTRL
(Command no Mac). Segue às mesmas regras dos componentes semelhantes
apresentados nesse item.

o index.xhtml:

<h:outputLabel value="Aprovações (Usando selectManyListbox):" /> <br />


<h:selectManyListbox value="#{aluno.materiasListbox}" >
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectManyListbox>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 39

o Managed Bean "Aluno":

private List<String> materiasListbox;


private List<String> materiasEscolhidas;

public List<String> getMateriasListbox() {


return materiasListbox;
}
public void setMateriasListbox(List<String> materiasListbox) {
this.materiasListbox = materiasListbox;
}
public List<String> getMateriasEscolhidas() {

5
if (this.materiasEscolhidas == null){
this.materiasEscolhidas = new ArrayList<String>();
this.materiasEscolhidas.add("Matemática");
this.materiasEscolhidas.add("Português");
this.materiasEscolhidas.add("Biologia");
this.materiasEscolhidas.add("Física");
this.materiasEscolhidas.add("Quimica");
}
return this.materiasEscolhidas;
}

o Navegador:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


40 Parte 5
Botões e Links
Botões e links são componentes geralmente associados a uma ação, que pode
ser compreendida como a chamada a um método no Managed bean. Ainda, podem
estar associados a um comando de navegação como o carregamento de outra página
na aplicação ou fora dela. São usados de forma diferente para realizar requisições via
POST ou GET e podem ser associados ainda a métodos que rodem do lado do cliente,
métodos Javascript, por exemplo.

 <h:commandButton> e <h:commandLink>: São os botões e links mais


tradicionais na utilização em aplicações web. Redundam em uma requisição
HTTP do tipo POST, geralmente invocando um método de um bean e/ou
expedindo algum comando de navegação.

o index.xhml:

<h:outputText value="Exemplo de utilização de um commandButton: " />


<h:commandButton value="Enviar"
actionListener="#{aluno.umMetodoQualquer()}"/>

<h:outputText value="Exemplo de utilização de commandLink: "/>


<h:commandLink value="Enviar"
actionListener="#{aluno.umMetodoQualquer()}"/>

o Managed Bean "Aluno":

public void umMetodoQualquer(){


//código aqui...
}

o Navegador:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 41

 <h:button> e <h:link>: Esses componentes são visualmente idênticos aos anteriores,


porém realizam requisições via GET. São novos na especificação JSF e principalmente
usados para chamadas a serviços HTTP REST, muito usados nos dias atuais, onde as
redes sociais tem grande relevância. Recebem, por vezes, parâmetros a serem passados
diretamente na requisição GET, via URL. Para tanto, utiliza-se da biblioteca Core (f:) e
sua tag <f:param />

o index.xhtml: Perceba o atributo "outcome" que referencia-se a uma String


mapeada para uma página qualquer. Nesse caso, o valor "index" apenas
recarrega a página atual.

<h:outputText value="Button (submit via GET): " />


<h:button value="Enviar (via GET)" outcome="index" >
<f:param name="escola" value="GrandePorte"/>

5
</h:button>

<h:outputText value="Link (submit via GET): " />


<h:button value="Enviar (via GET)" outcome="index" >
<f:param name="escola" value="GrandePorte"/>
</h:button>

o Managed Bean "Aluno": Não há vinculações com o bean neste exemplo.


Poderíamos substituir o conteúdo de cada um dos atributos detalhados acima
para esses componentes por valores dinâmicos, linkados a alguma propriedade
de um Managed Bean.

o Navegador:

 <h:commandLink>: Esse componente representa um link comum e estático do HTML.


Claro que podemos ligar seu atributo "value" com uma propriedade do bean, mas não
apresenta demais funcionalidades como as tags anteriores. Recebe o endereço de seu
link diretamente no atributo "value".

o index.xhtml:

<h:outputText value="OutputLink (exige URL de destino): " />


<h:outputLink value="http://www.google.com" target="_blank">
Ir para a página do Google
</h:outputLink>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


42 Parte 5

o Managed Bean: sem conexão com o bean. A afirmação feita aos componentes
<h:button> e <h:link> também se aplicam a esse componente nesse item.

o Navegador:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 43

Contêineres e Organização: panelGrid e PanelGroup

Os componentes <h:panelGrid> e <h:panelGroup> são utilizados para renderizar tabelas


HTML. Suas finalidades são a organização de layout dos componentes a serem exibidos. a tag
panelGroup é utilizada como forma de agrupar componentes em uma única célula.

 <h:panelGrid> e <h:panelGroup>

o index.xhtml: vale lembrar que todos os componentes mostrados devem estar


dentro de um <h:form> para serem anexados a alguma propriedade de um
Managed Bean ou para realizar qualquer requisição. Neste caso, incluímos um
<h:form> explicitamente para lembrar a importância desse feito. Note a
utilização da tag panelGroup ao final do código.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


44 Parte 5
<h:form>
<h:panelGrid columns="2" title="Cadastro de Alunos">
<f:facet name="header">
<h:outputText value="Cadastro de Alunos" />
</f:facet>

<h:outputLabel value="Nome: " for="alunoNome2" />


<h:inputText id="alunoNome2" value="#{aluno.nome}"/>

<h:outputLabel value="Endereço: " for="endAluno2"/>


<h:inputTextarea id="endAluno2" value="#{aluno.endereco}" />

<h:outputLabel value="Senha: " for="alunoSenha2" />


<h:inputText id="alunoSenha2" value="#{aluno.senha}"/>

<h:outputLabel value="Matéria: " />


<h:selectOneRadio value="#{aluno.materiaEscolhidaRadio}"
layout="pageDirection">
<f:selectItem itemLabel="Matemática"
itemValue="Matemática"/>
<f:selectItem itemLabel="Português" itemValue="Português"/>
<f:selectItem itemLabel="Biologia" itemValue="Biologia"/>
<f:selectItem itemLabel="Física" itemValue="Física"/>
<f:selectItem itemLabel="Química" itemValue="Química"/>
</h:selectOneRadio>

<h:outputText value="" />


<h:outputText value="" />

<h:outputLabel value="Aprovações anteriores:" />


<h:selectManyCheckbox value="#{aluno.aprovacoes}"
layout="pageDirection">
<f:selectItems value="#{aluno.materiasEscolhidas}"/>
</h:selectManyCheckbox>

<h:panelGroup >
<h:commandButton value="Cadastrar" />
<h:graphicImage library="imagens" name="Check_24x24.png"/>
</h:panelGroup>
</h:panelGrid>
</h:form>

o Managed Bean "Aluno": como já foi demonstrado em cada um dos itens


individualmente nos tópicos anteriores, não será feito nesta Seção.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 45

o Navegador: Perceba a organização e alinhamento dos itens sem a necessidade


de posicionamento manual pelo desenvolvedor.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


46 Parte 5
Adicionando componentes à página: Javascript, CSS, Imagens
e Mensagens

Uma página web é composta de uma grande quantidade de componentes.


Esses componentes podem ser itens de marcação gráficos, conteúdo, regras de estilo
aplicáveis, scripts e funções, imagens, vídeos e outros tipos de mídia, etc.

Veremos algumas tags de vital importância em aplicações web em geral e que,


em JSF, tornam a rotina do desenvolvedor muito mais tranquila e versátil. Note nos
exemplos abaixo, que as tags possuem dois atributos: library e name. O primeiro
deles, library, é uma comodidade trazida pelo JSF para referenciar subpastas criadas
conforme a comodidade do desenvolvedor dentro de uma pasta chamada resources.
Essa pasta deverá ser criada dentro da pasta WebContent de seu projeto (ou na raiz
das páginas xhtml), caso seja de vontade do desenvolvedor. O atributo name refere-
se ao nome do arquivo dentro da pasta especificada na tag anterior. Esse mecanismo
livra da necessidade de se preocupar com longos caminhos para referenciar arquivos.

 Inserindo folhas de estilo em cascata (CSS) a uma facelet:

o <h:outputStylesheet>: essa tag insere uma tag HTML <link> na região


do cabeçalho da página (<head>), independente do local onde foi
declarada.

<h:outputStylesheet library="css" name="main.css" />

 Inserindo um script javascript a uma facelet:

o <h:outputScript>: essa tag insere uma referência HTML <script> no


local onde foi declarada.

<h:outputScript library="js" name="main.js" />

 Inserindo uma imagem a uma facelet:

o <h:graphicImage>: essa tag insere uma tag HTML <img> na página


exatamente no local onde for declarada.

<h:graphicImage library="imagens" name="Check_24x24.png"/>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 47

Biblioteca JSF Core

A biblioteca Core contém componentes que são independentes das tags HTML
para renderização da página. A maior parte dessas tags representam objetos que são
adicionados aos componentes, como os seguintes:

 Atributos;
 Parâmetros;
 Facets;
 Ouvintes;
 Conversores;
 Validadores;

5
 Itens de Seleção.

Alguns desses itens já foram ou serão vistos ao longo do curso em situações


reais de utilização.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


48 Parte 5
Tag Descrição
Attribute Define um atributo (chave/valor) em seu componente
pai.
Param Adiciona um componente filho como parâmetro ao
componente pai.
Facet Adiciona um "facet"(faceta/comportamento) ao
componente.
actionListener Adiciona um ouvinte de eventos ao componente.
setPropertyActionlistener Adiciona um ouvinte de eventos que configura uma
propriedade (JSF 1.2).
valueChangeListener Adiciona um ouvinte para o evento valueChange.
phaseListener Adiciona um ouvinte para o evento de fase do
componente (JSF 1.2).
Event Adiciona um ouvinte de eventos do sistema.
Converter Adiciona um conversor arbitrário a um componente.
convertDateTime Adiciona um conversor do tipo dateTime ao
componente.
convertNumber Adiciona um conversor de número ao componente.
Validator Adiciona um validador ao componente.
validateDoubleRange Valida um range do tipo double para o valor de um
componente.
validateLength Valida o comprimento do valor de um componente.
validateLongRange Valida um range do tipo long para o valor de um
componente.
validateRequired Verifica se um valor está presente (JSF 2.0).
validateRegex Valida um valor com base em uma expressão regular
(JSF 2.0).
validateBean Usa a API de Bean Validation (JSR 303) para validação
(JSF 2.0).
loadBundle Carrega um Resource Bundle e armazena as
propriedades em um mapa.
selectItems Especifica itens para componentes de seleção.
selectItems Especifica um item para componentes de seleção.
Verbatim Converte texto contendo linguagem de marcação em um
componente.
viewParam Define um parâmetro de view, que pode ser inicializado
com um parâmetro de requisição (JSF 2.0).
Metadata Guarda parâmetros de view (JSF 2.0).
Ajax Habilita comportamento Ajax para os componentes (JSF
2.0).
View Usado para especificar a localidade da página (locale) ou
um ouvinte de fase
Subview Não é necessário para facelets.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 49

Navegação

Nesse capítulo falaremos sobre navegação em aplicações JSF 2.x. Esse


assunto abrange como redirecionaremos ou moveremos o usuário para as diversas
páginas de nossa aplicação, dependendo de sua interação e de decisões tomadas em
nível de programação. Vejamos um exemplo visual que ilustra um planejamento de
navegação simples em uma aplicação web.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


50 Parte 5
Note que, a cada movimentação de uma página para outra, existe uma String
que representa um resultado, um caso de navegação, denominado pelo JSF de
outcome. É com base na produção de "outcomes "que a navegação se processa para
essa ou para aquela página. O que faremos é mapear os casos de navegação
("outcomes") para as páginas de nossa aplicação, baseando-se na origem do evento
disparado para a navegação e na página de destino mapeada para o resultado
recebido.

Navegação Estática Implícita

Na navegação implícita, o outcome provém diretamente do click ou interação


do usuário com algum componente da aplicação como um botão ou link. A
implementação JSF faz a navegação em grande parte por conta própria, inferindo qual
página deverá ser exibida, tendo como base a String configurada como outcome.

Este caso é chamado de navegação implícita porque não existe qualquer


mapeamento feito pelo desenvolvedor, de outcomes para páginas da aplicação. A
implementação JSF procura inferir qual é o caso pela String.

Por exemplo, se o usuário estiver na página index.xhtml e, ao clicar no botão


definido por:

<h:button value="Visitar a galeria" outcome="galeria" >

ou

<h:commandButton value="Visitar a galeria" action="galeria"/>

a implementação JSF tentará fazer o redirecionamento para uma página chamada


"galeria" com a mesma extensão da página atual, ou seja, xhtml. Se o outcome
também vier sem a "/", a página direcionada será para o contexto da página atual e
nesse caso, a página galeria.xhtml e index.xhtml deverão estar no mesmo diretório.

Perceba ainda que existe diferença onde deverá ser colocado o outcome. No
caso de um <h:button> ou <h:link> deverá estar no atributo outcome e, no caso de um
<h:commandButton> ou <h:commandLink> deverá estar no atributo action. O único
detalhe a ser lembrado é que os dois últimos precisam estar em um <h:form> para
terem o redirecionamento funcionando.

Navegação Estática Explícita

A navegação explícita utiliza-se de declarações XML feitas no arquivo de


configuração faces-config.xml, onde registramos os casos de navegação, delineando
cada resultado ou outcome conforme a página de origem para um destino ou página a
encaminhar o usuário. Esse tipo de navegação ainda é estática, exigindo do
desenvolvedor que os casos de navegação sejam inseridos manualmente no arquivo
faces-config.xml. É possível de se utilizar wildcards como * afim de representar
diversos caracteres, da mesma forma que usamos nas tags <url-pattern>.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 51

Para definir um caso de navegação no faces-config.xml, procederemos com a


seguinte estrutura de nós XML:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


52 Parte 5
A estrutura em formato XML:

<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"


xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>sucesso</from-outcome>
<to-view-id>/login.xhtml</to-view-id>
</navigation-case>

<navigation-case>
<from-outcome>falha</from-outcome>
<to-view-id>/erro.xhtml</to-view-id>
</navigation-case>

<!-- E tantos outros navigation-cases forem necessários -->


</navigation-rule>
<!-- E tantos outros navigation-rules forem necessários -->
</faces-config>

A princípio essa estrutura pode parecer um pouco confusa, mas na primeira


utilização tudo se torna claro.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 53

Navegação Dinâmica

Temos visto até agora como configurar nossa aplicação para navegar entre
páginas usando outcomes. Outcomes nada mais são do que Strings que, ao serem
interpretadas pela implementação JSF, busca alguma regra de navegação associada
e, caso não encontre, tenta navegar para uma página de mesmo nome, inferindo o
caminho e extensão do arquivo a partir da página de origem da requisição.

Esse mecanismo é estático. Precisamos dizer literalmente quais serão os


outcomes, sem possibilidade de mudá-los em tempo de execução.

Com a navegação dinâmica, faremos a ligação dos outcomes com a lógica de

5
nossa aplicação, deixando para o tempo de execução a decisão do destino de nossa
navegação.

Um botão ou link, que antes nos direcionava sempre ao mesmo destino, por
click dado, agora direcionará para uma página diferente a cada click, sendo essa
decisão atrelada a um método em um Managed Bean.

Vejamos um exemplo com três páginas. Da página index inicial é sorteado um


outcome para a próxima página:

index.xhtml:

<h:form>
<h1>Esta é a Página Dados!</h1>
<h:button value="Próxima página" outcome="#{meuBean.navegacao()}" />
</h:form>

dados.xhtml:

<h:form>
<h1>Esta é a Página Dados!</h1>
<h:commandButton value="Retornar..." action="voltar" />
</h:form>

conteudo.xhtml:

<h:form>
<h1>Esta é a Página Conteúdo!</h1>
<h:commandButton value="Voltar" action="voltar" />
</h:form>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


54 Parte 5
Managed Bean "MeuBean":

@ManagedBean
@SessionScoped
public class MeuBean {

public String navegacao(){


Random random = new Random();
int numSorteado = random.nextInt(9);
if (numSorteado <=4){
return "prosseguirDados";
}else{
return "prosseguirConteudo";
}
}
}

faces-config.xml:

<navigation-rule>
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>prosseguirDados</from-outcome>
<to-view-id>/dados.xhtml</to-view-id>
</navigation-case>

<navigation-case>
<from-outcome>prosseguirConteudo</from-outcome>
<to-view-id>/conteudo.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>voltar</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 55

Teoria facelets

Estudaremos a partir de agora a utilização do mecanismo de Facelets como


solução para a camada view de nossas aplicações JSF e todas as suas
funcionalidades.

Templates

É muito comum o uso de modelos visuais consistentes em páginas web de


forma que o usuário possa ter uma experiência de navegação agradável e fácil,
familiarizando-se com os layouts das páginas que visita. Não faria sentido ter um
5
layout e uma identidade de cores para cada página da aplicação.

Por esse e outros motivos, a reutilização da estrutura visual das páginas é


assunto comum entre web developers e de fácil utilização no framework Java Server
Faces 2.x.

Um template nada mais é do que um modelo geral e abstrato com placeholders


que serão preenchidos por conteúdo real nas páginas de implementação concreta na
aplicação.

Vejamos um diagrama esquemático dessa ideia:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


56 Parte 5

Perceba no diagrama que o template (página principal.xhtml) possui duas


áreas já estilizadas e definidas que serão imutáveis e padronizadas a todas as páginas
que implementarem esse modelo: o cabeçalho e o rodapé. Note ainda que as outras
duas áreas, a barra lateral e o quadro central são placeholders para conteúdo
customizado de cada página. Dessa forma, é possível manter um visual consistente e
garantir uma estrutura única em todas as páginas que seguem esse template.

Para implementar templates, faremos uso de uma outra biblioteca do JSF, a


biblioteca Facelets. Para implementar essa biblioteca, precisamos declarar seu
namespace na tag <html> da página em questão:
xmlns:ui="http://java.sun.com/jsf/facelets" .

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 57

O conteúdo da biblioteca Facelets é delineado abaixo na tabela:

Tags Descrição
ui:include Inclui conteúdo de outro arquivo XML.
ui:composition Quando usado sem um atributo template, uma composition é uma
sequência de elementos que podem ser inseridos em algum outro
lugar. A composição pode ter partes variáveis (especificadas com
tags filhas ui:insert).
Quando usado com o atributo template, o template é carregado. As
tags filhas dessa tag determinam as partes variáveis do template. O
conteúdo do template substitui essa tag.
ui:decorate Quando usado sem um atributo template, ui:decorate especifica uma
página dentro da qual podem ser inseridas outras partes ou trechos.

5
As partes variáveis são especificadas com tags filhas ui:insert.
Quando usada com o atributo template, o template é carregado. As
tags filhas dessa tag determinam as partes variáveis do template.
ui:define Define conteúdo que será inserido em um template com a tag
correspondente ui:insert.
ui:insert Insere conteúdo em um template. O conteúdo é definido dentro da
tag que carrega o componente.
ui:param Especifica um parâmetro que é passado para um arquivo incluído ou
um template.
ui:component Essa tag é idêntica à ui:composition, só que nesse caso ela cria um
componente que é adicionado à árvore de componentes.
ui:fragment Essa tag é idêntica à ui:decorate, só que nesse caso ela cria um
componente que é adicionado à árvore de componentes.
ui:debug A tag ui:debug permite aos usuários mostrar uma janela de debug,
por meio de um atalho de teclado, que mostra a hierarquia de
componentes para a página atual e as variáveis de escopo application.
ui:remove A implementação JSF remove tudo o que estiver dentro de tags
ui:remove.
ui:repeat Itera sobre uma lista, array, result set ou objeto individual.

Vejamos um exemplo de como templates funcionam por meio de uma atividade.

Usaremos para templates as tags: ui:composition, ui:insert, ui:define. Em


nossa página de template usaremos a biblioteca Primefaces 3.3.1., cujo jar pode ser
baixado em:

http://www.primefaces.org/downloads.html

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


58 Parte 5
Composição / Modularização
Derivando a idéia dos templates, vista acima, pode-se imaginar situações em
que um bloco de código seja necessário para inserção dinâmica em qualquer página
que desejarmos. Nos templates, definimos o local para o placeholder e as páginas que
implementam o modelo dão conteúdo real a eles.

Os placeholders são localizações estáticas na página. Apenas seu conteúdo é


dinâmico. Com a composição, criamos um bloco de código que pode ser inserido em
qualquer local de qualquer página, bastando para isso referenciar sua localização.

Vejamos um exemplo:

Criando uma nova página em branco chamada formularioLogin.xhtml com o


seguinte conteúdo:

<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="E-mail: " for="email" />
<h:inputText id="email" />
<h:outputLabel value="Senha: " for="senha" />
<h:inputText id="senha" />

<h:commandButton value="Enviar"/>
</h:panelGrid>
</h:form>
</ui:composition>

poderíamos inseri-la em qualquer ponto de qualquer página de nossa aplicação com a


tag:

<ui:include src="/formularioLogin.xhtml" />

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 59

Practice

Atividade TRABALHO EM DUPLA

5
Experimentação com componentes

a) Crie um novo projeto no Eclipse e configure-o para trabalhar com JSF 2.1. Dê o
nome de TesteComponentes.

b) Crie um facelet chamado cadastro.xhtml com um formuário de cadastro


apropriadamente desenhado e ligado a um Managed Bean. Esse Managed Bean
deverá se chamar Cadastro e deverá ter o escopo de sessão. Garanta que todos os
componentes possuam a estrutura adequada para atender à página.

c) Crie uma outra página chamada bemvindo.xhtml e exiba todos os dados do usuário
cadastrado. Essa página deverá ser chamada a partir do botão "Cadastrar" da página
de cadastro

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


60 Parte 5

Atividade TRABALHO EM DUPLA

Navegação estática implícita e explícita

a) Crie um novo projeto no Eclipse já configurado para JSF 2.x. Dê o nome de


NavegacaoJSF;

b) Crie uma página denominada index.xhtml (e a configure como default para


welcome-file em seu projeto). Essa página, deverá possuir o seguinte corpo (<body>):

<h1>Navegação JSF!</h1>
<br />
<br />
<h:button value="Ir para página dados" outcome="dados" >
<f:param name="escola" value="GrandePorte"/>
</h:button>

Note que essa é uma página bem simples, com apenas um componente, um
<h: button>. Lembre-se de que esse componente envia uma requisição via GET.
Estamos aproveitando a ocasião e demonstrando também o envio de parâmetros para
essa requisição (que serão anexados à URL já que trata-se de método GET). Esse
botão envia um outcome com o valor de "dados". Essa String será usada pelo JSF
para procurar uma página de nome dados.xhtml (mesma extensão da página emissora
da requisição) na mesma pasta da página atual e enviar a ela o parâmetro de
requisição: escola=GrandePorte.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 61

c) Crie a página dados.xhtml, que deverá possuir um corpo como o seguinte:

<h:form>
<h1>Esta é a página de Dados!</h1>
<br />
<br />

<h3>Parâmetro passado por GET: </h3>


<h:outputText value="#{param.escola}" />
<br />
<br />

5
<!-- <h:button value="Retornar..." outcome="index" /> -->
<h:commandButton value="Retornar..." action="index" />
</h:form>

Essa página será chamada pelo <h:button> na página index.xhtml e receberá


dia GET o parâmetro passado. Veja que o parâmetro está sendo exibido na linha:

<h:outputText value="#{param.escola}" />

Aproveitaremos para acrescentar que o objeto implícito param está disponível


para uso com Expression Language, da mesma forma como fazíamos nas JSPs. E ele
não é o único. Veja abaixo uma tabela dos parâmetros que podem ser usados com EL:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


62 Parte 5
bjeto Implícito Descrição
#{component} o componente UIComponent atual
#{facesContext} o objeto FacesContext atual
#{view} o objeto UIViewRoot atual
#{request} o corrente objeto HttpServletRequest
#{session} o corrente objeto HttpSession
#{application} o ServletContext atual
#{flash} o corrente objeto Flash(que também implementa um mapa)
#{cc} o corrente componente composto (Composite)
#{requestScope} o atual mapa de atributos de requisição
#{viewScope} o atual mapa de atributos da view
#{sessionScope} o atual mapa de atributos da sessão
#{applicationScope} o atual mapa de atributos da aplicação
#{initParam} o atual mapa de parâmetros do contexto
#{param} o atual mapa de parâmetros de requisição
#{paramValues} o atual mapa de valores dos parâmetros de requisição
#{header} o atual mapa do header da requisição
#{headerValues} o atual mapa de valores do header da requisição
#{cookie} o atual mapa de cookies da requisição
#{resource} converte um identificador JSF de recurso para uma URL
concreta do recurso.

d) Rode sua aplicação no servidor e teste a navegação implícita criada entre essas
duas páginas.

e)

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 63

e) Você, atento ao código de ambas as páginas, percebeu que usamos no botão da


página dados, o componente <h:commandButton> ao invés de <h:button> como na
primeira página, certo? Pois bem, atente para a sintaxe de construção e diferenças
entre um e outro. Descomente a linha existente nessa página para trocar o
componente para um <h:button> e teste novamente. Faça o mesmo, trocando o
componente para <h:commandLink> e <h:link>.

f) Neste item, você deverá tornar a navegação entre essas páginas, explícita.
Primeiramente, crie as regras de navegação, usando os seguintes comandos, em seu
arquivo faces-config.xml:

<navigation-rule>

5
<from-view-id>/index.xhtml</from-view-id>
<navigation-case>
<from-outcome>prosseguir</from-outcome>
<to-view-id>/dados.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

<navigation-rule>
<from-view-id>/dados.xhtml</from-view-id>
<navigation-case>
<from-outcome>voltar</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

g) Altere os outcomes e actions em seus botões conforme o mapeamento definido


acima e execute novamente sua aplicação. Perceba que tudo funciona da mesma
forma, porém agora usamos outcomes com nomes diferentes das páginas para os
quais são mapeados, por isso é exigido que façamos essas declarações explícitas no
faces-config.xml.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


64 Parte 5

Atividade Revisão aos pares

Navegação dinâmica

Aproveitando o código da atividade anterior, você deverá complementá-lo com


algumas novas funcionalidades:

a) Crie mais uma página em sua aplicação, denominada conteudo.xhtml. Essa página
deverá possuir um botão ou link para retornar à página index.xhtml, nossa página
inicial.

b) Altere nossa página inicial para receber do usuário o outcome desejado. Utilize o
controle que preferir para capturar esse dado. Dê uma dica ao usuário de quais são os
resultados possíveis (algo semelhante à funcionalidade de um menu). Para isso:

b.1) Crie um Managed Bean denominado NavBean com uma propriedade para
armazenar a escolha do usuário;

b.2) Crie um método que será o ponto de decisão para a navegação da


aplicação. Esse método deverá estar atrelado ao botão ou link da página que
disparará o evento.

c) Crie os casos de navegação explícita no arquivo faces-config.xml, obedecendo as


seguintes regras:

 provindos da página index.xhtml:


o outcome: consulta ==> navega para dados.xhtml
o outcome: verConteudo ==> navega para conteudo.xhtml

 provindos de qualquer página da aplicação:


o outcome: voltar ==> navegar para index.xhtml

d) Teste e execute sua aplicação.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 65

Atividade Revisão aos pares

Demonstrando o uso de templates, fazendo uso


da biblioteca de componentes ricos Primefaces 3.3.1.

a) Crie um novo projeto no Eclipse com suporte a JSF 2.x e Primefaces 3.3.1., dando
o nome de TemplatesJSF. Limpe o projeto, em seguida, excluindo o que foi criado por
5
Default pelo Eclipse;

b) Crie uma página chamada principal.xhtml, que será nosso template para as demais
páginas. Essa página será composta pelo seguinte conteúdo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


66 Parte 5
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>
<ui:insert name="title">Título padrão</ui:insert>
</title>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="120">
<h1>Cabeçalho do Site</h1>
</p:layoutUnit>
<p:layoutUnit position="west" size="200">
<h:form>

<p:tieredMenu style="width:180px;">
<p:submenu label="Alunos" icon="ui-icon-refresh">
<p:menuitem value="Cadastrar" icon="ui-icon-disk"/>
<p:menuitem value="Consultar"
icon="ui-icon-arrowrefresh-1-w" />
</p:submenu>
<p:submenu label="Professores" icon="ui-icon-newwin">
<p:menuitem value="Consultar" icon="ui-icon-close" />
</p:submenu>
<p:separator />
<p:submenu label="Navegação" icon="ui-icon-extlink">
<p:submenu label="Links">
<p:menuitem value="Grande Porte"
url="http://www.grandeporte.com.br" />
<p:menuitem value="PrimeFaces"
url="http://www.primefaces.org"/>
</p:submenu>
<p:menuitem value="Google" url="http://www.google.com.br" />
</p:submenu>
</p:tieredMenu>

</h:form>
</p:layoutUnit>
<p:layoutUnit position="south" size="100">
<h1>Rodapé do site</h1>
</p:layoutUnit>
<p:layoutUnit position="center">
<ui:insert name="center" />
</p:layoutUnit>
</p:layout>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 67

Essa é uma página bem simples de se analisar. Ela usa o componente


<p:layout> e <p:layoutUnit> do Primefaces para diagramar a página em quatro regiões
bem definidas: norte, sul, oeste e centro. Dessas regiões, somente a região Centro
será populada pelas páginas que implementarão esse template. Todas as demais
regiões são fixas e já desenvolvidas neste template. Perceba o uso da tag <ui:insert>
no <h:head> dessa página e na região center do layout definido. Essa tag define um
placeholder para conteúdo e um nome pelo qual é possível acessá-lo.

Todo o conteúdo circundado é código referente à montagem do menu rico da


biblioteca Primefaces 3.3.1. Esse componente <p:tieredMenu> já possui integração
com Ajax e uma série de funcionalidades e animações.

c) Implementaremos agora nossa primeira página cliente desse template. Crie uma

5
página chamada index.xhtml e configure sua aplicação para que ela seja a página
padrão de inicialização. Deverá possuir o seguinte código:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">

<ui:composition template="/principal.html">

<ui:define name="title">
Página composta com template!
</ui:define>

<ui:define name="center">
<h2>Conteúdo inserido pela página index!!</h2>
<p:editor />
</ui:define>

</ui:composition>
</html>

Pouco código certo? Pois é, essa página usa os benefícios da composição de


Facelets por meio de templates.

d) Execute sua aplicação e verifique o resultado. Você perceberá que seu menu está
escondido por trás do <p:layoutUnit> definido como "center". Esse é um problema de
CSS que resolveremos já.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


68 Parte 5
e) Crie uma pasta chamada resources em sua pasta WebContent e, dentro dela, uma
pasta chamada css. Dentro desta última, crie uma folha de estilo de nome principal.css
com o seguinte conteúdo:

.ui-layout-west {
z-index:20 !important;
overflow:visible !important;;
}

.ui-layout-west .ui-layout-unit-content {
overflow:visible !important;
}

f) Como próximo passo, acrescente essa folha de estilos ao seu template, de modo
que todas as páginas-filhas possam fruir desse benefício. Lembra-se da tag
<h:outputStylesheet>? Coloque-a no <h:head> do seu template.

<h:outputStylesheet library="css" name="principal.css" />

g) Rode novamente sua aplicação e veja que agora o problema está resolvido.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 5 69

Performance

Atividade Todos juntos

5
Transformando o menu lateral em um componente

a) Utilizando-se da aplicação criada na Atividade 3, crie uma nova página chamada


menuLateral.xhtml com o seguinte código:

<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">

</ui:composition>

b) Copie todo o código do menu lateral utilizado na página template principal.xhtml


para essa nova composition.

c) Insira a página criada no mesmo local onde estava antes, porém agora usando a
tag <ui:include>.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


70 Parte 5

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte

Java Persistence API (ou simplesmente JPA) é


uma API padrão da linguagem Java que descreve uma
interface comum para frameworks de persistência de
dados. A JPA define um meio de mapeamento objeto-
relacional para objetos Java simples e comuns (POJOs),
denominados beans de entidade. Diversos frameworks
de mapeamento objeto/relacional como o Hibernate
implementam a JPA. Também gerencia o
desenvolvimento de entidades do Modelo Relacional
usando a plataforma nativa Java SE e Java EE.
Versão 2.1.1
Parte 6 3

Preparation

Trocando Ideias É agora que você fala !!

Antes de iniciarmos, vamos conversar sobre os tópicos apresentados na


capa desta parte. Isso é importante para que seu instrutor e seus colegas

6
saibam como está seu conhecimento sobre o assunto e se você precisa ou
pode fornecer ajuda aos colegas e instrutor.

 O que você já sabe?


 O que você não sabe?
 Porque é importante conhecer estes tópicos?
 Quais são os seus temores?
 O que você considera difícil?

Reflexão É aqui que você se compromete !!

Depois de falar sobre o assunto com seus colegas e instrutor, escreva,


desenhe, rabisque, diga algo sobre o que você vai fazer para dominar esses
tópicos. Comprometa-se!

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


4 Parte 6

Presentation

Teoria Eventos em jsf

Eventos de botões e links em Java Server Faces

Toda aplicação necessita trabalhar com os eventos gerados pelos usuários


quando interagem com a aplicação, seja um click em um botão, ou uma seleção em
um componente de entrada de texto, ou ainda click em um link.

O JSF dá suporte a quatro tipos de eventos:

 Eventos de alteração de valor – Componentes de aceitam alteração de valor:


inputText, selectOneRadio, selectManyMenu – quando o valor do componente
sofre alteração.

 Eventos de ação – São disparados por componentes que se originam de uma


ação: commandButton, commandLink – Quando um botão ou link são
ativados(clicados).

 Eventos de fase – Disparados pelo ciclo de vida do JSF.

 Eventos de sistema.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 5

EVENTOS DE AÇÃO
Vamos codificar uma simples aplicação onde utilizaremos os eventos de ação:
Crie um arquivo chamado acaoBTO.xhtml conforme código abaixo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Eventos em JSF</title>
</h:head>
<h:body>
<h:form>
<h:commandButton value="Clique Aqui" actionListener="#{cliqueBean.mudaTexto}" />
</h:form>
</h:body>
</html>

Crie uma classe de nome CliqueBean.java com o escopo request conforme


código abaixo:
6
package br.com.grandeporte.acoes;

import javax.faces.bean.ManagedBean;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@ManagedBean
public class CliqueBean {

public CliqueBean() {
}

public void mudaTexto(ActionEvent e) {


UICommand c = (UICommand) e.getComponent();
c.setValue ("Clicado");
}
}

Execute a página acaoBTO.xhtml que acabamos de criar e verifique se a


saída e o comportamento se parecem com as imagens a seguir:

Ao executar a página acaoBTO.xhtm o


sistema apresentará no browser do usuário a
imagem IM-01, quando o usuário clicar no
botão, a aplicação irá submeter este form ao
servidor e apresentará como resultado a
imagem IM-02.
IM-01 IM-02

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


6 Parte 6
Esta primeira aplicação executa o código do método mudaTexto quando o
usuário interage com a aplicação clicando no commandButton que aparecerá no
browser, este componente tem no seu atributo actionListener o valor:

actionListener ="#{cliqueBean.mudaTexto}"

utilizando expressão de linguagem já visto anteriormente, isso gera um evento de


ação que remete o form para o servidor, e dentro dos seis ciclos que sua aplicação
percorre no servidor (especificamente na 5ª etapa – Invoke Application), executará os
métodos disparados pelos componentes que originam ações, isto um passo antes de
renderizar a página novamente para o browser, neste caso ele executará o método
public void mudaTexto(ActionEvent e) codificado no managedbean correspondente.

Mas por que usar o actionListener em vez do atributo action? Esta pergunta é
bastante conveniente, pois existem esses dois atributos do componente
commandButton para acessar métodos dos nossos ManagedBeans, e assim como a
pergunta é boa, a resposta será a altura! Já vimos anteriormente que existe um mapa
de navegação que espera que os métodos dos nossos managed beans retornem uma
string para que a aplicação saiba qual página renderizar para o usuário, então,
seguindo está lógica, podemos então usar o atributo action para acessar métodos que
irão retornar Strings para o mapa de navegação e usaremos o atributo actionListener
para acessar métodos que irão acessar a lógica de negócio de nossa aplicação (ver
M.V.C.), esta escolha de qual atributo irá acessar a lógica e qual irá acessar a
navegação tem um porquê, quando a framework JSF for executar os métodos de
ações ele executará primeiro os métodos actionlisteners para depois executar os
actions de nossas tags .xhtml.

Seguindo esta lógica eu posso então acrescentar o método no ManagedBean


CliqueBean:

package br.com.grandeporte.acoes;

import javax.faces.bean.ManagedBean;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;
@ManagedBean
public class CliqueBean {

public CliqueBean() {
}

public void mudaTexto(ActionEvent e) {


UICommand c = (UICommand) e.getComponent();
c.setValue ("Clicado");
}

public String navega(){


return "outraPagina";
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 7

e também acrescentar o atributo action no arquivo acaoBTO.xhtml


<h:commandButton value="Clique Aqui" actionListener="#{cliqueBean.mudaTexto}"
action="#{cliqueBean.navega}"/>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Eventos em JSF</title>
</h:head>
<h:body>
<h:form>
<h:commandButton value="Clique Aqui" actionListener="#{cliqueBean.mudaTexto}"

action="#{cliqueBean.navega}"/>

</h:form>
</h:body>

6
</html>

Execute novamente esta aplicação em modo debug fazendo uso de break


points nos dois métodos, desta forma ficará mais claro qual método a framework
executará primeiro.

Agora eu quem pergunto a você programador java, como foi que a aplicação
desenvolvida por você conseguiu mudar o valor do componente commandButton?
Para responder esta pergunta temos que entender a classe ActionEvent, seus
métodos e construtores, ressalto aqui a importância da documentação desta
framework, mas irei facilitar seus estudo mostrando um pouco desta classe de eventos.
Esta classe tem este construtor public ActionEvent(UIComponent componente) e
quando usamos o atributo actionListener acabamos lançando o componente que está
utilizando este atributo, claro que implicitamente a framework faz isto, por isso
conseguimos capturar o componente commandButton com o método
e.getComponent() que trás uma referência do próprio botão que ativou a ação.

Isto também ocorre com os componentes <H:CommandLink como veremos no


exemplo abaixo

Crie um arquivo chamado acaoLINK.xhtml conforme código abaixo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title> Eventos em JSF </title>
</h:head>

<h:body>
<h:form>
<h:commandLink id="link" value="Enviar" actionListener="#{mudaCorDaFonte.mudaCorLink}"/>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


8 Parte 6
Crie uma classe chamada MudaCorDaFonte.java conforme código abaixo:

package br.com.grandeporte.acao;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;

@ManagedBean
@RequestScoped
public class MudaCorDaFonte {

public void mudaCorLink(ActionEvent e) {


UICommand c = (UICommand) e.getComponent();
c.getAttributes().put("style","color:lime;text-align:center;font:19px Arial,sans-serif");
}
}

Execute o arquivo acaoLINK.xhtml e verifique se o comportamento foi igual ao


das imagens abaixo.
A imagem (IM-03) mostra o que será
renderizado no browser do usuário quando ele
requisitar a página acaoLINK.xhtml, quando o
usuário clicar no link ele enviará este form ao
servidor que acessará o método
mudaCorDaFonte(ActionEvent e) que por sua vez
IM-03 IM-04 irá mudar a cor, tamanho e o tipo da fonte
conforme (IM-04).

Também podemos atribuir eventos de ação a componentes utilizando a


biblioteca de apoio core, para isto vamos alterar o arquivo acaoLINK.xhtml conforme
código abaixo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title> Eventos em JSF </title>
</h:head>
<h:body>
<h:form>
<h:commandLink id="link" value="Enviar" >
<f:actionListener type="br.com.grandeporte.listern.MudaCorDaFonte" />
</h:commandLink >

</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 9

Altere o arquivo MudaCorDaFonte.java conforme código abaixo:

package br.com.grandeporte.listern;
import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;

@ManagedBean REMOVA ESSAS NOTAÇÕES


@RequestScoped

public class MudaCorDaFonte implements ActionListener {

@Override
public void processAction(ActionEvent e) {
UICommand c = (UICommand) e.getComponent();
c.getAttributes().put("style", "color:lime;text-align: center; font: 19px Arial,
sans-serif");
}

public void mudaCorLink(ActionEvent e) {


UICommand c = (UICommand) e.getComponent();
c.getAttributes().put("style", "color:lime;text-align: center; font: 19px Arial,
sans-serif");

6
}
}

Notem que esta classe MudaCorDaFonte.java agora não tem a notação


@ManagedBean, porém ela agora está implementando a interface chamada
ActionListener, esta interface ter um método abstrato que deverá ser reescrito por
você, programador Java, este método tem a seguinte assinatura:

processAction(ActionEvent):void

este tipo de código é muito parecido com a interface ActionListener usados nas
aplicações JSE vista no curso Java Level 1, mas não se engane, aquela interface faz
parte do pacote java.awt.ActionListener e esta que estamos usando faz parte do
pacote javax.faces.event.ActionListener, as duas interfaces tem métodos para serem
sobrescritos, e que serão executados todas vez que este listener ‘ouvir’ determinada
ação, em JSE o método abstrato era o actionPerformed e em JSF o método se chama
processAction.

O interessante de usar esta biblioteca de apoio é que podemos atribuir várias


tags deste tipo aos componentes inclusive em conjunto com os atributos listener nativa
do próprio componente, e a dúvida agora é qual dos métodos será executado
primeiro? Vamos ao modo debug para tirar suas dúvidas, mas adiantando, primeiro
executará o atributo actionListener nativa da tag, posterior as tags de apoio
<f:actionListener sucessivamente da primeira até a última, posterior o atributo action.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


10 Parte 6
EVENTOS DE ALTERAÇÃO DE VALOR
Os componentes que geram ações de alteração de valor são:

 <h:selectOneRadio/>
 <h:inputText/>
 <h:selectOneMenu/>

Estes componentes contém o atributos de nome valueChangeListener="" que


podem ser utilizados em conjunto com expressão de linguagem para executarem um
método de um managedBean no servidor conforme código abaixo:

Crie um arquivo .xhtml de nome alteracaovalor.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Eventos em JSF</title>
</h:head>
<h:body>
<h2>Eventos de alteração de valor do componente h:inputText</h2>
<h:form>
<h:outputLabel value="Preço: " for="preco"/>
<h:inputText valueChangeListener="#{produtoBean.mudaPreco}" id="preco" onchange="submit()"/>
</h:form>
</h:body>
</html>

Crie o arquivo ProdutoBean.java conforme código abaixo:

ManagedBean:
package br.com.grandeporte.mudancavalor;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;

@ManagedBean
@SessionScoped
public class ProdutoBean {
public void mudaPreco(ValueChangeEvent e) {
System.out.println("Preço antigo: " + e.getOldValue());
System.out.println("Preço novo: " + e.getNewValue());
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 11

Execute o arquivo alteracaovalor.xhtml e verifique se o comportamento dele é


igual ao das imagens logo abaixo:

IM-05 IM-06

IM-07
IM-08 6
Sua aplicação deve exibir no browser do usuário a
imagem(IM-05) para que o usuário possa digitar
algo no componente h:inputText (IM-06 e IM-08),
assim que o esse form for enviado, o método
mudaPreço(VlueChangeEvent) da classe
ProdutoBean.java será executado e exibirá o valor
antigo e o novo valor do componente no console
IM-09 (IM-07 e IM-09).

A impressão no console do valor antigo e valor novo ocorreu porque dentro do


método mudaPreco codificamos a impressão destes valores utilizando os métodos
getOldValue() e getNewValue() desta classe ValueChangeEvent, fica novamente a
dica para você dar uma olhada na documentação desta framework, mas adiantando,
esta Classe tem um este construtor:

public ValueChangeEvent(UIComponent component, Object oldValue, Object newValue) {


super(component);
this.oldValue = oldValue;
this.newValue = newValue;
}

Este construtor, além de gravar uma referência do componente que disparou


este evento, também guarda o valor que ele tinha anteriormente, e seu novo valor
dentro dos atributos globais this.oldValue e this.newValue, que podem ser
recuperados pelos método getOldValue() e getNewValue() destes atributos.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


12 Parte 6
A framework JSF também tem tags de apoio para este evento, a tag para
acessar uma classe listener é a <f:valueChangeListener />.

Crie uma classe de nome RegistraAlteracao.java para ilustrarmos o uso da tag


<f:valueChangeListener />.

package br.com.grandeporte.acoes;

import javax.faces.event.AbortProcessingException;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;

public class RegistraAlteracao implements ValueChangeListener {

@Override
public void processValueChange(ValueChangeEvent e)
throws AbortProcessingException {
System.out.println(" Preço antigo : " + e.getOldValue());
System.out.println(" Preço novo : " + e.getNewValue());
}
}

Notem que esta classe não tem as notações @ManagedBeans, porém, ela implementa
a interface ValueChangeListener, e por isso temos que sobrescrever o método
processValueChange(ValueChangeEvent):void , este método será executado quando este
listener for ativado.

Altere o arquivo alteracaovalor.xhtml conforme exemplo abaixo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</h:head>

<h:body>
<h2>Eventos de alteração de valor do componente f:valueChangeListener</h2>
<h:form>
<h:outputLabel value="Preço: " for="preco" />

<h:inputText id="preco">
<f:valueChangeListener type="br.com.grandeporte.listern.RegistraAlteracao" />
</h:inputText>

</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 13

Execute o arquivo alteracaovalor.xhtml e verifique se o comportamento dele é


igual ao das imagens abaixo.

IM-10 IM-11

O resultado é igual a do exemplo


anterior, mas é importante ressaltar
que neste exemplo estamos usando
um listener utilizando a tag
IM-12 <f:valueChangeListener/>

6
IM-14
IM-13

Como podemos perceber, esta classe implementa uma interface chamada


ValueChangeListener que por sua vez contém um método abstrato de nome
processValueChange(ValueChangeEvent e): void, desta forma podemos acessar
classes ouvintes de ações, no caso, de alteração de mudança de valor do componente
<h:inputText/>, também podemos utilizar a referencia do componente que causou o
evento, bem como seu valor antigo e novo, da mesma forma do exemplo anterior,
importante ressaltar que podemos utilizar várias tags <f:valueChangeListener/> em
conjunto com atributos valueChangeListener, sabendo que a framework executará
primeiro o atributo valueChangeListener, posterior as tags <f:valueChangeListener/>
consecutivamente.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


14 Parte 6
Vamos criar uma outra aplicação para por em prática os conhecimentos adquiridos até
aqui sobre EVENTOS DE ALTERAÇÃO:

Crie um arquivo .xhtml de nome pesquisa.xhtml conforme código abaixo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>ação de alteração de valor</title>
</h:head>
<h:body>
<h1>Pesquisa sobre preferência musical</h1>
<h:form>
<h2>Sexo:</h2>
<h:selectOneRadio valueChangeListener="#{produtoBean.mudaPreco}" onchange="submit()">
<f:selectItem itemValue="true" itemLabel="Homem" />
<f:selectItem itemValue="false" itemLabel="Mulher" />
</h:selectOneRadio>

<h2>Preferência musical:</h2>
<h:selectManyCheckbox value="#{produtoBean.arrStr}" onchange="submit()">
<f:selectItem itemLabel="GOSPEL" itemValue="Gospel"></f:selectItem>
<f:selectItem itemLabel="ROCK" itemValue="Rock"></f:selectItem>
<f:selectItem itemLabel="POP" itemValue="Pop"></f:selectItem>
<f:selectItem itemLabel="FORRO" itemValue="Forro"></f:selectItem>
<f:selectItem itemLabel="DANCE" itemValue="Dance"></f:selectItem>
</h:selectManyCheckbox>
</h:form>
</h:body>
</html>

Notem que estamos usando o evento onchange="submit()" em todos os


componentes deste form, isso sognifica que toda vez que o usuário clicar em um dos
componentes este form será enviado ao servidor. Notem também que estamos
utilizando o componente <h:selectManyCheckbox/> que nos permite selecionar vários
checkBox, sendo assim, o atributo que ele acessará deve ser do tipo que suporta um
vetor do tipo de variável correspondente.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 15

Crie o arquivo ProdutoBean.java dentro do pacote br.com.listener conforme


código abaixo:

package br.com.grandeporte.listern;

import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ValueChangeEvent;

@ManagedBean
@SessionScoped
public class ProdutoBean {
private ArrayList<String> arrStr = new ArrayList<String>();

public ProdutoBean(){}

public void mudaPreco(ValueChangeEvent e) {


System.out.println("Preço antigo: " + e.getOldValue());
System.out.println("Preço novo: " + e.getNewValue());
}

6
public void setArrStr(ArrayList<String> arrStr) {
for(String str : arrStr){
System.out.println("Tipo musical = " + str);
}
this.arrStr = arrStr;
}

public ArrayList<String> getArrStr() {return arrStr;}


}

Execute o arquivo pesquisa.xhtml e verifique se o comportamento desta


aplicação é igual ao das imagens abaixo:

O sistema irá apresentar


a tela da imagem (IM-15) no
browser do usuário que
requisitou a página
pesquisa.xhtml.

A cada seleção nos


componentes (IM-16, IM-18 e IM-
IM-15 20), o form é enviado para o
servidor, os métodos utilizados
na expressão de linguagem de
cada atributo são acessados e
executados, Notem que ao
acessar o método setArrStr o
servidor imprime o vetor de
String(tipo musical) que o
usuário selecionou conforme
imagens (IM-19 e IM-21)
IM-16 IM-17

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


16 Parte 6

IM-18 IM-19

IM-20 IM-21

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 17

EVENTOS DE SISTEMA
Os eventos de sistema são úteis para os programadores fazerem verificações,
ou até mesmo tomarem para si, em determinado momento o processo, isso ajuda a
tomar decisões antes que uma página seja renderizada, ou até mesmo quando sua
aplicação for inicializada ou finalizada pelo servidor.

Vejam as Classes de EVENTOS DE SISTEMA:


CLASSE DE EVENTO DESCRIÇÃO TIPO DE FONTE
PostConstructApplicationEvent O primeiro é disparado imediatamente após o Application
PreDestroyApplicationEvent início da aplicação e o segundo imediatamente
antes dela ser encerrada
PostAddToViewEvent O primeiro é disparado logo depois que o componete foi UIComponent
PreRemoveFromViewEvent adicionado a árvore de visualização e o segundo no
instante que ele está pra ser removido
PostRestoreStateEvent Disparado depois que o estado de um componete foi UIComponet
restaurado
PreValidateEvent Dispara respectivamente antes e após a validação de um UIComponent
PostValidateEvent componente

6
PreRenderViewEvent Disparado antes de a raiz da visualização ser renderizado UIComponent
PreRenderComponentEvent Disparado antes de o componente ser renderizado UIComponent
Disparados, respectivamente, depois que o componente UIViewRoot
PostConstructViewMapEvent raiz cria o mapa de escopo da visualização e quando o
PreDestroyViewMapEvent conteúdo deste mapa é removido

PostConstructCustomScopeEvent Disparados, respectivamente, depois da criação de um ScopeContext


PreDestroyCustomScopeEvent escopo customizado e antes de ele ser destruído

ExceptionQueuedEvent Disparados depois que uma exceção foi colocada na fila ExceptionQueuedEvent
-Context

Existem quatro maneiras de atribuir a uma classe, um evento de sistema:

1ª – Com a tag:

<f:event listener="#{managedBeans.metodo}" type="postValidate"/>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Eventos em JSFe</title>
</h:head>
<h:body>
<h:form>
<h2>Eventos de Sistema utilizando a tag f:event</h2>
<h:form>
<h:inputText value="#{monitoraEventosSistema.nome}" id="txtnome">
<f:event listener="#{monitoraEventosSistema.metodo}" type="postValidate"/>
</h:inputText>
<h:commandButton value="Enviar"></h:commandButton>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


18 Parte 6
crie o arquivo MonitoraEventosSistema.java conforme código abaixo:

package br.com.grandeporte.listern;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ComponentSystemEvent;

@ManagedBean
@RequestScoped
public class MonitoraEventosSistema {
private String nome;

public void metodo(ComponentSystemEvent event) throws AbortProcessingException{


UIComponent source = event.getComponent();
UIInput nomeInput = (UIInput) source.findComponent("txtnome");
nomeInput.setValue("nome horrivel");
}

public String getNome() {return nome;}

public void setNome(String nome) {this.nome = nome;}


}

A execução desta página ficaria assim:

IM-22 IM-23 IM-24

O sistema irá renderizar na tela do usuário a imagem(IM-22), não importa o nome que o usuário
digite(IM-23), após o sistema acessar o getters e setters ele irá executar o método apontado na tag:

<f:event listener="#{monitoraEventosSistema.metodo}" type="postValidate"/>

que mudará o valor do componente <h:inputText/> (IM-24)

Notem a assinatura do método +método(ComponentSystemEvent):void , então


sendo assim podemos mudar o atributo type da tag <f:event/> para outro tipos de
listener, veja quais tipos de classes e para que serve cada uma delas:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 19

VALOR DO ATRIBUTO Classe responsável pelo listener Quando executa


TYPE
Antes de criar o componente (caso tente
javax.faces.event.PreRenderComponent
preRenderComponent setar algo no componente dá erro pois
Event ele não foi construído ainda)
Após a criação do componente (executa
preRenderView
javax.faces.event.PreRenderViewEvent o método na primeira vez que a tela é
renderizada )
postAddToView Após o componente ser renderizado
javax.faces.event.PostAddToViewEvent pela primeira vez
preValidate Antes de acessar os métodos getters e
javax.faces.event.PreValidateEvent setters do componente
Após acessar os métodos getters e
postValidate javax.faces.event.PostValidateEvent setters do componente

Não importa qual nome que o usuário digite, o listener de fase sempre vai
atravessar o processo mudando o resultado antes de renderizar a página novamente
para o usuário!

6
Esta classe de nome MonitoraEventosSistema.java tem o método apontado na
tag:
<f:event listener="#{monitoraEventoSistema.metodo}"

que, captura os componentes do forme que enviou a requisição, com o método


findComponent(“ID CO COMPONENTE”) é possível capturar componentes do form
que fez a requisição, e com o método .setValue(“VALOR”) é possível adicionar valores
ao componente capturado. Importante ressaltar que, existem outros métodos que
podem ser executados tanto pelo componente capturado, quando os que o atributos
do objeto ComponentSystemEvent trás, para tanto é necessário que o desenvolvedor
se interesse pela documentação desta framework pois não está no escopo deste curso
tratarmos de todos esses métodos e parâmetros.

2ª – Com a tag:

@ListenerFor(SystemEventClass = PreRenderViewEvent.Class)

Este listener de sistema será abordado com mais detalhe no capítulo que fala
sobre criação de componentes.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


20 Parte 6

3ª – Por meio do arquivo de configuração faces-config.xml, para ilustrar este


tipo de listern vamos criar a seguinte aplicação:

Crie uma classe de nome OuvinteDeSystema.java no pacote


br.com.grandeporte.listern conforme código abaixo:

package br.com.grandeporte.listern;

import javax.faces.application.Application;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructApplicationEvent;
import javax.faces.event.PreDestroyApplicationEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;

public class OuvinteDeSystema implements SystemEventListener {


@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
//caso a fase for a de inicializar a construção da sua aplicação pelo servido ele executará
este método
if(event instanceof PostConstructApplicationEvent){
System.out.println("PostConstructApplicationEvent foi chamado!");
}
//caso a fase for a de destruição da sua aplicação pelo servido ele executará este método
if(event instanceof PreDestroyApplicationEvent){
System.out.println("PreDestroyApplicationEvent foi chamado!");
}
}
@Override
public boolean isListenerForSource(Object source) {
return (source instanceof Application);
}
}

Notem que esta classe está comparando a qual fase sua aplicação está no
momento, se foi construída no servidor (PostConstructApplicationEvent) ou se foi
destruída no servidor (PreDestroyApplicationEvent), ela apenas irá imprimir a situação
atual no console, mas poderia, mas você, programador java, poderia desenvolver
lógicas de negócios para sua aplicação, ou até mesmo estar configurando algo usando
este listener de sistema.

Inclua no seu arquivo faces-config.xml as seguintes tags:

<application>
<system-event-listener>
<system-event-listener-class>br.com.grandeporte.listern.OuvinteDeSystema</system-event-listener-class>
<system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
</system-event-listener>
</application>

Executando esta aplicação verificaremos que toda vez que o servidor for subir
nossa aplicação ele irá disparar o evento PostConstructApplicationEvent que nossa
classe OuvinteDeSystema capturará e executará o método específico conforme IM-25.

IM-25

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 21

4ª – Por meio da chamada do método subscribeToEvent da classe UIComponent ou


da Application, mas esse método é voltado para desenvolvedores de frameworks,
caso o aluno se interesse pode dar uma olhada na documentação da API JSF.

Vamos criar uma aplicação para vermos na prática o uso destes EVENTOS DE
SISTEMA:

Vamos codificar a seguinte classe de nome ExtratoBean.java no pacote


br.com.grandeporte.listern:

package br.com.grandeporte.listern;
import java.util.Date;import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;import javax.faces.event.ComponentSystemEvent;

@ManagedBean
@SessionScoped

6
public class ExtratoBean {
private Date dataInicial;
private Date dataFinal;
public void validaDatas(ComponentSystemEvent event) {

UIComponent source = event.getComponent(); //pega uma instancia dos componentes de sistema

//captura o componente de id data-inicial e converte para UIInput


UIInput dataInicialInput = (UIInput) source.findComponent("data-inicial");
UIInput dataFinalInput = (UIInput) source.findComponent("data-final");

if (dataInicialInput.isValid() && dataFinalInput.isValid()) {


Date dataInicialEscolhida = (Date) dataInicialInput.getLocalValue();
Date dataFinalEscolhida = (Date) dataFinalInput.getLocalValue();

if (dataFinalEscolhida.before(dataInicialEscolhida)) {
FacesMessage message = new FacesMessage("A data final não pode vir antes da
data inicial");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(source.getClientId(), message);
context.renderResponse();
}
}
} Agora vamos codificar o arquivo geraextrato.xhtml

public void geraExtrato() {


FacesMessage message = new FacesMessage("extrato gerado com sucesso");
message.setSeverity(FacesMessage.SEVERITY_INFO);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
}

//Getters e setters
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


22 Parte 6

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Gera Extrato</title>
</h:head>
<h:body>
<h2>Geração de extrato</h2>
<h:form>
<f:event type="postValidate" listener="#{extratoBean.validaDatas}" />
<h:messages/>

<h:outputLabel value="Data inicial: " for="data-inicial" />


<h:inputText value="#{extratoBean.dataInicial}" id="data-inicial"
required="true" requiredMessage = "DATA INICIAL É OBRIGATÓRIA">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
<h:outputLabel value="Data final: " for="data-final" />
<h:inputText value="#{extratoBean.dataFinal}" id="data-final" required="true">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:inputText>
Executando o arquivo geraextrato.xhtml ele deverá apresentar a seguinte saída:
<h:commandButton value="Ver extrato" action="#{extratoBean.geraExtrato}" />
</h:form>
</h:body>
</html> A aplicação irá fornecer a tela representada pela imagem(IM-26)

-Caso o usuário digite a data final posterior a data final


conforme imagem(IM-27), o sistema irá setar a mensagem Extrato
gerado com sucesso(IM-28), lembrando que quem setou esta
mensagem foi o método validaDatas da classe ExtratoBean que foi
apontada com a tag <f:event/> do arquivo geraextrato.xhtml.

-Caso o usuário coloque uma data final anterior à data inicial


(IM-29) o sistema irá setar a mensagem da (IM-30).
IM-26

IM-27 IM-28 IM-29 IM-30

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 23

-Caso o usuário digite datas fora do padrão estipulado na tag


<f:convertDateTime pattern="dd/MM/yyyy" />(IM-31) o sistema irá setar a mensagem
padrão da framework (IM-32).

IM-31 IM-32

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


24 Parte 6
EVENTOS DE FASE (Phase Events)
As aplicação JSF disparam eventos, chamados de EVENTOS DE FASE, esta fase se
refere ao ciclo de vida de cada página confeccionado por você programador java, para isto, se
tiver qualquer dúvida sobre as 6 (seis) fases passadas no início do capítulo que fala sobre a
framework JSF é hora de revisá-las para que você consiga entender os conceito que serão
passados agora.

Para capturar este evento gerado pelas suas páginas JSF é necessário configurar o
arquivo faces-config conforme mencionado abaixo ou acrescentar nas páginas que se deseja
ouvir os eventos de fase com a tag:

<f:phaseListener type="br.com.grandeporte.listern.MonitoraFaseListern"></f:phaseListener>

tudo dependendo do que você, programador java pretende, com este listener :

- configurando o arquivo faces-config.xml:

<lifecycle>
<phase-listener>br.com.grandeporte.listern.MonitoraFaseListern</phase-listener>
</lifecycle>

Crie a seguite classe para monitorar os eventos de suas páginas .xhtml

package br.com.grandeporte.listern;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

public class MonitoraFaseListern implements PhaseListener {

@Override
public void afterPhase(PhaseEvent e) {
System.out.println("MonitoraFaseListern.afterPhase()");
System.out.println(e.getPhaseId());
}

@Override
public void beforePhase(PhaseEvent e) {
System.out.println("MonitoraFaseListern.beforePhase()");
System.out.println(e.getPhaseId());
}

@Override
public PhaseId getPhaseId() {
System.out.println(PhaseId.ANY_PHASE);
return PhaseId.ANY_PHASE ;
}
}

Esta classe reescreveu 3 (três) métodos da interface PhaseListener, o método:

- getPhaseId():PhaseId - Informa a aplicação quando passar os eventos de fase ao


listener, Se por acaso quisermos apenas capturar a fase APPLY_REQUEST_VALUES
trocaríamos o tipo de retono para: return PhaseId.APPLY_REQUEST_VALUES; então
ele só iria ‘escutar’ esta fase do ciclo de vida da aplicação JSF;

- afterPhase(PhaseEvent e) – Este método executa no início da fase informado pelo


método getPhaseId():PhaseId;

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 25

- beforePhase (PhaseEvent e) – Este método executa após a fase informado pelo


método getPhaseId():PhaseId;

A partir de agora, toda página que for requisitada pelos usuários executarão o
listener de fase que você acabou de criar, claro que se você optou em usar a tag
f:phaseListener, a classe acima só executará quando está página for requisitada.

Vamos codificar e executar a página acaoBTO.xhtml criado no início deste


capitulo (optando pela configuração do arquivo faces-config.xml):

A aplicação apresentará uma tela com um botão para o usuário clicar conforme
abaixo

Assim que o usuário clicar ele executará uma método de um managedBean


que mudará o texto do botão:

E como toda página agora tem um listener ouvindo todas as fases, e como
6
codificamos ele exibirá no console os textos abaixo, notem que ele imprime todas as
fases conforme explicados anteriormente.

Este tipo de EVENTO era bastante útil antes da


versão 2.0 para criar componentes customizados
dotados de conhecimento das fases do ciclo de vida da
aplicação JSF, suponho que estes tipos de eventos
criados pelas fases do ciclo de vida de suas páginas não
sejam mais úteis do que os eventos de Sistema
explicados anteriormente.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


26 Parte 6

Teoria AJAX em jsf

O suporte ao ajax está embutido no JSF 2.0, que contam com uma biblioteca
em javaScript. Essa biblioteca pode ser acessível tanto na página quanto através de
código java. Nas páginas JSF, a forma de utilizar AJAX é usando as tags de apoio
f:ajax, os atributos desta tags são:

ATRIBUTOS DESCRIÇÃO

Disable default é false, mas se true ele diabilita a tag

Event O evento dispara a requisição ajax, este evento pode ser tanto do
javaScript sem o prefixo on, exemplo = “blur” = onbluor, mas também
pode ser nomes de eventos de componentes, ex: action, valueChange
ou actionListener que são eventos de botões e links

Execute Este atributo se refere a qual componentes irá sofrer a requisição ajax,
os id deste devem ser separados por vírgula ou pode ser antecedidos
de @ nos casos (@this, @form, @all, @nome).

Immediate Default é false, mas se atribuído o valor true, a aplicação o processará


logo no início do seu ciclo de vida.

Onerror Indica uma função que será executada caso ocorra algum erro ao
processar sua página.

Onevent Neste atributo você poderá indicar uma função do javaScript que sua
aplicação executará quando processar a chamada ajax de sua página,
esta chamada ajax produz três(3) fases, BEGIN – início, COMPLETE-
Final, e SUCCESS-momento da renderização da página.

Listener Sua aplicação invoca o método processAjaxBehavior deste listener


uma vez a cada chamada do ajax na fase chamada da aplicação.

Render Deve-se indicar neste atributo os componentes que devem sofrer


alteração quando a requisição ajax for feita, este atributo pode receber
diversos ids de componentes separados por vírgula, ou ainda pode
receber as palavras chaves (@this, @form, @all, @nome), default
deste atributo é @nome.

Conceitualmente uma chamada AJAX se diferencia das HTTP normais em dois


aspectos apenas:

1º - O AJAX processa parcialmente o formulário no servidor quando é chamado.

2º - O AJAX gera parcialmente no cliente após ser gerada pelo servidor.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 27

Um exemplo básico do uso do AJAX em JSF:

Crie uma classe java de nome BeanAjax.java

package br.com.grandeporte;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class BeanAjax {
private String nome;
public BeanAjax() {}

public String getNome() {return nome;}

public void setNome(String nome) {this.nome = nome;}


}

6
Cria uma página mxml de nome eco.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"
/>
<title>Insert title here</title>
</h:head>

<h:body>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="Texto digitado: "></h:outputLabel>
<h:inputText id="texto1" value="#{beanAjax.nome}">
<f:ajax event="keyup" render="apoio"/>
</h:inputText>
<h:outputLabel value="ECO do texto digitado: "></h:outputLabel>
<h:inputText id="apoio" value="#{beanAjax.nome}"></h:inputText>
</h:panelGrid>
</h:form>
</h:body>
</html>

Ao executar esta aplicação nota-se o uso do ajax, a cada letra digitada no


componente <h:inputText id="texto1" uma requisição ajax é enviada ao servidor pelo
método event="keyup" referenciada no atributo da tag <f:ajax e quando a página é
renderizada no browser do usuário o único componente que é atualizado é o
componente <h:inputText id="apoio discriminado no atributo render="apoio" desta tag
f:ajax.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


28 Parte 6
Este exemplo apresentado de início é algo bem simples relacionado com as
suas diversas funcionalidades, vamos ver um exemplo um pouco mais complexo,
atualize sua classe BeanAjax.java

package br.com.grandeporte;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

@ManagedBean
@SessionScoped
public class BeanAjax {
private String nome;

private int idade;

public BeanAjax() {}

public void validaNome(FacesContext fc, UIComponent c, Object value) {


for (int i = 0; i <= 10; i++) {
if (((String) value).contains(i + ""))
throw new ValidatorException(new FacesMessage(
"Nome nao pode conter numeros"));
}
}

public String getNome() {return nome;}

public void setNome(String nome) {this.nome = nome;}

public int getIdade() { return idade;}

public void setIdade(int idade) {this.idade = idade;}

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Aprendendo Ajax</title>
</h:head>

<h:body>
<h1>AJAX. Exemplo 02...</h1>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="Entre com seu nome: "></h:outputLabel>
<h:inputText id="txtNome" value="#{beanAjax.nome}" validator="#{beanAjax.validaNome}">
</h:inputText>
<h:message id="msgerronome" for="txtNome" style="color: green"></h:message>

<h:outputLabel value="Entre com sua idade: "></h:outputLabel>


<h:inputText id="txtIdade" value="#{beanAjax.idade}"></h:inputText>
<h:message id="msgerroidade" for="txtIdade" style="color: blue"></h:message>

<f:ajax event="keyup" execute="txtNome txtIdade" render="msgerroidade gerronome" />


</h:panelGrid>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 29

O resultado da execução desta aplicação


é uma página para que o usuário digite seu nome
e sua idade conforme imagem ao lado.

A aplicação está fazendo


requisição AJAX a cada tecla digitada,
esta requisição está executando os
campos de entrada de texto txtNome e
txtIdade, e renderizando os campos de
<h:message... que irá exibir a
mensagem conforme as imagens ao
lado e abaixo.

Então, para se fazer uma requisição AJAX usando as tags da framework JSF é
necessário ter em mente 3 conceitos:

- Associar um componete ajax a um componete que gere um evento;

- Informar a esta tag ajax quais os componentes que irão ser validado no
servidor;

- Informar a tag ajax qual o(s) componente(s) que irão ser renderizados no
browser do cliente após requisição ajax.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


30 Parte 6
Sendo assim também podemos utilizar as tags ajax da seguinte forma:
Vamos alterar o arquivo validação.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Aprendendo Ajax</title>
</h:head>
<h:body>
<h1>AJAX. Exemplo 02...</h1>
<h:form>
<h:panelGrid columns="3">

<f:ajax event="keyup" execute="txtNome txtIdade" render="msgerroidade gerronome"/>

<h:outputLabel value="Entre com seu nome: "/>


<h:inputText id="txtNome" value="#{beanAjax.nome}" validator="#{beanAjax.validaNome}"/>
<h:message id="msgerronome" for="txtNome" style="color: green"/>

<h:outputLabel value="Entre com sua idade: "></h:outputLabel>


<h:inputText id="txtIdade" value="#{beanAjax.idade}"/>
<h:message id="msgerroidade" for="txtIdade" style="color: blue"/>
</f:ajax>

</h:panelGrid>
</h:form>
</h:body>
</html>

O suporte a ajax oferecido pela framework JSF é de baixo nível pois abstrai
toda a complexibilidade do usuário desta framework quando utiliza requisições deste
tipo, vamos nos aprofundar mais sobre requisição ajax, quais situações o programador
pode encontra necessitar fazer uma requisição ajax? Para responder esta pergunta é
só começar a desenvolver uma página onde o há a necessidade de atualizar parte de
sua página e não toda ela, ou melhor ainda, executar validações de campos de
entrada, antes mesmo que o usuário envie o form utilizado. Vamos alterar mais uma
vez o arquivo para lhe mostrar, que o exemplo acima está didaticamente muito bom,
mas podemos reduzir o número de requisições utilizando o método "blur" conforme
abaixo:

<f:ajax event="blur" execute="txtNome txtIdade" render="msgerroidade gerronome"></f:ajax>

Como visto anteriormente a tag <f:ajax tem o atributo onevent="" que pode
executar uma função javaScript indicada dentro das aspas duplas, sabemos que este
método executará 3 (três) vezes conforme tabela passada no início deste capítulo (nó
inicio da requisição AJAX, após a renderização da página .xhtml e após a última etapa
do ciclo de vida da sua página);
Para manipular erros na requisição ajax, caso ele ocorra, você, programador
java pode fazer o uso do método onerror="" apontando para um método javascript
para tratamento deste.

Na documentação JSF há uma ampla documentação sobre javascript que não


é o escopo deste curso, o aluno que se interessar pode estar consultando tal
documento.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 31

Como visto programador JAVA, existe várias formas de se utilizar este suporte
a AJAX em sua aplicação JSF, se aprofunde mais fazendo os exercícios extras para
realmente entender os conceitos.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


32 Parte 6

Validadores e
Teoria conversores em jsf
Como visto nos exemplos passados até agora, em nenhum momento nos
preocupamos em validar ou converter dados fornecidos pelo usuário em nossas
páginas .xhtml, mas isso porque didaticamente não foi necessário, porém nos seus
projetos, você programador java, irá validar campos de entrada e converter valores de
String(valores doscampos de entrada) para tipos DATE, int, char, etc.

A framework JSF nos facilita no desenvolvimento nos fornece várias tags para
validação e conversão, estas tags são enviadas junto com o formulário ao servidor, e,
dentro dos 6(seis) ciclos que nossa aplicação percorre, exatamente na fase
ATUALIZAÇÃO DO MODELO nossa framework irá checar todas as validações do
campos, caso ocorra algum erro, ela vai pra última fase (renderizar respota) e antes de
exibir a página novamente ao usuário com os dados enviados preenchido nos campos
respectivos, a framework irá setar mensagens para que possa ser exibida para o
usuário(ver capítulo sobre mensagens).

Isto tudo tem um objetivo bem claro, não deixar que dados inconsistentes
cheguem a regra de negócio de nossa aplicação, além desta facilidade de validar
campos usando os validaores padrões, você programador java, não tem o trabalho de
tratar a página para ser enviada pro usuário, pois a framework faz isto para você.

CONVERSORES:

Vamos desenvolver um exemplo básico de conversão para entendermos


melhor seus como funciona um conversor em JSF.

Crie um novo projeto DINAMIC WEB PROJECT de nome – validação_conversao

Crie um arquivo xhtml de nome validação_conversão.xhtml.

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Conversão e validação</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel value="converter para números: "></h:outputLabel>
<h:inputText id="txtnum" >
<f:convertNumber type="number" />
</h:inputText>
<h:message for="txtnum" style="color:blue" />
<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 33

Execute esta aplicação e verifique se a saída é igual a apresentada na imagem


abaixo:

A aplicação irá apresentar no browser do


usuário IM-1, se o usuário digitar apenas números
conforme IM-2 e submeter este form, a framework,
irá converter esta String que chegará no servidor em
números conforme IM-3.
IM-1

6
IM-2 IM-3

Caso o usuário coloque letras após os


números conforme IM-4, ou ainda se ele colocar
letras no meio dos números, a framework irá
considerar os números até achar alguma letra, então
ele irá desprezar o que estiver depois da primeira
IM-4 letra achada conforme IM-5

IM-5

Caso o usuário coloque letras no início do


campo conforme IM-6 a framework setará um erro na
sessão que poderá ser apresentado ao usuário
utilizando da tag <h:message conforme IM-7.

IM-6

IM-7

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


34 Parte 6
Agora que já tivemos um primeiro contato com um conversor em JSF, vamos
verificar os atributos desta tag. <f:convertNumber/>

Atributos Tipo Valor


type String Number(default), currency ou percent.

pattern String Padrão de formatação usando pattern.

maxFractionDigits int Número máximo de dígitos na parte fracionária.

minFractionDigits int Número mínimo de dígitos na parte fracionária.

maxIntegerDigits int Número máximo de dígitos na parte inteira.

minIntegerDigits int Número mínimo de dígitos na parte inteira.

integerOnly boolean true, apenas a parte inteira é analisada sintáticamente(default - false).


groupingUsed boolean Usado para separadores de grupos, o default é true.
locale String ou Localidade para serem usadas para análise sintática ou formatação
java.util.Locale
currencyCode String Código ISO 4217 de moeda, tais como USD ou EUR
currencySymbol String Esta String é passada para o método da classe
DecimalFormat.setDecimalFormatSymbols sobrepondo o símbolo da
lacalidade atual

Faça os testes com estes atributos e veja o comportamento de cada um deles.

Outra tag muito útil de conversão é a tag <f:convertDateTime /> para converter
o texto digitado em datas, crie o arquivo convetdata.xhtml conforme código abaixo:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Conversão e validação</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="3">

<h:outputLabel value="converter para Data:"/>


<h:inputText id="txtdt">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:inputText>
<h:message for="txtdt" style="color:blue" />

<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 35

Execute esta aplicação e verifique se a saída do texto é igual as imagens


apresentadas a seguir:

IM-8 IM-9

Caso o usuário digite datas conforme padrão estipulado no atributo


pattern(dd/MM/yyyy) o validador irá executar no ciclo de vida de sua aplicação sem
erro algum conforme IM-8 e 9

6
IM-10 IM-11

Caso o usuário digite datas omitindo números no caso da IM-10 em vez de


‘2013’ colocou ‘13’ o validador irá acrescentar zeros(0) para completar o padrão
conforme IM-11.

Caso o Usuário digite separadores que


não seja ‘/’ ou letras em vez de números
conforme IM-12, ao validar este valor a
framework irá setar uma mensagem de erro
padrão na sessão conforme IM-14.

IM-12

IM-14

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


36 Parte 6
atributos da tag. <f:convertDateTime />:

Atributos Tipo Valor


type String Date(default), time ou ambos.

pattern String Padrão de formatação usando pattern.

dateStyle String Default, short, médium, long ou full.

timeStyle String Default, short, médium, long ou full.

locale String ou Localidade para serem usadas para análise sintática ou formatação
java.util.Locale
timeZone Java.util.TimeZone Região de fuso usado para análise sintática ea formatação, default(GMT),
apartir do JSF 2.0 é possível alterar para localidade padrão o default da
máquina do usuário, para isto temos que atribuir o valor TRUE a
javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIM
EZONE, no arquivo web.xml.

Faça os testes com estes atributos para quando for necessário usar, você,
programador java, não fique reescrevendo código, pois a solução já está pronta para
você usar!

Para outras conversão existe a tag <f:converter /> , esta tag tem o atributo
converterId que recebe como parâmetro nomes relativos de classes conversoras, veja
o exemplo a seguir:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Conversão e validação</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="3">

<h:outputLabel value="converter para Data usando


f:convertDateTime:"/>
<h:inputText id="txtdt">
<f:convertDateTime/>
</h:inputText>
<h:message for="txtdt" style="color:blue" />

<h:outputLabel value="converter para Data usando converter


converterId=javax.faces.DateTime:"/>
<h:inputText id="txtdt2">
<f:converter converterId="javax.faces.DateTime"/>
</h:inputText>
<h:message for="txtdt2" style="color:blue" />

<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid> </h:form> </h:body></html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 37

Execute esta página e verifique se o comportamento dela se parece com o das


imagens abaixo:

IM-15 IM-16

A validação destes campos são


idênticos, os dois validam baseados na
classe javax.faces.DateTime, porém um está
usando a tag <f:convertDateTime/> e a outra
a tag <f:converter/>.

IM-17
visualize as imagens IM-15/16/17.
6
A IM-18 mostram o mesmo senário
para converter entradas erradas, notem que o
resultado na IM-19 e notem que a mensagem
de erro são idênticas.

IM-18

IM-19

Em JSF temos várias classes conversoras que podem ser usadas:

javax.faces.Boolean javax.faces.Byte javax.faces.Double


javax.faces.Short javax.faces.Float javax.faces.Long
javax.faces.Integer javax.faces.Character javax.faces.BigDecimal
javax.faces.BigInteger javax.faces.Boolean javax.faces.Boolean
javax.faces.Boolean

Todas essas convertem para essas classes Wrappers e seus tipos primitivos
correspondentes.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


38 Parte 6
VALIDADORES

Até agora, didaticamente nós, desenvolvedores java, não validamos nenhum


campo de entrada de dados, mas como dito, didaticamente não foi necessário, mas
saibam que por diversas vezes vocês terão que validar campos de entrada fornecidas
pelo usuário de sua aplicação para que esses dados inconsistente não cheguem a
regra de negócio de sua aplicação. Assim como fizemos com os CONVERSORES,
vamos ver que a framework JSF trás tags para facilitar o desenvolvimento de suas
páginas .xhtml, vamos ver este primeiro exemplo de validação:

Crie um arquivo .xhtml de nome validadores.xhtml

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Conversão e validação</title>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
<h:outputStylesheet library="css" name="styles.css" />
<h:form>
<h:panelGrid columns="3">

<h:outputLabel value="validando tamanho mínimo e máximo do texto:"/>


<h:inputText id="txtdt" >
<f:validateLength minimum="3" maximum="8"/>
</h:inputText>
<h:message for="txtdt" style="color:blue" />

<h:commandButton value="Submeter"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>

Execute o arquivo validadores.xhtml e verifique se o resultado é igual ao das


imagens abaixo:

Esta validação se resume em restringir


o tamanho mínimo de letras (3) e tamanho
IM-20 máximo de letras(8), caso o usuário digite uma
palavra dentro deste range a aplicação
executará sem nenhum problema conforme
IM-20 e IM-22.

IM-21

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 39
Caso o usuário digite uma palavra com
menos de 3(três) letras IM-22, e submeter
este form a framework irá, dentro do ciclo da
aplicação, verificar que o campo digitado não
tem o padrão passado, então ele irá setar uma
IM-22 mensagem padrão na sessão e retornará a
página com os campos preenchidos com as
informações que o usuário inseriu para que
ele tenha a oportunidade de arrumar o que
está fora dos padrões de validação estipulado
por você programador java conforme IM-24.

IM-24 Caso o usuário digite uma palavra com

6
mais de 8 (oito) letras IM-25, e submeter este
form a framework irá, dentro do ciclo da
aplicação, verificar que o campo digitado não
tem o padrão passado, então ele irá setar
uma mensagem padrão na sessão e retornará
a página com os campos preenchidos com as
informações que o usuário inseriu para que
ele tenha a oportunidade de arrumar o que
IM-25 está fora dos padrões de validação estipulado
por você programador java conforme IM-26.

IM-26

Vamos conhecer as tags padrão JSF para validações de campos:

Tag JSF Classe do validador Atributos Valores validados


f:validateDoubleRange DoubleRangeValidator - minimum. double
- maximum.
f:validateLongRange LongRangeValidator - minimum. long
- maximum.
f:validateLenth LengthValidator - minimum. String
- maximum.
f:validateRequired RequiredValidator Tem que haver algum valor .
(add. JSF2.0)
f:validateRegex RegexValidator - pattern String em comparação a um
valor regular. (add. JSF2.0)
f:validateBean BeanValidator - validation- Grupos de validadores de
Groups beans(ver especificação JSR
303)

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


40 Parte 6
Conversores customizados

Até agora usamos as tags para fazer nossas validações, mas há momentos
que temos que validarmos campos ou objetos em nossa aplicação e que a framework
não nos dá suporte, um exemplo clássico é a validação de documentos em um
formulário de cadastro, em específico vamos pegar o cpf, sabemos que ele deve
conter 11 dígitos sendo números e que seus dois últimos números são dígitos
conferidor, ou seja, existe uma equação que se faz com os 9(nove) primeiros dígitos o
resultado é os dígitos conferidores. O alvo aqui não é que vocês discutem a lógica por
trás desta equação, mas sim, que vocês compreendam que é possível criar
conversores e validadores personalizados. Vamos primeiramente entender a interface
Converter que é a que devemos implementar para criarmos conversores customizados,
após entendermos como funciona a lógica por trás de conversores, vamos criar
validadores customizados e entender a lógica por trás da interface Validator.

A ordem que serão explicadas essas interfaces é a ordem que a framework


processa-os, primeiro a framework converte a entrada do usuário e depois valida.

Quando eu falo em entrada de dados pelo usuário, temos que entender que
tudo o que o usuário digita dentro de um form é reconhecido como String quando este
form é enviado ao servidor, aí que entra a conversão de dados, resumidamente a
framework terá que converter estas Strings em tipos de dados específico, por exemplo,
se você, programador java criar um atributo do tipo int, e atribuir a este valor os dados
digitados pelo usuário em um campo

<h:inputText id="idade" value="#{usuario.idade}"/>

a framework irá acessar o método setIdade passando um valor do tipo int, isso não
acontece por mágica, a framework irá converter a String digitada pelo usuário para o
tipo int antes de passar o parâmetro para o método, mas eu pergunto a vocês, se o
usuário digitar uma letra em vez de números? Ou se o usuário digitar um número
negativo? Ou um número estrambólico do tipo 1235? Você poderá delimitar tudo isto
usando tags da framework em TODAS as páginas que utilizarem este campo de
entrada para popular este atributo idade. É justamente nestas situações que podemos
utilizar conversores personalizados, veja o exemplo a seguir:

Crie os arquivos .xhtml de nome convertvalida.xhtml e result.xhtml conforme


IM-27 e IM-28.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 41

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" IM-27
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>#{msgs.titulo}</title>
</h:head>
<h:body>
<h:form>
<h1>#{msgs.cabecalho}</h1>
<h:panelGrid columns="3">
#{msgs.nome}
<h:inputText id="nome" value="#{usuario.nome}" rendered="true">
</h:inputText>
<h:message for="nome"/>

#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}">
</h:inputText>
<h:message for="cpf" showDetail="true" showSummary="true" styleClass="errorMessage"/>
</h:panelGrid>

6
<h:commandButton value="#{msgs.bto}" action="result"/>
</h:form>
</h:body>
</html>

<?xml version="1.0" encoding="UTF-8"?> IM-28


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>#{msgs.titulo}</title>
</h:head>
<h:body>
<h:form>
<h1>#{msgs.cabecalho}</h1>
<h:panelGrid columns="3">
#{msgs.nome}
<h:inputText id="nome" value="#{usuario.nome}" rendered="true"/>
<h:message for="nome"/>

#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}"/>
<h:message for="cpf" showDetail="true" showSummary="true"/>
</h:panelGrid>
<h:commandButton value="#{msgs.bto}" action="result"/>
</h:form> </h:body> </html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


42 Parte 6
Crie o arquivo mensagem.properties dento do pacote mensagens na raiz da
aplicação onde fica os códigos java conforme IM-30 abaixo:

cpfvalido = CPF VALIDO!


titulo = Cadastra CPF" IM-30
nome = Nome:
cpf=CPF:
digcpf= Dig:
bto= Validar
cabecalho= Validação de CPF
numcpfinvalido ={0} - Numero do CPF incorreto, verifique!

IM-29

Acrescente ao arquivo faces-config.xml que se encontra na pasta


/WebContent/WEB_INF o código abaixo da IM-31 para que sua aplicação consiga
através da expressão de linguagens capturar o valor do arquivo arquivo
‘mensagem.properties’ que você acabou de criar.

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
IM-31
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_1.xsd"
version="2.1">

<application>
<message-bundle>mensagens.mensagens</message-bundle>
<resource-bundle>
<base-name>mensagens.mensagens</base-name>
<var>msgs</var>
</resource-bundle>
</application>

</faces-config>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 43

Crie também um bean de nome Cpf.java conforme IM-32

package br.com.bean;

import java.io.Serializable; IM-32


public class Cpf implements Serializable {
private String cpf;

public Cpf(String cpf) {


this.cpf = cpf;
}
public Cpf() {
}

@Override
public String toString() {
// TODO Auto-generated method stub
return cpf + "";
}
}

Crie o arquivo Usuario.java conforme IM-33: 6


package br.com.managedbeans;

import javax.faces.bean.ManagedBean; IM-33


import javax.faces.bean.RequestScoped;
import br.com.bean.Cpf;

@ManagedBean
@RequestScoped
public class Usuario {

private String nome;


private Cpf cpf;

public Usuario() {
this.nome = "";
this.cpf = new Cpf("");
}
public String getNome() {return nome;}
public void setNome(String nome) {this.nome = nome;}
public Cpf getCpf() {return cpf;}
public void setCpf(Cpf cpf) {this.cpf = cpf;}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


44 Parte 6
Crie o conversor personalizado de nome ConversorCpf.java conforme IM-34:

package br.com.conversor;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent; IM-34
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter; Anotação
import br.com.bean.Cpf;
@FacesConverter(forClass=br.com.bean.Cpf.class)
@FacesConverter(forClass=br.com.bean.Cpf.class) aponta para a classe a qual irá realizar a conversão,
todo objeto instanciado deste tipo será convertido
public class ConversorCpf implements Converter{ usando este conversor.
private boolean validaOk = true;
private String msgErro="";
Para se criar um conversor temos que implementar a interface Converter,
sendo assim temos que reescrever os métodos getAsObject – Transforma a
String em um Objeto e o método getAsString que transforma Objeto em
String.
public ConversorCpf() {
@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String valor) throws ConverterException {
// método que transforma a String digitada pelo usuário em um objeto do tipo Cpf
String cpf = new String(valor);
if(cpf.length() >10 && cpf.length() <12){
try {
long cpfInt =Long.parseLong(cpf);
validaOk = true;
} catch (Exception e) {
validaOk = false;
msgErro = "CPF só pode conter números";
}
}else{
validaOk = false;
msgErro = "CPF só pode conter 11 números";
}

if(!validaOk){
FacesMessage message = new FacesMessage(msgErro, "erro2");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message);
}else return new Cpf(cpf.toString());
}

@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object valor) {
// Método que pega o objeto Cpf e o transforma para String
return valor.toString();
}
}

Execute esta aplicação e verifique se a saída foi igual a imagem IM-37.

IM-35 IM-36 IM-37

Se o usuário digitar um cpf que não fuja das regras de conversão que
definimos, ver IM-34, ele irá apresentar a saída igual a da IM-37

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 45

IM-38 IM-39 IM-40

Se o usuário digitar um cpf que não tenha 11(onze) números conforme IM-38 e
IM-39, o sistema não conseguirá converter essa entrada para um objeto do tipo
Cpf.java, e ainda irá setar uma mensagem de erro que poderá ser exibida em uma tag
<h:message/> conforme IM-40.

6
IM-41 IM-42

Se o usuário digitar 11(onze) dígitos, porém por descuido digitar alguma letra
no meio da informação IM-41, ao converter o nosso conversor irá notar o erro e irá
setar a mensagem de erro conforme IM-42.

Pelo que vimos no exemplo sobre conversão, o que vocês, que já sabem fazer
conversões usando as tags JSF e através da interface Converter. Analise qual é a
maneira mais adequada para a sua aplicação, como dica eu sugiro que, se o objeto a
ser Convertido, seja utilizado em mais de uma tela do seu sistema, então vale a pena
utilizar a interface, mas se a conversão for apenas em uma tela, então use o conversor
fornecido pela framework JSF através das tags já vistas anteriormente.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


46 Parte 6
Validadores customizados
Agora que vimos como customizar nossos conversores, no caso do exemplo
acima o objeto Cpf.java, passamos para a segunda etapa que é criar validadores
customizados, como sabemos, existem validadores que a framework fornece, mas
nem sempre satisfazem nossa necessidade, no exemplo criado anteriormente,
convertemos as Strings passadas pelo envio do form em objetos do tipo Cpf.java, se o
usuário digitar 11(onze) números ele atenderá a exigência codificada na classe
ConversorCpf.java, mas isto não garante que o cpf passado seja válido, e como
podemos fazer isto então, já que a framework não nos trás algo desse tipo para
validação, a saída é criar um validador customizados de Cpf, as regras de como se
valida um cpf pode ser encontrada facilmente na internet, eu utilizei esta fonte para
criar o validador que desenvolveremos a seguir:

http://www.gerardocumentos.com.br/?pg=entenda-a-formula-do-cpf .

Assim como o Conversor, para criar um Validador temos que criar uma classe
que implemente uma interface, no caso a interface Validator, neste caso temos que
reescrever o método validate que será executada toda vez que instanciarem um objeto
do tipo alvo desta validação. Vamos acrescentar ao projeto anterior um arquivo de
nome ValidadorCpf.java dentro do pacote Bbr.com.validadoresconforme IM-43.

package br.com.validadores;

import javax.faces.application.FacesMessage;
IM-43
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

@FacesValidator("br.com.bean.Cpf")
public class ValidadorCpf implements Validator{
private boolean vallidaOk = true;

public ValidadorCpf() {}

@Override
public void validate(FacesContext arg0, UIComponent arg1, Object valor)
throws ValidatorException {
String cpf = valor.toString();
if(cpf.length() >10 && cpf.length() <12){
validaCPF(cpf.substring(0, 9));
if(vallidaOk){
validaDigCpf(cpf.substring(9, 11), cpf.substring(0, 9));
}
}else{
vallidaOk = false;
}
if(!vallidaOk){
//poderia criar mensagem em tempo de execução para serem apresentadas para o usuário
FacesMessage msgErro = new FacesMessage("Msg sumario", "msg detalhe");
msgErro.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msgErro);
}
}

public void validaCPF(String _cpf){


if (!(_cpf.trim().matches("[0-9]{1,9}"))) {//tratar os caso tenha menor que 9
numeros, criar mensagem a respeito ou outra lógica que você programador java queira
implementar
vallidaOk = false;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 47

public void validaDigCpf(String _dig_cpf, String _cpf){


long soma1 = 0, soma2 = 0, vlr = 11, resto, digito1, digito2;
IM-43
long digitoCPFGerado = 0;
if ((!(_dig_cpf).trim().matches("[0-9]{1,2}")) && (vallidaOk == true)) {

}else{
for (int i = 0; i < 9; i++) {
soma1 += (Long.parseLong(_cpf.trim().substring(i, i + 1)) * (vlr - 1));
soma2 += Long.parseLong(_cpf.trim().substring(i, i + 1)) * vlr;
vlr--;
}
resto = (soma1 % 11);
if (resto > 1) {
digito1 = (11 - resto);
} else {
digito1 = 0;
}
soma2 += (digito1 * 2);
resto = (soma2 % 11);
if (resto > 1) {
digito2 = (11 - resto);
} else {

6
digito2 = 0;
}
digitoCPFGerado = (digito1 * 10) + digito2;
if(digitoCPFGerado == Long.parseLong(_dig_cpf)){
this.vallidaOk = true;
}else{
this.vallidaOk = false;
}
}
}
}

Inclua no arquivo convertvalida.xhtml as seguintes linhas de código conforme


IM-44.

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" IM-44
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>#{msgs.titulo}</title>
</h:head>
<h:body>
<h:form>
<h1>#{msgs.cabecalho}</h1>
<h:panelGrid columns="3">
#{msgs.nome}
<h:inputText id="nome" value="#{usuario.nome}" rendered="true"/>
<h:message for="nome"/>

#{msgs.cpf}
<h:inputText id="cpf" value="#{usuario.cpf}">

<f:validator validatorId="br.com.bean.Cpf"/>
</h:inputText>

<h:message for="cpf" showDetail="true" showSummary="true"/>


</h:panelGrid>
<h:commandButton value="#{msgs.bto}" action="result"/>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


48 Parte 6
Execute novamente sua aplicação, agora vamos inserir cpfs válido e inválidos
para testar se esta classe validadora está funcionando corretamente conforme IM-45 e
IM-46.

IM-45 IM-46

Caso o usuário digite os dados de um cpf válido(IM-45), o sistema executa


normalmente apresentado os dado conforme IM-46

IM-47 IM-48

Caso o usuário digite os dados de um cpf inválido(IM-47), o sistema executa


a conversão, e depois a validação, o método validate irá ser executado, e
constatará que este dígito conferidor está errado, então o código setará uma
mensagem e forçará um erro de validação para ser apresentada ao usuário(IM-48),
desta forma esses dados não acessarão a lógica de negócio da aplicação.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 49

Componentes personalizados
Teoria em jsf

Este tópico será destinado a criação de componentes personalizados utilizando


tags JSF, o intuito de se criar componentes personalizados é acima de tudo,
reaproveitamento de código, baixa manutenção.

Já vimos como criar templates, inserir pedaços de código dentro de nossas


páginas .xhtml, então essas tags customizadas segue esta idéia, suas tags serão
inseridas como pedaços de código dentro de outras páginas xhtml.

Existem 2(duas) maneiras de criar componentes personalizados:

6
1ª – Pode-se criar uma página JSF utilizando as tags <composite:interface/> e
<composite:implementation/> conforme código abaixo:

Crie um novo Dynamic Web Project de nome


JSF_COMPONENTES_PERSONALIZADOS, não esquecendo de selecionar o atributo
da Framework JSF.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


50 Parte 6
Crie a classe Usuario.java dentro do pacote
br.com.grandeporte.managedbeans conforme código Abaixo:

package br.com.managedbeans;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean
@SessionScoped
public class Usuario {
private String login;
private String senha;

public Usuario() {}

public String logar(){


return "dados";
}

public String getLogin() {


return login;
}

public void setLogin(String login) {


this.login = login;
}

public String getSenha() {


return senha;
}

public void setSenha(String senha) {


this.senha = senha;
}
}

Crie um pacote dentro do pacote resource que está na raiz do pacote


WebContent de nome mycomp.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 51

Crie um arquivo .xhtml de nome login.xhtml dentro do pacote mycomp


conforme imagem abaixo:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
<composite:attribute name="image" required="true" />
<composite:attribute name="nlogin"></composite:attribute>
<composite:attribute name="nsenha"></composite:attribute>
<composite:attribute name="clogin"></composite:attribute>
<composite:attribute name="csenha"></composite:attribute>
<composite:attribute name="txtbto"></composite:attribute>

<composite:attribute name="acao"
method-signature="java.lang.String action()" />

6
</composite:interface>
<composite:implementation>
<h:form>
<h:panelGrid columns="2">
<h:outputLabel value="#{cc.attrs.nlogin}"></h:outputLabel>
<h:inputText value="#{cc.attrs.clogin}"></h:inputText>
<h:outputLabel value="#{cc.attrs.nsenha}"></h:outputLabel>
<h:inputSecret value="#{cc.attrs.csenha}"></h:inputSecret>
<h:commandButton action="#{cc.attrs.acao}"
value="#{cc.attrs.txtbto}"></h:commandButton>
</h:panelGrid>
</h:form>
</composite:implementation>
</html>

Este componente de login será utilizado por outra página .xhtml.

Uma página de componente(s) no JSF 2.0 pode conter suporte aos


componentes do JSF, a validação, converters e listeners. Além disso, qualquer outra
tag HTML pode ser adicionada ao componente, incluindo também recursos de
templates.

As tags utilizadas para criar componentes compostos no exemplo são:

<composite:interface/> e <composite:implementation/>

Para utilizá-las, é necessário adicionar o seguinte namespace:

<html xmlns:composite=”http://java.sun.com/jsf/composite”>

A tag <composite:interface/> declara o contrato para um componente, ou seja,


definimos quais são os atributos que o componente receberá. Os atributos são
definidos dentro desta tag, com a tag <composite:attribute />, onde temos os
atributos name e required. Em name colocamos o nome do atributo do nosso
componente composto e definindo true, em required, definimos o atributo como de
preenchimento obrigatório.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


52 Parte 6
O exemplo mostrado possui um componente que terá o seguintes atributos
obrigatório, em ordem definidos na interface: image, me terá outros atributos
opcionais: nLogin, nSenha, cLogin, cSenha, txtbto e acao.

A tag <composite:implementation/> é onde definimos o conteúdo do


componente composto. Onde definir #{cc.attrs.x}, sendo que “x” é o nome do atributo
do seu componente, será o local de substituição quando preencher o componente na
página que o utilizar.

Crie um arquivo .xhtml de nome index1.xhtm

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:mycomp="http://java.sun.com/jsf/composite/mycomp"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>COMPONENTES_PERSONALIZADOS</title>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
<h2>LOGIN:</h2>
<mycomp:login nlogin="Login" nsenha="Senha" clogin="#{usuario.login}"
csenha="#{usuario.senha}" acao="#{usuario.logar}" txtbto="Logar">
</mycomp:login>
</h:body>
</html>

Crie outra página.xhtml de nome dados.xhtml conforme código abaixo:

<?xml version="1.0" encoding="UTF-8"?>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>APRESENTANDO DADOS DO USUARIO CAPTURADOS VIA COMPONENTES
PERSONALISADOS</title>
</h:head>
<h:body>
<h:panelGrid columns="2">
<h:outputText value="LOGIN: " />
<h:outputText value=" #{usuario.login}" />
<h:outputText value="SENHA: " />
<h:outputText value="#{usuario.senha}" />
</h:panelGrid>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 53

Execute a página index1.xhtml e verifique se o sistema se comporta conforme


imagens abaixo:

O sistema deverá apresentar esta tela da direita, e assim que o usuário


preencher os dados e clicar no botão Logar ele deverá apresentar os dados
digitados na tela conforme imagem abaixo.

Acabamos de criar um componente personalizado de nome login.xhtml, e o


utilizamos

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


54 Parte 6

Jpa e eclipselink
Teoria Ou hibernate

JPA (JAVA PERSISTENCE API) é uma padronização da linguagem java para o


mapeamento OR(Objeto/Relacional) através de notações.

HIBERNATE é uma framework que implementa a especificação JPA, o JPA


define as regras enquanto HIBERNATE o executa, faz o que o JPA especificou.

ECLIPSELINK também é uma framework que implementa a especificação JPA,


o JPA define as regras enquanto ECLIPSELINK o executa, faz o que o JPA
especificou.

Tudo isto foi desenvolvido, para que você, programador JAVA não necessite
mais de todo aquele trabalhão utilizando SQL para montar seus objetos utilizando
JDBC, com JDBC tínhamos que saber os tipo de dados das tabelas para fazer
conversão, criar códigos SQL dinamicamente.

Para usar a framework HIBERNATE ou o ECLIPSELINK, temos que entender


como funciona estes frameworks, assim como você acabou de aprender como é que
se usa o JSF.

Existem duas formas de relacionar tabelas com classes a partir de um banco


de dados já criado, ou, também podemos criar tabelas do nosso banco de dados
através de nossas classes. Para início de nossos estudo, vamos primeiramente criar
classes a partir do nosso banco de dados utilizando as facilidades da nossa
IDE(Eclipse) , assim vamos ter contato com as anotações (@), após estudarmos as
mais importantes iremos ‘refletir’ nossas classes no banco criando novas tabelas e
campos através de classes e atributos.

Vamos criar então um banco de dados conforme imagens abaixo para que nós
possamos utilizar este framework corretamente. O banco irá se chamar cadastro.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 55
A seguir os comandos SQL DDL para a criação do banco de dados e tabelas:

CREATE DATABASE cadastro ;

CREATE TABLE IF NOT EXISTS cadastro. usuario (


id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
Nome VARCHAR(70) NOT NULL ,CPF MEDIUMTEXT NOT NULL ,
flag TINYINT(1) NOT NULL , data_cadastro DATE NOT NULL ,
PRIMARY KEY (id) );

CREATE TABLE IF NOT EXISTS cadastro.categorias (


id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
descriacao VARCHAR(45) NOT NULL , flag TINYINT(1) NULL DEFAULT '1' ,
data_cadastro DATE NOT NULL , PRIMARY KEY (id) );

CREATE TABLE IF NOT EXISTS cadastro.produto (


id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
nome VARCHAR(45) NOT NULL , preco DOUBLE NOT NULL ,
descricao VARCHAR(45) NOT NULL , idCategoria INT(10) UNSIGNED NOT NULL ,

6
flag TINYINT(1) NULL DEFAULT '1' , PRIMARY KEY (id) ,
INDEX FK_prod_cat1 (idCategoria ASC) , CONSTRAINT FK_prod_cat1
FOREIGN KEY (idCategoria ) REFERENCES bd_gp_jpa.categorias (id )
ON DELETE CASCADE ON UPDATE CASCADE);

Utilizaremos o ECLIPSELINK porque nossa IDE está preparada para usa-la, da


mesma forma de se utilizar o ECLIPSELINK é bem parecida com HIBERNATE ficando
a critério do aluno pesquisar ou ler as publicações que serão editadas no twitter
LOUCO_POR_JAVA deste autor desta apostila.

Após criarmos estas tabelas no banco, vamos utilizar a IDE Eclipse para criar
nossas classes e nosso arquivo persistence.xml que é um arquivo de configuração
utilizado pelas classes de nossa framework para mapear uma conexão com o banco e
suas tabelas com classes.

Crie um Dinamic Web Project de nome JSF_JPA conforme imagem abaixo:

Click
em
modify

1 - Selecione o ícone Java Server Faces


2 - JPA

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


56 Parte 6
Quando aparecer esta tela abaixo, clique no ícone parecido com um diskete,
após selecione um dos EclipseLink, utilizaremos o último da lista conforme imagem
abaixo.

Baixe esta library, todas estes arquivos ficarão gravados na pasta libraries
dentro da sua pasta workspace.

1 - Selecione o
link Add
connection

2 - Selecione
banco MySQL.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 57

3 - Selecione o 4 - Selecione
ícone. Driver MySQL que irá
utilizar, no nosso caso o
5.1

5-Sele-
cione
a aba
JAR
List

6
7-Selecione o Driver Mysql que irá
utilizar para sua conexão com o BD.

6-Selecione o Driver listado


e clique em Remove JAR/Zip

8-Selecione a aba Properties.

9 – Troque o nome da database que usará,


no nosso caso será o banco de nome
cadastro

10 – coloque a senha de acesso ao banco


de dados MySQL, e caso seu usuário seja
diferente de root.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


58 Parte 6

11 – Selecione novamente a aba


Name/Type, selecione o Drive desejado
eclique em OK.

12 – Reparem que agora os dados foram


preenchidos automaticamente, clique em
Test Connection para verificar se a
configuração foi feita corretamente, caso
sim, o sistema irá aprsentar um
JOPtionPane conforme abaixo

13 – Clique em next para


visualizar a seguinte tela.

14 – Clique em finish para


finalizar a configuração.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 59

15 – O resto já é de conhecimento do programador JAVA J2EE, pois, já fizeram diversos


projetos para utilizar a framework JSF. A estrutura do nosso projeto deverá ficar igual a
última imagem da direita acima.

6
Agora vamos criar nossas classes a partir das tabelas do banco de dados cadastro criado no
início deste capítulo.
17 – Altere o atributo Transaction type
para Resource Local

16 – de dois(2)
cliques no arquivo
de configuração
persistence.xml

18 – O link Populate from connection irá


ser habilitado, o selecione

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


60 Parte 6

19 – Selecione a
conexão criada nos
passos 1 a 14, no nosso
caso não demos nome
para ele, então por
default ele se chamará
New MySQL

20 – Selecione a aba
Source

21 – Este é o arquivo
gerado por toda estes
passos, um mapeamento
do banco de dados para
conexão e
relacionamento entre as
tabelas e nossas classes.

Salve seu projeto, agora vamos criar nossas classes a partir de nossas tabelas utilizando a IDE
Eclipse, siga os passos a seguir:

22 – Crie um novo pacote com o


nome de entidades.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 61

6
23 – Crie dentro do pacote entidades
arquivos do tipo JPA Entities from Tables
conforme figura ao lado

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


62 Parte 6

24 – Selecione as 3 (três) tabelas mapeadas


pela conexão que criamos nos passos
anteriores e clique em next.

25 – A próxima tela que o sistema apresentará será a


tela de associações, nesta tela em especial ele nos
mostra o relacionamento muito pra um (muitos
produtos para uma categoria), então sabemos que
existirá um List de objetos produtos dentro de
categoria, pois, uma categoria terá muitos produtos,
mas no objeto produto só existirá uma categoria.
Clique em next.

26 – Altere o atributo do Key generator para


identity, pois o MySQL usa este atributo para
gerar suas chaves primárias e estrangeiras. Toque
também o atributo da Association fetch para
Lazy. Selecione também o tipo de coleções que
utilizaremos, selecione java.util.List

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 63

27 – Pronto, agora é só clicar em Finish e


verificar as classes criadas pela nossa IDE
dentro do pacote entidades conforme
imagem abaixo

Verifiquem os atributos dos beans que sua IDE criou, em todos atributos foram
colocados anotações, veremos agora o que significam essas anotações, para isto,
deveremos ter em mente os conceitos de banco de dados, pois estas anotações estão
intrinsicamente ligados aos tipos de dados da tabela, se são chave primárias ou até
mesmo se são chave primária com criação de números automáticos:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


64 Parte 6
Anotações para Entity
As classes Entity podem ser melhor especificadas quando adicionamos
algumas anotações, estas anotações podem informar ao JPA que você por exemplo
não segue o padrão de nome de tabela igual ao nome da classe Java, que sua tabela
no banco tem um relacionamento de Um-Para-Muitos com outra tabela, que a tabela
utiliza um gerador de ID do tipo SEQUENCE para definir o número da chave primaria e
outras informações.

Obrigatoriamente toda entity do JPA precisa ter pelo menos as


anotações javax.persistence.Entity que informa que é uma tabela do banco de dados
e javax.persistence.Id que informa qual o atributo é chave primaria da tabela.

Segue algumas anotações básicas utilizadas no mapeamento do JPA:

javax.persistence.Entity

Usado para definir que uma classe é uma Entity, por padrão quando o nome da
Entity é igual ao nome da tabela o mapeamento é feito automaticamente pelo JPA.

Propriedade Descrição
name Informa o nome da Entity, por padrão o nome da entity é nome da
classe. Este nome é utilizado para referenciar a entity na consulta.

Exemplo:
Criar uma Entity que está mapeada para a tabela PRODUTO.
@Entity
public class Produto {
...
}

javax.persistence.Table

Define o nome da tabela no banco de dados.

Propriedade Descrição
Catalog O catalogo da tabela.
Name O nome da tabela.
schema O esquema da tabela.
uniqueConstraints Regras / Restrições que podem ser adicionadas na tabela.

Exemplo:
Criar uma Entity que está mapeada para a tabela PRJ_PDT que armazena os
dados de um produto. Se criarmos uma classe chamada Prj_Pdt para mapear esta
tabela, não estaremos seguindo as boas praticas de nomeação de classes e por
padrão a anotação @Entity irá fazer o mapeamento através do nome da classe. Para
especificar manualmente qual a tabela deve ser mapeada com a Entity, podemos usar
a anotação @Table e especificar a propriedade name.
@Entity
@Table(name="prod")
public class Produto {
...
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 65

javax.persistence.Id

Informa o atributo da Entity que representa a chave primaria.

Exemplo:

Criar um atributo para mapear a coluna ID da tabela PRODUTO que representa


a chave primaria desta tabela. O tipo do atributo pode ser definido de acordo com o
tipo da coluna da tabela.

@Entity
public class Produto {

@Id
private int id;

...
}

6
javax.persistence.Column

Informa as configurações de coluna da tabela, por padrão quando o nome do


atributo da Entity é igual ao nome da coluna da tabela, o relacionamento é feito
automaticamente pelo JPA.

Propriedade Descrição
columnDefinition Definição do tipo da coluna.
insertable Informa se a tabela deve ser incluída no SQL de insert, por padrão é
true.
length Tamanho da coluna, por padrão é 255.
name Nome da tabela que contém está coluna, se não for informado a
coluna assume o nome da tabela da entity.
nullable Informa se o valor pode ser null.
precision Precisão da coluna decimal.
scale Número de casas decimais, usado somente em coluna com número
decimal.
table Nome da tabela que contém está coluna, se não for informado
assume o nome da tabela da entity.
unique Informa se a coluna é chave única.
updatable Informa se a coluna deve ser incluída no SQL de update, por padrão
é true.

Exemplo:

Criar um atributo para representar a coluna DATA_VALIDADE da tabela


PRODUTO, sendo que o tipo desta coluna no banco de dados representa uma data.
Se criarmos um atributo com o nome data_validade não estaremos seguindo as boas
práticas de nomes de atributos e por padrão os nomes dos atributos representam os
nomes das colunas da tabela. Para especificar manualmente qual o nome da coluna,
podemos usar a anotação @Column e especificar a propriedade name.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


66 Parte 6
@Entity
public class Produto {

@Column(name="DATA_VALIDADE")
@Temporal(value=TemporalType.DATE)
private Date dataValidade;

javax.persistence.SequenceGenerator

Utilizado para representar uma sequência numérica gerada através do banco de


dados.

Propriedade Descrição
name Nome único para o gerador que pode ser referenciado por uma ou
mais classes que pode ser utilizado para gerar valores de chave
primaria.
allocationSize A quantidade que será incrementada na sequence, o padrão é 50.
initialValue Valor inicial da sequence.
sequenceName Nome da sequence do banco de dados.

Exemplo:

Criar uma Entity para representar a tabela PRODUTO e no banco de dados temos
criado uma SEQUENCE chamada SEQ_PRODUTO que deve ser usada para geração
do ID da tabela.
@Entity
@SequenceGenerator(name="SEQ_PROD", sequenceName="SEQ_PRODUTO", initialValue=1,
allocationSize=1)
public class Produto {
...
}

javax.persistence.GeneratedValue

Define a estratégia para criar o ID, pode ser tipo AUTO (incrementa
automaticamente 1, 2, 3 em sequência) ou utilizando uma SEQUENCE.

Propriedade Descrição
generator Nome do gerador da chave primaria que é especificado na anotação
@SequenceGenerator ou @TableGenerator.
Strategy Estratégia de geração de chave primaria que o serviço de persistência
precisa usar para gerar a chave primaria.
Seu valor pode ser obtido através da enum
javax.persistence.GenerationType, os valores podem ser AUTO,
IDENTITY, SEQUENCE ou TABLE.

Exemplo:

Criar uma Entity para representar a tabela PRODUTO e usar o


AUTO_INCREMENT do banco de dados para gerar o valor da coluna ID que
representa chave primaria da tabela.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 67
@Entity
public class Produto {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

...
}

Criar uma Entity para representar a tabela PRODUTO e no banco de dados


temos criado uma SEQUENCE chamada SEQ_PRODUTO que deve ser usada para
gerar o valor da coluna ID que representa a chave primaria da tabela.

@Entity
@SequenceGenerator(name="SEQ_PROD", sequenceName="SEQ_PRODUTO", initialValue=1,
allocationSize=1)
public class Produto {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_PROD")

6
private Long id;

...
}

javax.persistence.Temporal

Utilizado para representar campos de Data e Hora, nesta anotação podemos


definir o tipo de dado DATE, TIME e TIMESTAMP.

Propriedade Descrição
Value O tipo usado para mapear java.util.Date e java.util.Calendar.
Seu valor pode ser obtido através da enum
javax.persistence.TemporalType, os valores podem ser DATE, TIME e
TIMESTAMP.

Exemplo:

Criar um atributo para representar a coluna DATA_VALIDADE da tabela


PRODUTO, sendo que o tipo desta coluna no banco de dados representa uma data.
@Entity
public class Produto {

@Column(name="DATA_VALIDADE")
@Temporal(value=TemporalType.DATE)
private Date dataValidade;

Criar um atributo para representar a coluna ENTRADA da tabela VALET, sendo que o
tipo desta coluna no banco de dados representa uma data e hora.

@Entity
public class Valet {

@Temporal(value=TemporalType.TIMESTAMP)
private Date entrada;

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


68 Parte 6
javax.persistence.Transient

Informa que o atributo não representa uma coluna da tabela.

Criar um atributo para representar a idade do cliente e não deve ser persistido no
banco de dados.

@Entity
public class Cliente {

@Transient
private Integer idade;

Agora que vimos as notações utilizadas pelo JPA, vamos a nossa aplicação,
vamos criar telas de cadastro para esses 3 (três) beans que representam tabelas no
BD, necessitaremos de uma quantidade excessiva de programação, o aluno deve se
empenhar para terminar o código a tempo, pois esta será uma aplicação JSF completa
com JPA.

Nossos beans ficarão assim:

package br.com.grandeporte.entity.model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
/**
* @author Rogério Aparecido dias
* The persistent class for the usuario database table.
*/
@Entity
public class Usuario implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Lob
private String cpf;

@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;

private boolean flag;

private String nome;

public Usuario() {}
Getters e Setters ...

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 69

package br.com.grandeporte.entity.model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
/**
* @author Rogério Aparecido dias
* The persistent class for the produto database table.
*/
@Entity
public class Produto implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;

private String descricao;

private boolean flag;

6
private String nome;

private double preco;

//bi-directional many-to-one association to Categoria


@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="idCategoria")
private Categoria categoria;

public Produto() {} Getters e Setters ...

package br.com.grandeporte.entity.model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
/**
* @author Rogério Aparecido dias
* The persistent class for the categorias database table. *
*/
@Entity
@Table(name="categorias")
public class Categoria implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

@Temporal(TemporalType.DATE)
@Column(name="data_cadastro")
private Date dtCadastro;

private String descriacao;

private boolean flag;

//bi-directional many-to-one association to Produto


@OneToMany(mappedBy="categoria")
private List<Produto> produtos;

public Categoria() {} Getters e Setters ...

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


70 Parte 6
Seguindo um padrão de projeto, vamos criar um pacote DAO para criar a
conexão a partir do arquivo persistence.xml e fazer o CRUD com esses objetos do
pacote entidades.

package br.com.grandeporte.DAO.model;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import entidades.Usuario;
/**
* @author Rogério Aparecido dias
*/
public abstract class UsuarioDAO {

public UsuarioDAO() {}

public static void alterUsu(Usuario usu) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.merge(usu);
em.getTransaction().commit();
System.out.println("Alterado com sucesso!");
} catch (Exception e) {
System.out.println("Erro ao alterar!/n" + e);
} finally {
em.close();
}
}

public static void delUsu(int id) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.remove(em.find(Usuario.class, id));
em.getTransaction().commit();
System.out.println("Removido com sucesso!");
} catch (Exception e) {
System.out.println("Erro ao remover!/n" + e);
} finally {
em.close();
}
}

public static void gravaUsu(Usuario usu) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(usu);
em.getTransaction().commit();
em.close();
}

public static Usuario getUsu(int id) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
Usuario usu = em.find(Usuario.class, id);
return usu;
}
public static List<Usuario> getArrCat() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select c from Usuario c");
List<Usuario> arrUsu = query.getResultList();
return arrUsu;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 71

package br.com.grandeporte.DAO.model;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import entidades.Categoria;

/**
* @author Rogério Aparecido dias
*/
public abstract class CategoriaDAO {

public CategoriaDAO() {}

public static List<Categoria> getArrCat() {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("select c from Categoria c");
List<Categoria> arrCat = query.getResultList();
return arrCat;
}

6
public static void alterCat(Categoria cat) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.merge(cat);
em.getTransaction().commit();
System.out.println("Alterado com sucesso!");
} catch (Exception e) {
System.out.println("Erro ao alterar!/n" + e);
} finally {
em.close();
}
}

public static void delCat(int id) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.remove(em.find(Categoria.class, id));
em.getTransaction().commit();
System.out.println("Removido com sucesso!");
} catch (Exception e) {
System.out.println("Erro ao remover!/n" + e);
} finally {
em.close();
}
}

public static void gravaCat(Categoria cat) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(cat);
em.getTransaction().commit();
em.close();
}

public static Categoria getCat(int id) {


EntityManagerFactory emf = Persistence.createEntityManagerFactory("JSF_JPA");
EntityManager em = emf.createEntityManager();
Categoria cat = em.find(Categoria.class, id);
return cat;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


72 Parte 6
Vamos criar agora nossos ManagedBeans dentro do pacote controller. Crie
uma classe de nome UsuarioBean no pacote br.com.grandeporte.beans.controller

package br.com.grandeporte.beans.controller;

import javax.faces.event.*;
import java.sql.Date;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import br.com.grandeporte.DAO.model.UsuarioDAO;
import br.com.grandeporte.entity.model.Usuario;
/**
* @author Rogério Aparecido dias
* ManagedBean que será nossa classe de controle do xhtml com as classes do pacote model.
*/
@ManagedBean
@RequestScoped
public class UsuarioBean {

private static Usuario usu;

public UsuarioBean() {
usu = new Usuario();
}

public void gravarUsu(ActionEvent e) {


usu.setFlag(true);
java.util.Date dt = new java.util.Date();
usu.setDtCadastro(new Date(dt.getYear(), dt.getMonth(), dt.getDay()));
UsuarioDAO.gravaUsu(usu);
}

public Usuario getUsu() {


return usu;
}

public void setUsu(Usuario usu) {


this.usu = usu;
}
}

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 73

Crie uma classe de nome CategoriaBean no pacote:


br.com.grandeporte.beans.controller

package br.com.grandeporte.beans.controller;

import javax.faces.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import br.com.grandeporte.DAO.model.CategoriaDAO;
import br.com.grandeporte.entity.model.Categoria;
/**
* @author Rogério Aparecido dias
* ManagedBean que será nossa classe de controle do xhtml com as classes do pacote model.
*/
@ManagedBean
@RequestScoped
public class CategoriasBean {
private Categoria cat;
private List<Categoria> arrCat;

6
public CategoriasBean() {
cat = new Categoria();
refresLista();
}

public void gravarCat(ActionEvent e) {


cat.setFlag(true);
java.util.Date dt = new java.util.Date();
cat.setDtCadastro(dt);
CategoriaDAO.gravaCat(cat);
refresLista();
}

public Categoria getCat() {


return cat;
}
Getters e Setters...

Vamos criar agora nossas páginas xhtml, vamos começar com a de nome
cadusuario.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>CRUD_JSF_JPA</title>
</h:head>
<h:body>
<h2>CADASTRAR USUÁRIO!</h2>
<h:form>
<h:panelGrid columns="2">

<h:outputLabel value="Nome: " />


<h:inputText value="#{usuarioBean.usu.nome}" />

<h:outputLabel value="CPF: " />


<h:inputText value="#{usuarioBean.usu.cpf}" />
<h:commandButton value="Gravar"
actionListener="#{usuarioBean.gravarUsu}"></h:commandButton>
</h:panelGrid>
</h:form>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


74 Parte 6
Vamos criar agora nossas páginas xhtml, vamos começar com a de nome
cadcategoria.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>CRUD_JSF_JPA</title>
</h:head>

<h:body>
<h2>CADASTRAR CATEGORIAS DE PRODUTOS!</h2>
<h:form>
<h:panelGrid columns="2">

<h:outputLabel value="DESCRIÇÃO: " />


<h:inputText value="#{categoriasBean.cat.descriacao}" />

<h:commandButton value="Gravar"
actionListener="#{categoriasBean.gravarCat}"></h:commandButton>

</h:panelGrid>
</h:form>
<h:dataTable value="#{categoriasBean.arrCat}" var="cat" border="1">
<f:facet name="header">Categorias </f:facet>

<h:column>
<f:facet name="header">ID </f:facet>
#{cat.id}
</h:column>

<h:column>
<f:facet name="header">Descrição </f:facet>
#{cat.descriacao}
</h:column>

<h:column>
<f:facet name="header">Abilitado </f:facet>
#{cat.flag}
</h:column>

<h:column>
<f:facet name="header">DATA CADASTRO </f:facet>
#{cat.dtCadastro}
</h:column>
</h:dataTable>
</h:body>
</html>

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 75

Execute esta aplicação e verifique se o sistema irá se portar conforme imagens


abaixo:

O sistema irá
apresentar a
tela da
esquerda,
preencha os
dados confor-
me Imagem da
direita, clique
no botão

6
Gravar

Verifique os dados da tabela usuario no seu banco de dados, verifique se


esses dados foram inseridos conforme imagem abaixo:

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


76 Parte 6
E como isto foi possível se não usamos SQL para inserir esses dados no banco
sem se quer utilizar as classes de conexão JDBC estudadas no início do curso? Se
você programador java, que já inspecionou seu código da classe UsuarioDAO tem a
resposta para esta pergunta! É exatamente nesta classe, no método :

... private String URL =


public static void gravaUsu(Usuario usu) { "jdbc:mysql://localhost:3306/cadastro";
EntityManagerFactory emf = private String USUARIO = "root";
Persistence.createEntityManagerFactory("JSF_JPA"); private String SENHA = "4898";
public Connection conexao =
DriverManager.getConnection(URL, USUARIO,
SENHA);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin(); private Statement st =conexao.createStatement();

String sqlInsert = "INSERT INTO cadastro.usuario


em.persist(usu); (nome, cpf, flag, data_cadastro) VALUES ('"+
usu.getNome()+ "', "+ usu.getCpf()+ ", "+
usu.getFlag()+ ", '" + usu.getDtCadastro() +
"');";

em.getTransaction().commit();
st.executeUpdate(sqlInsert);
em.close();
} close();
...

O diagrama acima mostra muito bem como funciona uma conexão feita pela
classe EntityManagerFactory, reparem que o parâmetro de entrada
obrigatóriamente é o nome inserido no arquivo persistence.xml:

Vamos ver agora os métodos desta Interface EntityManager que usaremos


para nossas persistência no BD.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 77

Interface EntityManager

A interface javax.persistence.EntityManager possui a assinatura de métodos


para manipular as entidades, executar consultas e outros:

public void persist(Object entity);

Faz uma nova instância gerenciável e persistivel.

EntityTransaction transaction = entityManager.getTransaction();


transaction.begin();
entityManager.persist(pessoa);
transaction.commit();

Utilizamos o método persist da EntityManager para salvar a Entity Pessoa no


banco de dados.

Note que criamos uma javax.persitence.EntityTransaction para criar uma

6
transação, pois os métodos persist(), merge() e remove() precisam de um transação
para realizar suas operações no banco de dados.

public <T> T merge(T entity);

Junta o estado da Entity com o estado persistido.

EntityTransaction transaction = entityManager.getTransaction();


transaction.begin();
entityManager.merge(pessoa);
transaction.commit();

Utilizamos o método merge da EntityManager para atualizar a Entity Pessoa


no banco de dados.

public void remove(Object entity);

Remove a instância da Entity do banco de dados.

EntityTransaction transaction = entityManager.getTransaction();


transaction.begin();
Pessoa pessoa = entityManager.find(Pessoa.class, id);
entityManager.remove(pessoa);
transaction.commit();

Primeiro utilizamos o valor do id para pesquisar (find) a Entity no banco de dados,


quando fazemos esta pesquisa e estamos dentro da transação a Entity fica no estado
persistivel dentro da EntityManager, então podemos utilizar o método remove para
remover a Entity Pessoa do banco de dados.

public boolean contains(Object entity);

Checa se a instância da Entity está em um estado persistivel.

boolean contem = entityManager.contains(pessoa);

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


78 Parte 6
public <T> T find(Class<T> entityClass, Object primaryKey);

Procura um registro no banco de dados através da entity e id da tabela, caso não


encontre retorna null.

Pessoa pessoa = entityManager.find(Pessoa.class, id);

Utilizamos o método find da EntityManager que pesquisa uma Entity Pessoa pela sua
classe e a chave primaria.

public <T> T getReference(Class<T> entityClass, Object primaryKey);

Procura um registro no banco de dados através da entity e id da tabela, caso


não encontre retorna uma exceção javax.persistence.EntityNotFoundException.

public void flush();

Os métodos persist(), merge() e remove() aguardam finalização da transação


para sincronizar as entidades com o banco de dados, o método flush() força essa
sincronização no momento em que é chamado.

public void refresh(Object entity);

Verifica se houve alguma alteração no banco de dados para sincronizar com a


entidade.

public void clear();

Remove as entidades que estão no estado gerenciável dentro da


EntityManager.

public void close();

Fecha a conexão do EntityManager.

public boolean isOpen();

Verifica se o EntityManager esta com a conexão aberta.

public EntityTransaction getTransaction();

Obtém uma javax.persistence.EntityTransaction que é uma transação com o


banco de dados.

public Query createQuery(String qlString);

A String que este método recebe como parâmetro é uma QL, parecida com a
linguagem SQL, porém com algumas modificações.

Agora que você, programador java já conhece sobre a API de persistência,


dobre uma ferramenta ORM chamada EclipseLink, fica muito fácil utilizar o Hibernate
para sua persistência em BDs.

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


Parte 6 79

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218


80 Parte 6

Avaliação Então...Como foi ?!?

Estou fera!

Fiz Certo!

 Muito Bom  Bom  regular  ruim  Muito ruim

www.grandeporte.com.br  (11) 4427-4579(11) 9 9903-3218

Você também pode gostar