You are on page 1of 157

TREINAMENTOS

Desenvolvimento Web com JSF2 e JPA2

Desenvolvimento Web com JSF 2 e JPA 2

15 de maro de 2011

www.k19.com.br

ii

Sumrio
1 Banco de dados 1.1 Bases de dados (Databases) . 1.2 Tabelas . . . . . . . . . . . . 1.3 Operaes Bsicas . . . . . . 1.4 Chaves Primria e Estrangeira 1.5 Consultas Avanadas . . . . . 1.6 Exerccios . . . . . . . . . . . 1 2 4 7 11 11 12 27 27 28 28 28 29 29 31 33 33 34 35 36 37 37 37 37 38 38 39 40 41 43 43 43 44 44

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

JDBC 2.1 Driver . . . . . . . . . . . . . . . . . . . . . 2.2 JDBC . . . . . . . . . . . . . . . . . . . . . 2.3 Instalando o Driver JDBC do MySQL Server 2.4 Criando uma conexo . . . . . . . . . . . . . 2.5 Inserindo registros . . . . . . . . . . . . . . 2.6 Exerccios . . . . . . . . . . . . . . . . . . . 2.7 SQL Injection . . . . . . . . . . . . . . . . . 2.8 Exerccios . . . . . . . . . . . . . . . . . . . 2.9 Listando registros . . . . . . . . . . . . . . . 2.10 Exerccios . . . . . . . . . . . . . . . . . . . 2.11 Fbrica de conexes (Factory) . . . . . . . . 2.12 Exerccios . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

. . . . . . . . . . . .

JPA 2 e Hibernate 3.1 Mltiplas sintaxes da linguagem SQL . . . . . . . . . . . 3.2 Orientao a Objetos VS Modelo Entidade Relacionamento 3.3 Ferramentas ORM . . . . . . . . . . . . . . . . . . . . . 3.4 O que JPA e Hibernate . . . . . . . . . . . . . . . . . . 3.5 Congurao . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Mapeamento . . . . . . . . . . . . . . . . . . . . . . . . 3.7 Gerando o banco . . . . . . . . . . . . . . . . . . . . . . 3.8 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . 3.9 Manipulando entidades . . . . . . . . . . . . . . . . . . . 3.9.1 Persistindo . . . . . . . . . . . . . . . . . . . . . 3.9.2 Buscando . . . . . . . . . . . . . . . . . . . . . . 3.9.3 Removendo . . . . . . . . . . . . . . . . . . . . . 3.9.4 Atualizando . . . . . . . . . . . . . . . . . . . . . iii

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

SUMRIO 3.9.5 Listando . 3.9.6 Transaes 3.10 Exerccios . . . . . 3.11 Repository . . . . . 3.12 Exerccios . . . . . 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SUMRIO . . . . . . . . . . . . . . . . . . . . 44 44 45 46 47 49 49 49 50 50 50 51 51 51 52 52 53 53 53 55 55 55 56 56 56 57 58 63 63 65 66 67 68 68 68 71 71 72 73 74 iv

Web Container 4.1 Necessidades de uma aplicao web . 4.2 Web Container . . . . . . . . . . . . 4.3 Especicao Java EE . . . . . . . . 4.4 Exerccios . . . . . . . . . . . . . . . 4.5 Aplicao Web Java . . . . . . . . . . 4.6 Exerccios . . . . . . . . . . . . . . . 4.7 Processando requisies . . . . . . . 4.8 Servlet . . . . . . . . . . . . . . . . . 4.8.1 Inserindo contedo na resposta 4.9 Exerccios . . . . . . . . . . . . . . . 4.10 JSP . . . . . . . . . . . . . . . . . . 4.11 Exerccios . . . . . . . . . . . . . . . 4.12 Frameworks . . . . . . . . . . . . . . Viso Geral do JSF 2 5.1 Aplicao de exemplo . . . . . . 5.2 Managed Beans . . . . . . . . . 5.2.1 GeradorDeApostasBean 5.3 Facelets e Componentes Visuais 5.3.1 Tela de entrada . . . . . 5.3.2 Tela de Sada . . . . . . 5.4 Exerccios . . . . . . . . . . . . Componentes Visuais 6.1 Formulrios . . . 6.2 Panel Grid . . . . 6.3 Panel Group . . . 6.4 Tabelas . . . . . 6.5 Namespaces . . . 6.6 Esqueleto HTML 6.7 Exerccios . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

Facelets 7.1 Templating . . . . . 7.2 Exerccios . . . . . . 7.3 Particionando as telas 7.4 Exerccios . . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

www.k19.com.br

SUMRIO 8 Navegao 8.1 Navegao Esttica Implcita . 8.2 Navegao Esttica Explcita . 8.3 Exerccios . . . . . . . . . . . 8.4 Navegao Dinmica Implcita 8.5 Navegao Dinmica Explcita 8.6 Exerccios . . . . . . . . . . .

SUMRIO 77 77 78 78 80 81 81 85 85 86 86 86 87 87 87 87 88 88 89 90 90 91 92 95 95 95 96 97 97 98 98 99 101 101 101 101 102 102 102 102 103

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

Managed Beans 9.1 Criando Managed Beans . . . . . . . . . . . . . . . . 9.2 Disponibilizando dados para as telas . . . . . . . . . . 9.3 Recebendo dados das telas . . . . . . . . . . . . . . . 9.4 Denindo o tratamento das aes . . . . . . . . . . . . 9.5 Expression Language . . . . . . . . . . . . . . . . . . 9.5.1 Nome dos Managed Beans . . . . . . . . . . . 9.5.2 Acessando as propriedades dos Managed Beans 9.6 Binding . . . . . . . . . . . . . . . . . . . . . . . . . 9.7 Escopo . . . . . . . . . . . . . . . . . . . . . . . . . . 9.7.1 Request . . . . . . . . . . . . . . . . . . . . . 9.7.2 Session . . . . . . . . . . . . . . . . . . . . . 9.7.3 Application . . . . . . . . . . . . . . . . . . . 9.7.4 View . . . . . . . . . . . . . . . . . . . . . . 9.8 Interdependncia e Injeo . . . . . . . . . . . . . . . 9.9 Exerccios . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

10 Converso e Validao 10.1 Converso . . . . . . . . . . . . . . . . 10.1.1 Converso Padro Implcita . . 10.1.2 Converso Padro Explcita . . 10.2 Mensagens de Erro . . . . . . . . . . . 10.2.1 h:message . . . . . . . . . . . . 10.2.2 h:messages . . . . . . . . . . . 10.2.3 Alterando as Mensagens de Erro 10.3 Exerccios . . . . . . . . . . . . . . . . 10.4 Validao . . . . . . . . . . . . . . . . 10.4.1 Validao Padro . . . . . . . . 10.4.2 Campo Obrigatrio (Required) . 10.4.3 f:validateLongRange . . . . . . 10.4.4 f:validateDoubleRange . . . . . 10.4.5 f:validateLength . . . . . . . . 10.4.6 f:validateRegex . . . . . . . . . 10.4.7 Bean Validation . . . . . . . . . 10.5 Exerccios . . . . . . . . . . . . . . . . v

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . .

K19 Treinamentos

SUMRIO 11 Eventos 11.1 Eventos de Aplicao (Application Events) 11.1.1 ActionEvent . . . . . . . . . . . . 11.1.2 ValueChangeEvent . . . . . . . . . 11.2 Eventos de Ciclo de Vida (Lifecycle Events) 11.3 Exerccios . . . . . . . . . . . . . . . . . . 12 Ajax 12.1 Fazendo requisies AJAX . . . . . . . . 12.2 Recarregando alguns pedaos das telas . 12.3 Processando alguns pedaos das telas . 12.4 Palavras especiais . . . . . . . . . . . . . 12.5 Exerccios . . . . . . . . . . . . . . . . .

SUMRIO 107 107 107 108 109 109 113 113 114 115 115 116 119 119 119 120 120 121 121 122 122 123 123 124 125 126 127 127 129 130 132 132 133 133 133 134 135 135 139 139 140 140 143 143 vi

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

13 Projeto 13.1 Modelo . . . . . . . . . . . . . . . . . . . . . . . 13.2 Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.3 Persistncia - Mapeamento . . . . . . . . . . . . . 13.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.5 Persistncia - Congurao . . . . . . . . . . . . . 13.6 Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.7 Persistncia - Open Session in View . . . . . . . . 13.7.1 Gerenciando as fbricas de Entity Managers 13.7.2 Filtros . . . . . . . . . . . . . . . . . . . . 13.7.3 Gerenciando os Entity Managers . . . . . . 13.8 Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.9 Persistncia - Repositrios . . . . . . . . . . . . . 13.10Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.11Apresentao - Template . . . . . . . . . . . . . . 13.12Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.13Cadastrando e Listando Selees . . . . . . . . . . 13.14Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.15Mensagens de Erro . . . . . . . . . . . . . . . . . 13.16Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.17Removendo Selees . . . . . . . . . . . . . . . . 13.18Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.19Otimizando o nmero de consultas . . . . . . . . . 13.20Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.21Cadastrando, Listando e Removendo Jogadores . . 13.22Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.23Removendo Selees com Jogadores . . . . . . . . 13.24Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.25Controle de Acesso . . . . . . . . . . . . . . . . . 13.26Exerccios . . . . . . . . . . . . . . . . . . . . . . 13.27Ordem dos ltros . . . . . . . . . . . . . . . . . . 13.28Exerccios . . . . . . . . . . . . . . . . . . . . . . www.k19.com.br

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SUMRIO 13.29Controle de Erro 13.30Exerccios . . . . 13.31Enviando email . 13.32Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

SUMRIO . . . . . . . . . . . . . . . . 144 144 146 147

vii

K19 Treinamentos

SUMRIO

SUMRIO

www.k19.com.br

viii

Captulo 1 Banco de dados


O nosso objetivo desenvolver aplicaes em Java. Essas aplicaes necessitam armazenar as informaes relacionadas ao seu domnio em algum lugar. Por exemplo, uma aplicao de gerenciamento de uma livraria deve armazenar os dados dos livros que ela comercializa. Uma forma de suprir essa necessidade seria armazenar essas informaes em arquivos. Contudo, alguns fatores importantes nos levam a descartar tal opo. A seguir, apresentamos as principais preocupaes a serem consideradas ao trabalhar com dados: Segurana: As informaes potencialmente condenciais devem ser controladas de forma que apenas usurios e sistemas autorizados tenham acesso a elas. Integridade: Eventuais falhas de software ou hardware no devem corromper os dados. Acesso: As funes de consulta e manipulao dos dados devem ser implementadas. Concorrncia: Usualmente, diversos sistemas e usurios acessaro as informaes de forma concorrente. Apesar disso, os dados no podem ser perdidos ou corrompidos. Considerando todos esses aspectos, conclumos que seria necessria a utilizao de um sistema complexo para manusear as informaes das nossas aplicaes. Felizmente, tal tipo de sistema j existe e conhecido como Sistema Gerenciador de Banco de Dados (SGBD).

Sistemas gerenciadores de banco de dados


No mercado, h diversas opes de sistemas gerenciadores de banco de dados. A seguir, apresentamos os mais populares: 1

Banco de dados Oracle SQL Server MySQL Server PostgreSQL

MySQL Server
Neste treinamento, utilizaremos o MySQL Server, que mantido pela Oracle e vastamente utilizado no mercado. O MySQL Server pode ser obtido a partir do site: http://www.mysql.com.

MySQL Query Browser


Para interagir com o MySQL Server, utilizaremos um cliente com interface grca chamado de MySQL Query Browser.

1.1

Bases de dados (Databases)

Um sistema gerenciador de banco de dados capaz de gerenciar informaes de diversos sistemas ao mesmo tempo. Por exemplo, as informaes dos clientes de um banco, alm dos produtos de uma loja virtual. Caso os dados fossem mantidos sem nenhuma separao lgica, a organizao caria prejudicada. Alm disso, seria mais difcil implementar regras de segurana referentes ao acesso dos dados. Tais regras criam restries quanto ao contedo acessvel por cada usurio. Determinado usurio, por exemplo, poderia ter permisso de acesso aos dados dos clientes do banco, mas no s informaes dos produtos da loja virtual, ou vice-versa. Ento, por questes de organizao e segurana, os dados devem ser armazenados separadamente no SGBD. Da surge o conceito de base de dados (database). Uma base de dados um agrupamento lgico das informaes de um determinado domnio, como, por exemplo, os dados da nossa livraria.

Criando uma base de dados no MySQL Server


Para criar uma base de dados no MySQL Server, utilizamos o comando CREATE DATABASE. www.k19.com.br 2

Banco de dados

K19 Treinamentos

Banco de dados

Repare que alm da base de dados livraria h outras trs bases. Essas bases foram criadas automaticamente pelo prprio MySQL Server para teste ou para guardar algumas conguraes. Quando uma base de dados no mais necessria, ela pode ser removida atravs do comando DROP DATABASE.

1.2

Tabelas

Um servidor de banco de dados dividido em bases de dados com o intuito de separar as informaes de sistemas diferentes. Nessa mesma linha de raciocnio, podemos dividir os dados de uma base a m de agrup-los segundo as suas correlaes. Essa separao feita atravs de tabelas. Por exemplo, no sistema de um banco, interessante separar o saldo e o limite de uma conta, do nome e CPF de um cliente. Ento, poderamos criar uma tabela para os dados relacionados s contas e outra para os dados relacionados aos clientes.

nome Jos Maria

Cliente idade cpf 27 31875638735 32 30045667856

numero 1 2

Conta saldo 1000 2000

limite 500 700 4

www.k19.com.br

Banco de dados Uma tabela formada por registros(linhas) e os registros so formados por campos(colunas). Por exemplo, suponha uma tabela para armazenar as informaes dos clientes de um banco. Cada registro dessa tabela armazena em seus campos os dados de um determinado cliente.

Criando tabelas no MySQL Server

As tabelas no MySQL Server so criadas atravs do comando CREATE TABLE. Na criao de uma tabela necessrio denir quais so os nomes e os tipos das colunas.

K19 Treinamentos

Banco de dados

www.k19.com.br

Banco de dados

Se uma tabela no for mais desejada ela pode ser removida atravs do comando DROP TABLE.

1.3

Operaes Bsicas

As operaes bsicas para manipular os dados das tabelas so: inserir, ler, alterar e remover. Essas operaes so realizadas atravs da linguagem de consulta denominada SQL. Esta linguagem oferece quatro comandos bsicos: INSERT, SELECT, UPDATE e DELETE. Estes comandos so utilizados para inserir, ler, alterar e remover registros respectivamente. 7 K19 Treinamentos

Banco de dados

www.k19.com.br

Banco de dados

K19 Treinamentos

Banco de dados

www.k19.com.br

10

Banco de dados

1.4

Chaves Primria e Estrangeira

Suponha que os livros da nossa livraria so separados por editoras. Uma editora possui nome e telefone. Para armazenar esses dados, uma nova tabela deve ser criada. Nesse momento, teramos duas tabelas (Livro e Editora). Eventualmente, ser necessrio descobrir qual a editora de um determinado livro ou quais so os livros de uma determinada editora. Para isso, os registros da tabela Editora devem estar relacionados aos da tabela Livro. Na tabela Livro, poderamos adicionar uma coluna para armazenar o nome da editora a qual ele pertence. Dessa forma, se algum quiser recuperar as informaes da editora de um determinado livro, deve consultar a tabela Livro para obter o nome da editora correspondente. Depois, com esse nome, deve consultar a tabela Editora para obter as informaes da editora. Porm, h um problema nessa abordagem, a tabela Editora aceita duas editoras com o mesmo nome. Dessa forma, eventualmente, no conseguiramos descobrir os dados corretos da editora de um determinado livro. Para resolver esse problema, deveramos criar uma restrio na tabela Editora que proba a insero de editoras com o mesmo nome. Para resolver esse problema no MySQL Server, poderamos adicionar a propriedade UNIQUE no campo nome da tabela Editora. Porm ainda teramos mais um problema: na tabela livro poderamos adicionar registros com editoras inexistentes, pois no h nenhum vnculo explcito entre as tabelas. Para solucionar estes problemas, devemos utilizar o conceito de chave primria e chave estrangeira. Toda tabela pode ter uma chave primria, que um conjunto de um ou mais campos que devem ser nicos para cada registro. Normalmente, um campo numrico escolhido para ser a chave primria de uma tabela, pois as consultas podem ser realizadas com melhor desempenho. Ento, poderamos adicionar um campo numrico na tabela Editora e torn-lo chave primria. Vamos chamar esse campo de id. Na tabela Livro, podemos adicionar um campo numrico chamado editora_id que deve ser utilizado para guardar o valor da chave primria da editora correspondente ao livro. Alm disso, o campo editora_id deve estar explicitamente vinculado com o campo id da tabela Editora. Para estabelecer esse vnculo o campo editora_id deve ser uma chave estrangeira associada ao campo id. Uma chave estrangeira um conjunto de uma ou mais colunas de uma tabela que possuem valores iguais aos da chave primria de outra tabela. Com a denio da chave estrangeira, um livro no pode ser inserido com o valor do campo editora_id invlido. Caso tentssemos obteramos uma mensagem de erro.

1.5

Consultas Avanadas

Com o conceito de chave estrangeira, podemos fazer consultas complexas envolvendo os registros de duas ou mais tabelas. Por exemplo, descobrir todos os livros de uma determinada editora.

11

K19 Treinamentos

Banco de dados

1.6

Exerccios

1. Abra o MySQL Query Browser utilizando localhost como Server Hostname, root como Username e root como Password.

2. Caso exista uma base de dados chamada Livraria, remova-a conforme a gura abaixo:

www.k19.com.br

12

Banco de dados 3. Crie uma nova base de dados chamada livraria, conforme mostrado na gura abaixo. Voc vai utilizar esta base nos exerccios seguintes.

4. Selecione a base de dados livraria como padro. 13 K19 Treinamentos

Banco de dados

5. Crie uma tabela chamada Editora conforme as guras abaixo.

Altere o modo de criao da tabela para InnoDB, conforme mostrado na gura. www.k19.com.br 14

Banco de dados

Crie os campos conforme a gura e no esquea de tornar todos os campos obrigatrios, marcando a opo NOT NULL. Alm disso o campo id deve ser uma chave primria e automaticamente incrementada. 15 K19 Treinamentos

Banco de dados

6. Crie uma tabela chamada Livro conforme as guras abaixo:

Altere o modo de criao da tabela para InnoDB, conforme mostrado na gura. www.k19.com.br 16

Banco de dados

Novamente, adicione os campos conforme a gura abaixo, lembrando de marcar a opo NOT NULL. Alm disso o campo id deve ser uma chave primria e automaticamente incrementada. 17 K19 Treinamentos

Banco de dados

Voc precisa tornar o campo editora_id em uma chave estrangeira. Selecione a aba Foreign Keys e clique no boto com o smbolo de mais para adicionar uma chave estrangeira. Depois siga os procedimentos conforme mostrados na gura abaixo. www.k19.com.br 18

Banco de dados

7. Adicione alguns registros na tabela Editora. Veja exemplos na gura abaixo: 19 K19 Treinamentos

Banco de dados

8. Adicione alguns registros na tabela Livro. Veja exemplos na gura abaixo:

www.k19.com.br

20

Banco de dados 9. Consulte os registros da tabela Editora, e em seguida consulte a tabela Livro. Veja exemplos logo abaixo:

21

K19 Treinamentos

Banco de dados 10. Altere alguns dos registros da tabela Livro. Veja o exemplo abaixo:

11. Altere alguns dos registros da tabela Editora. Veja o exemplo abaixo: www.k19.com.br 22

Banco de dados

12. Remova alguns registros da tabela Livro. Veja o exemplo abaixo:

23

K19 Treinamentos

Banco de dados 13. Remova alguns registros da tabela Editora. Preste ateno para no remover uma editora que tenha algum livro relacionado j adicionado no banco. Veja o exemplo abaixo:

14. Faa uma consulta para buscar todos os livros de uma determinada editora. Veja um exemplo na gura abaixo: www.k19.com.br 24

Banco de dados

25

K19 Treinamentos

Banco de dados

www.k19.com.br

26

Captulo 2 JDBC
No captulo anterior, aprendemos que utilizar bancos de dados uma boa soluo para o armazenamento dos dados de uma aplicao. Entretanto, voc deve ter percebido que a interface de utilizao do MySQL (e dos outros bancos de dados em geral) no muito amigvel. A desvantagem deste tipo de interface, que ela exige que o usurio conhea a sintaxe da linguagem SQL para escrever as consultas. Alm disso, quando o volume de dados muito grande, mais difcil visualizar os resultados. Na prtica uma aplicao com interface simples desenvolvida para permitir que os usurios do sistema possam manipular os dados do banco, evitando desse modo que um usurio necessite conhecer SQL. Por isso, precisamos fazer com que essa aplicao consiga se comunicar com o banco de dados utilizado no sistema.

2.1

Driver

Como a aplicao precisa conversar com o banco de dados, ela deve trocar mensagens com o mesmo. O formato das mensagens precisa ser denido previamente. Por questes de economia de espao, cada bit de uma mensagem tem um signicado diferente. Resumidamente, o protocolo de comunicao utilizado binrio. Mensagens denidas com protocolos binrios so facilmente interpretadas por computadores. Por outro lado, so complexas para um ser humano compreender. Dessa forma, mais trabalhoso e mais suscetvel a erro desenvolver uma aplicao que converse com um banco de dados atravs de mensagens binrias. Para resolver esse problema e facilitar o desenvolvimento de aplicaes que devem se comunicar com bancos de dados, as empresas que so proprietrias desses bancos oferecem os drivers de conexo. Os drivers de conexo atuam como tradutores de comandos escritos em uma determinada linguagem de programao para comandos no protocolo do banco de dados. Do ponto de vista do desenvolvedor da aplicao, no necessrio conhecer o complexo protocolo binrio do banco. Em alguns casos, o protocolo binrio de um determinado banco de dados fechado. Consequentemente, a nica maneira de se comunicar com o banco de dados atravs de um driver de conexo. 27

JDBC

2.2

JDBC

Suponha que os proprietrios dos bancos de dados desenvolvessem os drivers de maneira totalmente independente. Consequentemente, cada driver teria sua prpria interface, ou seja, seu prprio conjunto de instrues. Dessa maneira, o desenvolvedor da aplicao precisa conhecer as instrues de cada um dos drivers dos respectivos bancos que ele for utilizar. Para facilitar o trabalho do desenvolvedor da aplicao, foi criado o JDBC (Java Database Connectivity). O JDBC uma API que generaliza a interface com os banco de dados. Assim, quando uma empresa proprietria de um banco de dados pretende desenvolver um driver para ser utilizado com a linguagem Java, ela segue a especicao JDBC com o intuito de incentivar a adoo do driver.

2.3

Instalando o Driver JDBC do MySQL Server

O driver ocial JDBC desenvolvido para funcionar com o MySQL se chama MySQL Connector/J. necessrio fazer o download do driver na seguinte url: http://www.mysql.com/downloads/connector/j/. s descompactar o arquivo e depois incluir o jar com o driver no BUILD PATH da aplicao.

2.4

Criando uma conexo

Com o driver de conexo JDBC adicionado ao projeto, j possvel criar uma conexo com o banco de dados correspondente. Abaixo, esto os passos necessrios para criar uma conexo. Escolher o driver de conexo; Denir a localizao do banco de dados; Informar o nome da base de dados; Ter um usurio e senha cadastrados no banco de dados. As informaes sobre o driver, localizao e nome da base de dados so denidas no que chamamos de url de conexo (ou string de conexo). O usurio e a senha, informamos no momento de criar uma conexo. Para criar esta conexo, utilizamos as classes D RIVER M ANAGER (que instancia a conexo) e C ONNECTION (que armazena a nossa conexo), ambas presentes no pacote JAVA . SQL.
1 2 3 4 5 6 7 8 String urlDeConexao = "jdbc:mysql://localhost/livraria"; String usuario = "root"; String senha = ""; try { Connection conn = DriverManager.getConnection(urlDeConexao, usuario, senha); } catch (SQLException e) { e.printStackTrace(); }

www.k19.com.br

28

JDBC

2.5

Inserindo registros

Estabelecida a conexo com o banco de dados, j podemos executar comandos. Como primeiro exemplo, iremos inserir registros em uma tabela. O primeiro passo para executar um comando deni-lo em linguagem SQL.
1 2 string textoDoComando = "INSERT INTO Editora (nome, email)" + "VALUES (K19, contato@k19.com.br);";

Em seguida, devemos pedir para uma conexo JDBC atravs do mtodo PREPARE S TATE criar o comando que queremos executar. Este mtodo devolve um objeto da interface P REPARED S TATEMENT. O comando no executado na chamada do mtodo PREPARE S TA TEMENT () e sim posteriormente quando o mtodo EXECUTE () for utilizado.
MENT ()
1 2 3 4 5 // criando comando PreparedStatement comando = conexao.prepareStatement(textoDoComando); // executando o comando comando.execute(); comando.close();

Podemos utilizar a mesma conexo para executar diversos comandos. Quando no desejamos executar mais comandos, devemos fechar a conexo atravs do mtodo CLOSE (). Fechar as conexes que no so mais necessrias importante pois os SGBDs possuem um nmero limitado de conexes abertas.
1 close.close();

2.6

Exerccios

1. Crie um projeto java no eclipse chamado JDBC.

2. Crie uma pasta chamada lib no projeto JDBC.

3. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo MYSQL - CONNECTOR - JAVA -5.1.13- BIN . JAR para pasta lib do projeto JDBC.

4. Adicione o arquivo MYSQL - CONNECTOR - JAVA -5.1.1. JAR ao build path (veja gura). 29 K19 Treinamentos

JDBC

5. Crie uma nova classe, com o nome InsereEditora, e adicione o seguinte contedo ao arquivo: www.k19.com.br 30

JDBC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import import import import java.sql.Connection; java.sql.DriverManager; java.sql.PreparedStatement; java.util.Scanner;

public class InsereEditora { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria"; String usuario = "root"; String senha = "root"; Scanner entrada = new Scanner(System.in); try { System.out.println("Abrindo conexao..."); Connection conexao = DriverManager.getConnection(stringDeConexao, usuario, senha); System.out.println("Digite o nome da editora: "); String nome = entrada.nextLine(); System.out.println("Digite o email da editora: "); String email = entrada.nextLine(); String textoDoComando = "INSERT INTO Editora (nome, email) " + "VALUES (" + nome + ", " + email + ")"; PreparedStatement comando = conexao.prepareStatement(textoDoComando); System.out.println("Executando comando..."); comando.execute(); System.out.println("Fechando conexao..."); conexao.close(); } catch (Exception e) { e.printStackTrace(); } } }

Rode e veja se o registro foi inserido com sucesso na base de dados.

6. (Opcional) Analogamente, ao exerccio anterior crie um programa para inserir livros.

2.7

SQL Injection

Apesar de funcional, a implementao da insero de registros feita anteriormente apresenta uma falha grave. Os dados obtidos do usurio atravs do teclado no so tratados antes de serem enviados para o banco de dados. Esses dados podem conter algum carcter especial que altere o comportamento desejado da consulta impedindo que algum registro seja inserido corretamente ou at abrindo uma brecha para que um usurio mal intencionado execute alguma consulta SQL para utilizar de maneira inadequada os dados da nossa aplicao. 31 K19 Treinamentos

JDBC

O problema de SQL Injection pode ser resolvido manualmente. Basta fazer escape dos caracteres especiais, por exemplo: ponto-e-vrgula e apstrofo. No MySQL Server, os caracteres especiais devem ser precedidos pelo carcter \. Ento seria necessrio acrescentar \ em todas as ocorrncias de caracteres especiais nos valores passados pelo usurio. A desvantagem desse processo que, alm de trabalhoso, diferente para cada banco de dados, pois o \ no padronizado e cada banco tem o seu prprio mtodo de escape de caracteres especiais. Para tornar mais prtica a comunicao com o banco de dados, o prprio driver faz o tratamento das sentenas SQL. Esse processo denominado sanitize.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

// lendo a entrada feita pelo usuario System.out.println("Digite o nome da editora: "); String nome = entrada.nextLine(); System.out.println("Digite o email da editora: "); String email = entrada.nextLine(); // texto do comando inclui parmetros String textoDoComando = "INSERT INTO Editora (nome, email) " + "VALUES (?, ?)"; // criao e adio de parmetros ao comando PreparedStatement comando = conexao.prepareStatement(textoDoComando); comando.setString(1, nome); comando.setString(2, email);

Observe que a sentena SQL foi denida com parmetros atravs do carcter ?. Antes de executar o comando, necessrio atribuir valores aos parmetros. Isso feito com o mtodo SET S TRING , que recebe o ndice (posio) do parmetro na consulta e o valor correspondente. De maneira similar, temos os mtodos SET I NT, SET D OUBLE, SET DATE, etc, variando conforme o tipo do campo que foi denido no banco. Os mtodos acima mostrados, realizam a tarefa de sanitizar(limpar) os valores enviados pelo usurio. www.k19.com.br 32

JDBC

2.8

Exerccios

7. Tente causar um erro de SQL Injection na classe feita no exerccio de inserir editoras. (Dica: tente entradas com aspas simples) 8. Altere o cdigo para eliminar o problema do SQL Injection. Voc deve deixar a classe com o cdigo abaixo:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

public class InsereEditora { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria"; String usuario = "root"; String senha = "root"; Scanner entrada = new Scanner(System.in); try { System.out.println("Abrindo conexao..."); Connection conexao = DriverManager.getConnection(stringDeConexao, usuario, senha); System.out.println("Digite o nome da editora: "); String nome = entrada.nextLine(); System.out.println("Digite o email da editora: "); String email = entrada.nextLine(); String textoDoComando = "INSERT INTO Editora (nome, email) " + "VALUES (?, ?)"; PreparedStatement comando = conexao.prepareStatement(textoDoComando); comando.setString(1, nome); comando.setString(2, email); System.out.println("Executando comando..."); comando.execute(); System.out.println("Fechando conexao..."); conexao.close(); } catch (Exception e) { e.printStackTrace(); } } }

9. Agora tente causar novamente o problema de SQL Injection ao inserir novas editoras.

2.9

Listando registros

O processo para executar um comando de consulta bem parecido com o processo de inserir registros. 33 K19 Treinamentos

JDBC
1 2 3 4 5 6 String textoDoComando = "SELECT * FROM Editora;"; PreparedStatement comando = conexao.prepareStatement(textoDoComando); System.out.println("Executando comando..."); ResultSet resultado = comando.executeQuery();

A diferena que para executar um comando de consulta necessrio utilizar o mtodo EXECUTE Q UERY () ao invs do EXECUTE (). Esse mtodo devolve um objeto da interface JAVA . SQL .R ESULT S ET , que responsvel por armazenar os resultados da consulta. Os dados contidos no R ESULT S ET podem ser acessados atravs de mtodos, como o GET STRING , GET I NT , GET D OUBLE, etc, de acordo com o tipo do campo. Esses mtodos recebem como parmetro uma string referente ao nome da coluna correspondente.
1 2 3 int id = resultado.getInt("id"), String nome = resultado.getString("nome"), String email = resultado.getString("email");

O cdigo acima mostra como os campos do primeiro registro da consulta so recuperados. Agora, para recuperar os outros registros necessrio avanar o R ESULT S ET atravs do mtodo NEXT .
1 2 3 4 5 6 7 8 9 int id1 = resultado.getInt("id"), String nome1 = resultado.getString("nome"), String email1 = resultado.getString("email"); resultado.next(); int id2 = resultado.getInt("id"), String nome2 = resultado.getString("nome"), String email2 = resultado.getString("email");

O prprio mtodo NEXT devolve um valor booleano para indicar se o R ESULT S ET conseguiu avanar para o prximo registro. Quando esse mtodo devolver FALSE signica que no h mais registros para serem consultados.
1 2 3 4 5 while(resultado.next()) { int id = resultado.getInt("id"), String nome = resultado.getString("nome"), String email = resultado.getString("email"); }

2.10

Exerccios

10. Insira algumas editoras utilizando a classe I NSERE E DITORA que voc criou nos exerccios acima. 11. Adicione uma nova classe ao projeto chamada ListaEditoras. O objetivo listar as editoras que foram salvas no banco. Adicione o seguinte cdigo esta classe. www.k19.com.br 34

JDBC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import import import import java.sql.Connection; java.sql.DriverManager; java.sql.PreparedStatement; java.sql.ResultSet;

public class ListaEditoras { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria"; String usuario = "root"; String senha = "root"; try { System.out.println("Abrindo conexao..."); Connection conexao = DriverManager.getConnection(stringDeConexao, usuario, senha); String textoDoComando = "SELECT * FROM Editora;"; PreparedStatement comando = conexao.prepareStatement(textoDoComando); System.out.println("Executando comando..."); ResultSet resultado = comando.executeQuery(); System.out.println("Resultados encontrados: \n"); while (resultado.next()) { System.out.printf("%d : %s - %s\n", resultado.getInt("id"), resultado.getString("nome"), resultado.getString("email")); } System.out.println("\nFechando conexao..."); conexao.close(); } catch (Exception e) { e.printStackTrace(); } } }

2.11

Fbrica de conexes (Factory)

Voc deve ter percebido que em diversos pontos diferentes da nossa aplicao precisamos de uma conexo JDBC. Se a url de conexo for denida em cada um desses pontos teremos um problema de manuteno. Imagine que o driver do banco seja atualizado ou que o ip do SGBD seja alterado. Teramos que alterar o cdigo da nossa aplicao em muitos lugares, mais precisamente, em cada ocorrncia da url de conexo. A probabilidade de algum ponto no ser corrigido grande. Para diminuir o trabalho de manuteno, ns poderamos criar uma classe responsvel pela criao e distribuio de conexes. Nessa e somente nessa classe estaria denida a url de conexo. Dessa forma, qualquer alterao no modo em que nos conectamos base de dados, s acarreta mudanas nesta classe. 35 K19 Treinamentos

JDBC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class FabricaDeConexao { public static Connection criaConexao() { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria"; String usuario = "root"; String senha = "root"; Connection conexao = null; try { conexao = DriverManager.getConnection(stringDeConexao, usuario, senha); } catch (SQLException e) { e.printStackTrace(); } return conexao; } }

Agora podemos obter uma nova conexo apenas chamando FABRICA D E C ONEXAO .C RIAC ONEXAO (). O resto do sistema no precisa mais conhecer os detalhes sobre a criao das conexes com o banco de dados, diminuindo o acoplamento da aplicao.

2.12

Exerccios

12. Adicione uma nova classe chamada FABRICA D E C ONEXAO e adicione o seguinte cdigo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class FabricaDeConexao { public static Connection CriaConexao() { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria"; String usuario = "root"; String senha = "root"; Connection conexao = null; try { conexao = DriverManager.getConnection(stringDeConexao, usuario, senha); } catch (SQLException e) { e.printStackTrace(); } return conexao; } }

13. Altere as classes I NSERE E DITORA e L ISTA E DITORAS para que elas utilizem a fbrica de conexo. Execute-as novamente. 14. (Opcional) Implemente um teste que remove uma editora pelo id. 15. (Opcional) Implemente um teste que altera os dados de uma editora pelo id.

www.k19.com.br

36

Captulo 3 JPA 2 e Hibernate


3.1 Mltiplas sintaxes da linguagem SQL

No captulo anterior, voc aprendeu a utilizar a especicao JDBC para fazer uma aplicao Java interagir com um banco de dados. Essa interao realizada atravs de consultas escritas em SQL. Uma desvantagem dessa abordagem, que a sintaxe da linguagem SQL, apesar de parecida, pode variar conforme o banco de dados que est sendo utilizado. Desse modo, os desenvolvedores teriam que aprender as diferenas entres as sintaxes do SQL correspondentes aos banco de dados que ele utilizar. Seria bom se, ao invs de programar direcionado a um determinado banco de dados, pudssemos programar de uma maneira mais genrica, voltado uma interface ou especicao, assim poderamos escrever o cdigo independente de SQL.

3.2

Orientao a Objetos VS Modelo Entidade Relacionamento

Outro problema na comunicao entre uma aplicao Java e um banco de dados o conito de paradigmas. O banco de dados organizado seguindo o modelo entidade relacionamento, enquanto as aplicaes Java, geralmente, utilizam o paradigma orientado a objetos. A transio de dados entre o modelo entidade relacionamento e o modelo orientado a objetos no simples. Para realizar essa transio, necessrio denir um mapeamento entre os conceitos desses dois paradigmas. Por exemplo, classes podem ser mapeadas para tabelas, objetos para registros, atributos para campos e referncia entre objetos para chaves estrangeiras.

3.3

Ferramentas ORM

Para facilitar a comunicao entre aplicaes Java que seguem o modelo orientado a objetos e os banco de dados que seguem o modelo entidade relacionamento, podemos utilizar ferramentas que automatizam a transio de dados entre as aplicaes e os diferente bancos de dados e que so conhecidas como ferramentas de ORM (Object Relational Mapper). Outra consequncia, ao utilizar uma ferramenta de ORM, que no necessrio escrever consultas em SQL, pois a prpria ferramenta gera as consultas de acordo com a sintaxe da 37

JPA 2 e Hibernate linguagem SQL correspondente ao banco que est sendo utilizado. A principal ferramenta ORM para Java utilizada no mercado de TI o Hibernate. Mas, existem outras que possuem o mesmo objetivo.

3.4

O que JPA e Hibernate

Aps o sucesso do Hibernate, a especicao JPA (Java Persistence API) foi criada com o objetivo de padronizar as ferramentas ORM para aplicaes Java e consequentemente diminuir a complexidade do desenvolvimento. Atualmente, essa especicao est na sua segunda verso. Ela especca um conjunto de classes e mtodos que as ferramentas de ORM devem implementar. Veja que a JPA apenas uma especicao, ela no implementa nenhum cdigo. Para isso, utilizamos alguma das diversas implementaes da JPA. Neste curso, utilizaremos o Hibernate como implementao de JPA. As outras implementaes de JPA mais conhecidas so: TopLink, EclipseLink e OpenJPA. Optamos por utilizar o Hibernate por ele ser o mais antigo e mais utilizado atualmente. Caso voc queira utilizar outro framework ORM, poder aplicar os conceitos aqui aprendidos justamente por que eles seguem a mesma especicao. Assim podemos programar voltado especicao e substituir uma implementao pela outra, sem precisar reescrever o cdigo da nossa aplicao. Claro que teramos que alterar alguns arquivos de congurao, mas o cdigo da aplicao permaneceria o mesmo.

3.5

Congurao

Antes de comear a utilizar o Hibernate, necessrio baixar no site ocial o bundle que inclui os jars do hibernate e todas as suas dependncias. Neste curso, utilizaremos a verso 3.5.1. A url do site ocial do Hibernate esta: (http://www.hibernate.org/) Para congurar o Hibernate em uma aplicao, devemos criar um arquivo chamado persistence.xml. O contedo desse arquivo possura informaes sobre o banco de dados, como a url de conexo, usurio e senha. Alm de dados sobre a implementao de JPA que ser utilizada. O arquivo PERSISTENCE . XML deve estar em uma pasta chamada META-INF, que deve estar no classpath da aplicao. Veja abaixo um exemplo de congurao para o PERSIS TENCE . XML : www.k19.com.br 38

JPA 2 e Hibernate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="K19" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect. MySQL5InnoDBDialect"/> <property name="hibernate.hbm2ddl.auto" value="create"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver "/> <property name="javax.persistence.jdbc.user" value="usuario"/> <property name="javax.persistence.jdbc.password" value="senha"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql:// localhost:3306/k19"/> </properties> </persistence-unit> </persistence>

A propriedade hibernate.dialect permite que a aplicao escolha qual sintaxe de SQL que deve ser utilizada pelo Hibernate.

3.6

Mapeamento

Um dos principais objetivos dos frameworks ORM estabelecer o mapeamento entre os conceitos do modelo orientado a objetos e os conceitos do modelo entidade relacionamento. Este mapeamento pode ser denido atravs de xml ou de maneira mais prtica com anotaes Java. Quando utilizamos anotaes, evitamos a criao de extensos arquivos em xml. A seguir veremos as principais anotaes Java de mapeamento do JPA. Essas anotaes esto no pacote javax.persistence. @Entity a principal anotao do JPA. Ela que deve aparecer antes do nome de uma classe. E deve ser denida em todas as classes que tero objetos persistidos no banco de dados. As classes anotadas com @E NTITY so mapeadas para tabelas. Por conveno, as tabelas possuem os mesmos nomes das classes. Mas, podemos alterar esse comportamento utilizando a anotao @TABLE. Os atributos declarados em uma classe anotada com @E NTITY so mapeados para colunas na tabela correspondente classe. Outra vez, por conveno, as colunas possuem os mesmos nomes dos atributos. E novamente, podemos alterar esse padro utilizando a anotao @C OLUMN. @Id Utilizada para indicar qual atributo de uma classe anotada com @E NTITY ser mapeado para a chave primria da tabela correspondente classe. Geralmente o atributo anotado com @I D do tipo L ONG. @GeneratedValue Geralmente vem acompanhado da anotao @I D. Serve para indicar que o atributo gerado pelo banco, no momento em que um novo registro inserido. 39 K19 Treinamentos

JPA 2 e Hibernate @Table Utilizada para alterar o nome padro da tabela. Ela recebe o parmetro name para indicar qual nome que deve ser utilizado na tabela. Veja o exemplo:
1 2 3 4 @Table(name="Publisher") @Entity public class Editora { // ...

@Column Utilizado para alterar o nome da coluna que ser utilizado na tabela. Caso voc esteja utilizando um banco de dados legado, no qual os nomes das colunas j foram denidos, voc pode mudar atravs dessa anotao. Alm disso, podemos estabelecer certas restries, como determinar se o campo pode ou no ser nulo.
1 2 3 4 @Entity public class Editora { @Column(name="publisher_name",nullable=false) private String nome;

@Transient Serve para indicar um atributo que no deve ser persistido, ou seja, os atributos anotados com @T RANSIENT no so mapeados para colunas. @Lob Utilizado para atributos que armazenam textos muito grandes, ou arquivos binrios contendo imagens ou sons que sero persistidos no banco de dados. O tipo do atributo deve ser S TRING, B YTE [], BYTE [] ou JAVA . SQL .B LOB. @Temporal Utilizado para atributos do tipo C ALENDAR ou DATE. Por padro, tanto data quanto hora so armazenados no banco de dados. Mas, com a anotao @T EMPORAL, podemos mandar persistir somente a data ou sement a hora.
1 2 3 4 5 @Entity public class Livro { @Temporal(TemporalType.DATE) private Calendar publicacao; // ...

3.7

Gerando o banco

Uma das vantagens de utilizar o Hibernate, que ele capaz de gerar as tabelas do banco para a nossa aplicao. Ele faz isso de acordo com as anotaes colocadas nas classes e as informaes presentes no PERSISTENCE . XML. As tabelas so geradas atravs de mtodo da classe P ERSISTENCE, o CREATE E NTITY M A NAGER FACTORY ( STRING ENTITY U NIT ). O parmetro ENTITY U NIT permite escolher, pelo nome, uma unidade de persistncia denida no PERSISTENCE . XML. A poltica de criao das tabelas pode ser alterada congurando a propriedade HIBER NATE . HBM 2 DDL . AUTO no arquivo PERSISTENCE . XML . Podemos, por exemplo, fazer com www.k19.com.br 40

JPA 2 e Hibernate que o Hibernate sempre sobrescreva as tabelas existentes, basta congurar a propriedade BERNATE . HBM 2 DDL . AUTO com o valor CREATE - DROP .
1 <property name="hibernate.hbm2ddl.auto" value="create-drop"/>

HI -

Uma outra opo, congurar o Hibernate para simplesmente atualizar as tabelas de acordo com as mudanas nas anotaes sem remov-las. Nesse caso, o valor da propriedade HIBER NATE . HBM 2 DDL . AUTO deve ser UPDATE .
1 <property name="hibernate.hbm2ddl.auto" value="update"/>

3.8

Exerccios

1. Crie um projeto no eclipse chamado JPA2-Hibernate e feche o projeto JDBC para no gerar confuso na hora de manipular os arquivos. 2. Crie uma pasta chamada lib dentro do projeto JPA2-Hibernate. 3. Entre na pasta K19-Arquivos/Hibernate da rea de Trabalho e copie os jars do Hibernate para a pasta lib do projeto JPA2-Hibernate. 4. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo MYSQL - CONNECTOR - JAVA -5.1.13. BIN . JAR para pasta lib do projeto JPA2Hibernate. 5. Entre na pasta K19-Arquivos/SLF4J da rea de Trabalho e copie os jars para pasta lib do projeto JPA2-Hibernate. 6. Entre na pasta K19-Arquivos/Log4J da rea de Trabalho e copie o arquivo 1.2.16. JAR para pasta lib do projeto JPA2-Hibernate. 7. Adicione os jars da pasta lib ao build path do projeto JPA2-Hibernate. 8. Crie uma pasta chamada META-INF na pasta src no projeto JPA2-Hibernate. 9. Crie o arquivo de conguraes persistence.xml na pasta META-INF. 41 K19 Treinamentos
LOG 4 J -

JPA 2 e Hibernate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="livraria" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect. MySQL5InnoDBDialect"/> <property name="hibernate.hbm2ddl.auto" value="create"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver "/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="root"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql:// localhost:3306/livraria"/> </properties> </persistence-unit> </persistence>

10. Crie uma classe para modelar as editoras da nossa livraria e acrescente as anotaes necessrias para fazer o mapeamento. Obs: As anotaes devem ser importadas do pacote JAVAX . PERSISTENCE .
1 2 3 4 5 6 7 8 9 10 11 @Entity public class Editora { @Id @GeneratedValue private Long id; private String nome; private String email; // GETTERS AND SETTERS }

11. Apague a tabela Livro e depois a Editora. 12. Congure o Log4J criando um arquivo chamado log4j.properties na pasta src do projeto JPA2-Hibernate.

log4j.rootCategory=INFO, CONSOLE log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%r [%t] %-5p %c - %m%n

13. Gere as tabelas atravs da classe P ERSISTENCE. Para isso, crie uma classe com mtodo MAIN . Obs: As classes devem ser importadas do pacote JAVAX . PERSISTENCE . www.k19.com.br 42

JPA 2 e Hibernate
1 2 3 4 5 6 7 8 public class GeraTabelas { public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("livraria"); factory.close() } }

Atravs do MySQL Query Browser verique se a tabela E DITORA foi criada corretamente.

3.9

Manipulando entidades

Para manipular as entidades da nossa aplicao, devemos utilizar um E NTITY M ANAGER que obtido atravs de uma E NTITY M ANAGER FACTORY.
1 2 3 4 EntityManagerFactory factory = Persistence.createEntityManagerFactory("K19"); EntityManager manager = factory.createEntityManager();

3.9.1

Persistindo

Para armazenar as informaes de um objeto no banco de dados basta utilizar o mtodo PERSIST () do E NTITY M ANAGER .
1 2 3 4 5 Editora novaEditora = new Editora(); novaEditora.setNome("K19 - Livros") novaEditora.setEmail("contato@k19.com.br"); manager.persist(novaEditora);

3.9.2
FIND ()
1 2

Buscando

Para obter um objeto que contenha informaes do banco de dados basta utilizar o mtodo ou o GET R EFERENCE () do E NTITY M ANAGER.

Editora editora1 = manager.find(Editora.class, 1L); Editora editora2 = manager.getReference(Editora.class, 2L);

A diferena entre os dois mtodos bsicos de busca FIND () e GET R EFERENCE () que o primeiro recupera os dados desejados imediatamente j o segundo posterga at a primeira chamada de um mtodo GET do objeto. 43 K19 Treinamentos

JPA 2 e Hibernate

3.9.3

Removendo
REMOVE ()

Para remover um registro correspondente a um objeto basta utilizar o mtodo do E NTITY M ANAGER.
1 2 Editora editora1 = manager.find(Editora.class, 1L); manager.remove(editora1);

3.9.4

Atualizando

Para alterar os dados de um registro correspondente a um objeto basta utilizar os prprios mtodos setters desse objeto.
1 2 Editora editora1 = manager.find(Editora.class, 1L); editora.setNome("K19 - Livros e Publicaes");

3.9.5

Listando

Para obter uma listagem com todos os objetos referentes aos registros de uma tabela, devemos utilizar a linguagem de consulta do JPA, a JPQL que muito parecida com a linguagem SQL. A vantagem do JPQL em relao ao SQL que a sintaxe a mesma para bancos de dados diferentes.
1 2 Query query = manager.createQuery("SELECT e FROM Editora e"); List<Editora> editoras = query.getResultList();

3.9.6

Transaes

As modicaes realizadas nos objetos administrados por um E NTITY M ANAGER so mantidas em memria. Em certos momentos, necessrio sincronizar os dados da memria com os dados do banco de dados. Essa sincronizao deve ser realizada atravs de uma transao JPA criada pelo E NTITY M ANAGER que administra os objetos que desejamos sincronizar. Para abrir uma transao utilizamos o mtodo BEGIN ().
1 manager.getTransaction().begin();

FLUSH ()
1 2 3 4 5

Com a transao aberta podemos sincronizar os dados com o banco atravs do mtodo ou COMMIT ().

Editora editora1 = manager.find(Editora.class, 1L); editora.setNome("K19 - Livros e Publicaes"); manager.getTransaction().begin(); manager.flush();

www.k19.com.br

44

JPA 2 e Hibernate
1 2 3 4 5 Editora editora1 = manager.find(Editora.class, 1L); editora.setNome("K19 - Livros e Publicaes"); manager.getTransaction().begin(); manager.getTransaction().commit();

3.10

Exerccios

14. No arquivo de conguraes PERSISTENCE . XML, altere o valor da propriedade HIBER NATE . HBM 2 DDL . AUTO para UPDATE . Assim as tabelas no sero recriadas a cada execuo e sim apenas atualizadas.

15. Crie um teste para inserir editoras no banco de dados.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

public class InsereEditoraComJPA { public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("livraria"); EntityManager manager = factory.createEntityManager(); Editora novaEditora = new Editora(); Scanner entrada = new Scanner(System.in); System.out.println("Digite o nome da editora: "); novaEditora.setNome(entrada.nextLine()); System.out.println("Digite o email da editora: "); novaEditora.setEmail(entrada.nextLine()); manager.persist(novaEditora); manager.getTransaction().begin(); manager.getTransaction().commit(); factory.close(); } }

16. Crie um teste para listar as editoras inseridas no banco de dados. 45 K19 Treinamentos

JPA 2 e Hibernate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ListaEditorasComJPA { public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("livraria"); EntityManager manager = factory.createEntityManager(); Query query = manager.createQuery("SELECT e FROM Editora e"); List<Editora> editoras = query.getResultList(); for(Editora e : editoras) { System.out.println("EDITORA: " + e.getNome() + " - " + e.getEmail()); } } }

3.11

Repository

A interface E NTITY M ANAGER do JPA oferece recursos sucientes para que os objetos do domnio sejam recuperados ou persistidos no banco de dados. Porm, em aplicaes com alta complexidade e grande quantidade de cdigo, espalhar as chamadas aos mtodos do E NTITY M ANAGER pode gerar diculdades na manuteno e no entendimento do sistema. Para melhorar a organizao das nossas aplicaes, diminuindo o custo de manuteno e aumentando a legibilidade do cdigo, podemos aplicar o padro Repository do DDD(Domain Driven Design). Conceitualmente, um repositrio representa o conjunto de todos os objetos de um determinado tipo. Ele deve oferecer mtodos para recuperar e para adicionar elementos. Os repositrios podem trabalhar com objetos prontos na memria ou reconstru-los com dados obtidos de um banco de dados. O acesso ao banco de dados pode ser realizado atravs de ferramenta ORM como o Hibernate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class EditoraRepository { private EntityManager manager; public EditoraRepository(EntityManager manager) { this.manager = manager; } public void adiciona(Editora e) { this.manager.persist(e); } public Editora busca(Long id) { return this.manager.find(Editora.class, id); } public List<Editora> buscaTodas() { Query query = this.manager.createQuery("SELECT e FROM Editora e"); return query.getResultList(); } }

www.k19.com.br

46

JPA 2 e Hibernate
1 2 3 4 5 6 7 EntityManagerFactory factory = Persistence.createEntityManagerFactory("K12");

EntityManager manager = factory.createEntityManager(); EditoraRepository editoraRepository = new EditoraRepository(manager); List<Editora> editoras = editoraRepository.buscaTodas();

3.12

Exerccios

17. Implemente um repositrio de editoras criando uma nova classe no projeto JPA2-Hibernate.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

class EditoraRepository { private EntityManager manager; public EditoraRepository(EntityManager manager) { this.manager = manager; } public void adiciona(Editora e) { this.manager.persist(e); } public Editora busca(Long id) { this.manager.find(Editora.class, id); } public List<Editora> buscaTodas() { Query query = this.manager.createQuery("SELECT e FROM Editora e"); return query.getResultList(); } }

18. Altere a classe InsereEditoraComJPA para que ela utilize o repositrio de editoras. 47 K19 Treinamentos

JPA 2 e Hibernate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class InsereEditoraComJPA { public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("livraria"); EntityManager manager = factory.createEntityManager(); EditoraRepository editoraRepository = new EditoraRepository(manager); Editora novaEditora = new Editora(); Scanner entrada = new Scanner(System.in); System.out.println("Digite o nome da editora: "); novaEditora.setNome(entrada.nextLine()); System.out.println("Digite o email da editora: "); novaEditora.setEmail(entrada.nextLine()); editoraRepository.adiciona(novaEditora); manager.getTransaction().begin(); manager.getTransaction().commit(); factory.close(); } }

19. (Opcional) Altere a classe ListaEditorasComJPA para que ela utilize o repositrio de editoras.

www.k19.com.br

48

Captulo 4 Web Container


4.1 Necessidades de uma aplicao web

As aplicaes web so acessadas pelos navegadores (browsers). A comunicao entre os navegadores e as aplicaes web realizada atravs de requisies e respostas denidas pelo protocolo HTTP. Portando, ao desenvolver uma aplicao web, devemos estar preparados para receber requisies HTTP e enviar respostas HTTP. Alm disso, na grande maioria dos casos, as aplicaes web devem ser acessadas por diversos usurios simultaneamente. Dessa forma, o desenvolvedor web precisa saber como permitir o acesso simultneo. Outra necessidade das aplicaes web gerar contedo dinmico. Por exemplo, quando um usurio de uma aplicao de email acessa a sua caixa de entrada, ele deseja ver a listagem atualizada dos seus emails. Portanto, fundamental que a listagem dos emails seja gerada no momento da requisio do usurio. O desenvolvedor web precisa utilizar algum mecanismo eciente que permita que o contedo que os usurios requisitam seja gerado dinamicamente. Trabalhar diretamente com as requisies e repostas HTTP e criar um mecanismo eciente para permitir o acesso simultneo e para gerar contedo dinmico no so tarefas simples. Na verdade, extremamente trabalhoso implementar essas caractersticas. Por isso, a plataforma Java oferece uma soluo para diminuir o trabalho no desenvolvimento de aplicaes web.

4.2

Web Container

Uma aplicao web Java deve ser implantada em um Web Container para obter os recursos fundamentais que as aplicaes web necessitam. Um Web Container responsvel pelo envio e recebimento de mensagens HTTP, permite que as aplicaes implantadas nele sejam acessadas simultaneamente por mltiplos usurios de uma maneira eciente e oferece mecanismos para que as aplicaes gerem contedo dinamicamente. Os dois Web Containers mais importantes do mercado so: Tomcat e Jetty. Tambm podemos utilizar um servidor de aplicao Java EE como o JBoss, Glasssh ou WebSphere pois eles possuem um Web Container internamente. 49

Web Container

4.3

Especicao Java EE

Como comum na plataforma Java, para padronizar a interface dos recursos oferecidos pelos Web Containers, especicaes foram denidas. Essas especicaes fazem parte do conjunto de especicaes do Java EE. O Java EE uma especicao que agrupa diversas outras especicaes. Apesar das especicaes, os Web Containers possuem algumas diferenas nas conguraes que devem ser realizadas pelos desenvolvedores. Dessa forma, no h 100% portabilidade entre os Web Containers. Contudo, a maior parte das conguraes e do modelo de programao padronizado. Sendo assim, se voc conhece bem um dos Web Container tambm conhece bastante dos outros.

4.4

Exerccios

1. Na rea de Trabalho, entre na pasta K19-Arquivos e copie glasssh-3.0.1-with-hibernate.zip para o seu Desktop. Descompacte este arquivo na prpria rea de Trabalho. 2. Ainda na rea de Trabalho, entre na pasta glassshv3/glasssh/bin e execute o script startserv para executar o glasssh. 3. Verique se o glasssh est executando atravs de um navegador acessando a url: http://localhost:8080. 4. Pare o glasssh executando o script stopserv que est na mesma pasta do script startserv. 5. No eclipse, abra a view servers e clique com o boto direito no corpo dela. Escolha a opo new e congure o glasssh. 6. Execute o glasssh pela view servers e verique se ele est funcionando acessando atravs de um navegador a url: http://localhost:8080. 7. Pare o glasssh pela view servers.

4.5

Aplicao Web Java

Para que uma aplicao Web Java possa ser implantada em um Web Container, a estrutura de pastas precisa seguir algumas regras. K19-App/ pasta raiz pode ter qualquer nome WEB-INF/ classes/ lib/ web.xml www.k19.com.br 50

Web Container A pasta K19-App raiz da nossa aplicao, o nome dessa pasta pode ser denido pelo desenvolvedor. A pasta WEB-INF deve ser criada dentro da pasta raiz de todas as aplicaes Web Java, o contedo dessa pasta no pode ser acessado diretamente pelos usurios. A pasta classes deve ser criada dentro da pasta WEB-INF, o cdigo compilado das aplicaes Web Java deve ser salvo nessa pasta. A pasta lib deve ser criada dentro da pasta WEB-INF, todos os jars das bibliotecas que sero utilizadas devem ser colocados nessa pasta. O arquivo web.xml contm conguraes do Web Container e deve ser criado na pasta WEB-INF. Os arquivos dentro da pasta raiz da aplicao mas fora da pasta WEB-INF podem ser acessados diretamente pelos usurios atravs de um navegador. As IDEs j criam toda a estrutura de pastas exigidas pelos Web Containers. Ento, na prtica, no temos o trabalho de criar esses diretrios manualmente.

4.6

Exerccios

8. Crie um projeto no eclipse do tipo Dynamic Web Project chamado App-Web-Java selecionando na ltima tela a opo Generate web.xml deployment descriptor. 9. Execute o projeto no glasssh clicando com o boto direito no nome do projeto e escolhendo a opo Run on Server dentro de Run As. 10. Verique o funcionamento da nossa aplicao acessando a url: http://localhost:8080/K19-App/ atravs de um navegador.

4.7

Processando requisies

Aps implantar a nossa aplicao web Java em um Web Container, as requisies e respostas HTTP j esto sendo processadas pelo Web Container que tambm j permite o acesso de mltiplos usurios nossa aplicao. Em seguida devemos denir como o contedo da nossa aplicao deve ser gerado. H duas maneiras fundamentais de gerar contedo dinmico: programando uma Servlet ou um JSP. Na verdade, os JSPs so traduzidos para Servlets automaticamente pelos Web Containers. Ento, escrever um JSP apenas uma maneira diferente de escrever uma Servlet.

4.8

Servlet

Para criar uma Servlet, podemos seguir os seguintes passos bsicos: 1. Criar uma classe 2. Herdar da classe javax.servlet.http.HttpServlet. 3. Reescrever o mtodo service 4. Utilizar a anotao @WebServlet para denir a url que ser utilizada para acessar a Servlet. Essa anotao existe aps a especicao de Servlet 3.0. Antes essa congurao era realizada atravs do arquivo web.xml. 51 K19 Treinamentos

Web Container
1 2 3 4 5 6 7 8 9 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Lgica para processar as regras de negcio e gerar contedo } }

Quando um usurio zer uma requisio para url denida atravs da anotao @W EB S ER VLET, o mtodo service() ser executado. Esse mtodo recebe dois parmetros: o primeiro uma referncia para um objeto da classe HttpServletRequest que guarda todos os dados da requisio HTTP realizada pelo navegador do usurio; o segundo uma referncia para um objeto da classe HttpServletResponse que permite que a resposta HTTP que ser enviada para o navegador do usurio seja construda pela aplicao.

4.8.1

Inserindo contedo na resposta

Para inserir contedo na resposta HTTP que ser enviada para o navegador do usurio, devemos utilizar o mtodo getWriter(). Em geral, o contedo inserido na resposta HTTP texto HTML.
1 2 3 4 5 6 7 8 9 10 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("<html><body><h1>Ol Mundo</h1></body></html>"); } }

4.9

Exerccios

11. Crie um pacote chamado servlets no projeto K19-App. 12. Crie uma classe chamada OlaMundo no pacote servlets da seguinte forma:
1 2 3 4 5 6 7 8 9 10 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.println("<html><body><h1>Ol Mundo</h1></body></html>"); } }

www.k19.com.br

52

Web Container 13. Verique o funcionamento da Servlet acessando atravs de um navegador a url: http://localhost:8080/K19-App/OlaMundo

4.10

JSP

Outra maneira de criar uma Servlet escrever um JSP. Lembrando que os JSPs so traduzidos para Servlets automaticamente pelos Web Containers. Para criar um JSP basta adicionar um arquivo .jsp.
1 2 3 4 5 6 7 8 9 <!-- olaMundo.jsp --> <html> <body> <!-- scriptlet --> <% java.util.Random geradorDeNumeros = new java.util.Random(); %> <!-- expression --> <%= geradorDeNumeros.nextInt(100) %> </body> </html>

Um arquivo JSP pode conter texto HTML e cdigo Java. O cdigo Java pode aparecer em diversos lugares. Por exemplo, dentro de scriptlets ou expressions.

4.11

Exerccios

14. Crie um arquivo JSP chamado olaMundo.jsp na pasta WebContent com o seguinte contedo.
1 2 3 4 5 6 7 8 9 <!-- olaMundo.jsp --> <html> <body> <!-- scriptlet --> <% java.util.Random geradorDeNumeros = new java.util.Random(); %> <!-- expression --> <%= geradorDeNumeros.nextInt(100) %> </body> </html>

15. Verique o funcionamento do JSP acessando atravs de um navegador a url: http://localhost:8080/K19-App/olaMundo.jsp

4.12

Frameworks

Hoje em dia, improvvel que uma empresa decida comear um projeto utilizando diretamente Servlets e JSPs pois a produtividade pequena e a manuteno difcil. Por isso bibliotecas que denem um modelo de programao baseado no padro MVC so utilizadas nos projetos. Essas bibliotecas so os chamados Frameworks web. Eis uma lista dos principais Frameworks web para aplicaes web Java: 53 K19 Treinamentos

Web Container JSF Struts 1.x Struts 2.x Spring MVC Nos prximos captulos mostraremos o funcionamento e explicaremos os conceitos relacionados ao framework JSF.

www.k19.com.br

54

Captulo 5 Viso Geral do JSF 2


O JSF 2 oferece muitos recursos para o desenvolvimento de uma aplicao web Java. Cada um desses recursos por si s j so sucientemente grandes e podem ser abordados em separado. Porm, no primeiro contato com JSF 2, interessante ter uma viso geral dos recursos principais e do relacionamento entre eles sem se aprofundar em muito nos detalhes individuais de cada recurso. Portanto, neste captulo, mostraremos de forma sucinta e direta o funcionamento e os conceitos principais do JSF 2. Nos prximos captulos, discutiremos de maneira mais detalhada as diversas partes do JSF 2.

5.1

Aplicao de exemplo

Inspirados na sorte de um dos nossos alunos que ganhou na Loto Mania utilizando um programa que ele fez baseado em algumas dicas que o instrutor Rafael Cosentino deu a ele para gerar nmeros aleatrios em Java, vamos montar uma pequena aplicao em JSF 2 que gera apostas de loteria.

5.2

Managed Beans

Os Managed Beans so objetos utilizados nas aplicaes JSF e possuem trs responsabilidades principais: 1. Receber os dados enviados pelos usurios atravs das telas da aplicao. 2. Executar as lgicas para tratar as requisies dos usurios. 3. Disponibilizar os dados que devem ser apresentados nas telas da aplicao. Para denir o funcionamento de um Managed Bean no JSF 2, devemos seguir os seguintes passos: 1. Criar uma classe com a anotao @ManagedBean. 55

Viso Geral do JSF 2 2. Denir atributos com os correspondentes getters e setters para poder receber dados das telas ou enviar dados para as telas. 3. Denir mtodos para implementar as lgicas de tratamento das possveis requisies dos usurios.

5.2.1

GeradorDeApostasBean

Na aplicao que gera apostas de loteria, devemos criar um Managed Bean para receber alguns parmetros que devem ser denidos pelos usurios para gerar as apostas corretamente.
1 2 3 4 5 6 7 8 9 10 @ManagedBean public class GeradorDeApostasBean { private int quantidadeDeNumeros; private int tamanhoDaAposta; private int quantidadeDeApostas; // getters e setters }

Devemos acrescentar no G ERADOR D E A POSTAS B EAN um mtodo para implementar a lgica de gerar as apostas. Este mtodo deve devolver no nal o nome da tela que apresentar as apostas geradas para os usurios.
1 2 3 4 public String geraApostas() { // Aqui deve ser implementa a lgica para gerar as apostas return "lista-de-apostas"; }

Por m, devemos adicionar um atributo no G ERADOR D E A POSTAS B EAN para disponibilizar as apostas geradas para a tela que ir apresent-las aos usurios.
1 2 3 private List<List<Integer>> apostas; // getters e setters

5.3

Facelets e Componentes Visuais

As telas das aplicaes JSF 2 podem ser denidas atravs de arquivos xhtml. Esses arquivos so processados pela engine do Facelets que faz parte do JSF 2. Os componentes visuais que formam as telas da aplicao so inseridos atravs de tags xhtml.

5.3.1

Tela de entrada

Na nossa aplicao de gerar apostas, devemos denir uma tela para os usurios passarem os parmetros necessrios para que as apostas sejam geradas. www.k19.com.br 56

Viso Geral do JSF 2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

<!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"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <h:form> <h:panelGrid> <h:outputLabel value="Quantidade total de nmeros:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeNumeros}"/> <h:outputLabel value="Quantidade de nmeros por aposta:"/> <h:inputText value="#{geradorDeApostasBean.tamanhoDaAposta}"/> <h:outputLabel value="Quantidade de apostas:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeApostas}"/> <h:commandButton action="#{geradorDeApostasBean.geraApostas}" value="Gerar"/> </h:panelGrid> </h:form> </h:body> </html>

5.3.2

Tela de Sada

Na tela de sada, devemos apresentar aos usurios uma listagem das apostas que foram criadas pelo G ERADOR D E A POSTAS B EAN. 57 K19 Treinamentos

Viso Geral do JSF 2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

<!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:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <ui:repeat var="aposta" value="#{geradorDeApostasBean.apostas}" varStatus="status"> <h:outputText value="Aposta #{status.index + 1}: "/> <h:outputText value="#{aposta}"/> <br/> </ui:repeat> </h:body> </html>

5.4

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado K19-Loteria. Siga as imagens abaixo para congurar corretamente o projeto. www.k19.com.br 58

Viso Geral do JSF 2

59

K19 Treinamentos

Viso Geral do JSF 2

www.k19.com.br

60

Viso Geral do JSF 2 2. Na pasta src do projeto K19-Loteria crie um pacote chamado managedbeans.

3. No pacote managedbeans crie uma classe chamada GeradorDeApostasBean com o seguinte contedo.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

@ManagedBean public class GeradorDeApostasBean { private int quantidadeDeNumeros; private int tamanhoDaAposta; private int quantidadeDeApostas; private List<List<Integer>> apostas; public String geraApostas() { // Prepara uma lista com todos os nmeros ArrayList<Integer> numeros = new ArrayList<Integer>(); for (int j = 1; j <= this.quantidadeDeNumeros; j++) { numeros.add(j); } // Cria uma sublista da lista de nmeros List<Integer> subList = numeros.subList(0, this.tamanhoDaAposta); // Lista de apostas vazia this.apostas = new ArrayList<List<Integer>>(); // Gera as apostas for (int i = 0; i < this.quantidadeDeApostas; i++) { Collections.shuffle(numeros); List<Integer> aposta = new ArrayList<Integer>(subList); this.apostas.add(aposta); } return "lista-de-apostas"; } // GETTERS AND SETTERS }

4. Na pasta WebContent, crie um arquivo chamado formulario.xhtml e monte a tela de entrada do gerador de apostas. 61 K19 Treinamentos

Viso Geral do JSF 2


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <!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"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <h:form> <h:panelGrid> <h:outputLabel value="Quantidade total de nmeros:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeNumeros}"/> <h:outputLabel value="Quantidade de nmeros por aposta:"/> <h:inputText value="#{geradorDeApostasBean.tamanhoDaAposta}"/> <h:outputLabel value="Quantidade de apostas:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeApostas}"/> <h:commandButton action="#{geradorDeApostasBean.geraApostas}" value="Gerar"/> </h:panelGrid> </h:form> </h:body> </html>

5. Na pasta WebContent, crie um arquivo chamado lista-de-apostas.xhtml para apresentar as apostas geradas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!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:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <ui:repeat var="aposta" value="#{geradorDeApostasBean.apostas}" varStatus="status"> <h:outputText value="Aposta #{status.index + 1}: "/> <h:outputText value="#{aposta}"/> <br/> </ui:repeat> </h:body> </html>

6. Preencha o formulrio e clique no boto de gerar apostas para verique o funcionamento da nossa aplicao. Acesse a url: http://localhost:8080/K19-Loteria/formulario.xhtml

www.k19.com.br

62

Captulo 6 Componentes Visuais


A arquitetura de componentes visuais do JSF permite que novos componentes alm dos que esto denidos na especicao sejam desenvolvidos por terceiros. Isso permitiu que bibliotecas de componentes extremamente ricos visualmente fossem desenvolvidas. Inclusive, em geral, essas bibliotecas utilizam recursos como o AJAX para melhorar a interatividade com o usurio. A mais famosa dessas bibliotecas a RichFaces cujo site ocial pode ser visitado atravs da url: (http://www.jboss.org/richfaces). Porm, no devemos deixar nossos olhos nos enganarem. Os componentes visuais do JSF vo alm da questo visual. Esses componentes podem ser reaproveitados em diversos pontos da mesma aplicao ou em aplicaes diferentes mostrando de forma concreta o poder da Orientao a Objetos e o desenvolvimento Orientado a Componentes. Alm disso, a arquitetura do JSF permite que outros tipos de componentes sejam conectados aos componentes visuais. Por exemplo, podemos conectar componentes validadores aos componentes visuais para que os dados vindos dos usurios sejam vericados de acordo com alguma regra. Neste captulo apresentaremos os principais componentes visuais denidos pela especicao do JSF.

6.1

Formulrios

Os formulrios so necessrios em todas as telas que precisam receber dados dos usurios. O componente visual h:form cria formulrios. 63

Componentes Visuais

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

<h:form> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <br/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <br/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="Pas: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <br/> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <br/> <h:outputLabel value="Li e estou de acordo com os termos de uso." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <br/> <h:commandButton value="Cadastrar"/> </h:form>

Na linha 2, utilizamos o componente visual h:outputLabel para criar um rtulo para o campo no qual deve ser digitado o nome da pessoa que se cadastra. Observe que o atributo for conecta o rtulo ao id do campo do nome. Dessa forma, se o usurio clicar no rtulo o cursor de digitao aparecer nesse campo. Na linha 3, utilizamos o componente visual h:inputText para criar o campo do nome. Denimos o atributo id para que o campo pudesse ser conectado ao rtulo loga acima. www.k19.com.br 64

Componentes Visuais Na linha 9, para criar um campo para texto maiores, utilizamos o componente h:inputTextarea. O funcionamento dele muito semelhante ao do h:inputText. A diferena bsica que a rea de digitao do h:inputTextarea maior. Na linha 13, aplicamos o componente h:selecOneRadio para criar um radio button que permite o usurio escolher o sexo (masculino e feminino). As opes do radio button so denidas pelo componente f:selectItem utilizado nas linhas 14 e 15. Na linha 19, criamos um combo box para que o usurio escolha qual o pas de origem da pessoa que ser cadastrada. Assim como no radio button, as opes do combo box so denidas com o componente f:selectItem. Na linha 28, utilizamos o componente h:inputSecret para criar um campo de texto que no mostra na tela o valor que j foi digitado. Esse componente til para senhas. Na linha 34, inserimos na tela um check box para saber se o usurio aceita ou no os termos de cadastro. O componente utilizado para isso foi o h:selectBooleanCheckbox. Por m, na linha 38, acrescentamos um boto para o usurio conrmar o cadastro.

6.2

Panel Grid

O componente h:panelGrid utilizado para organizar outros componentes em tabelas de uma forma prtica. Basicamente, para utilizar este componente, devemos denir quantas colunas queremos e ele automaticamente distribui os componentes em um nmero suciente de linhas.

65

K19 Treinamentos

Componentes Visuais
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="Pas: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:outputLabel value="Li e estou de acordo com os termos de uso." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <h:commandButton value="Cadastrar"/> </h:panelGrid> </h:form>

6.3

Panel Group

Em certas situaes no conseguimos colocar dois ou mais componentes em um determinado local. Por exemplo, em uma clula de um panel Grid. Nesses casos, devemos aplicar o componente h:panelGroup. A ideia inserir dois ou mais componentes em um panel Group e depois inserir o panel Group no lugar que s aceita um componente.

www.k19.com.br

66

Componentes Visuais
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="Pas: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:panelGroup> <h:outputLabel value="Li e estou de acordo com os termos de uso." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> </h:panelGroup> <h:commandButton value="Cadastrar"/> </h:panelGrid> </h:form>

6.4

Tabelas

Podemos criar tabelas utilizando o componente h:dataTable com dados de alguma coleo. Basicamente, a diferena dos Data Tables e dos Panel Grids que os Data Tables iteram diretamente nos tames de colees.

1 2 3 4 5 6 7 8

<h:dataTable value="#{geradorDeApostasBean.apostas}" var="aposta" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Apostas"></h:outputText> </f:facet> <h:outputText value="#{aposta}"></h:outputText> </h:column> </h:dataTable

Na linha 2, o componente h:column utilizado para adicionar uma coluna na tabela de67 K19 Treinamentos

Componentes Visuais nida com o h:dataTable. Na linha 3, aplicamos o componente f:facet para adicionar um cabealho na coluna correspondente.

6.5

Namespaces

Para poder aplicar as tags que denem as telas das aplicaes JSF, precisamos adicionar os namespaces correspondentes s bibliotecas de tags que desejamos utilizar.
1 2 3 4 5 6 7 8 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <!-- Contedo Aqui --> </html>

Os dois principais namespaces so: http://java.sun.com/jsf/html e http://java.sun.com/jsf/core. O primeiro o namespace da biblioteca de tags do JSF que geram contedo HTML especicamente. O segundo corresponde a biblioteca de tags do JSF que no est atrelada a um tipo de visualizao, ou seja, so tags mais genricas. Outro namespace importante o http://java.sun.com/jsf/facelets que contm tags que nos ajudam a reaproveitar o cdigo das telas. Veremos em outro captulo o funcionamento das tags desse namespace.

6.6

Esqueleto HTML

Um documento HTML possui um esqueleto constitudo por algumas tags principais. Para reetir essa estrutura devemos inserir algumas tags nos documentos XHTML que denem as telas JSF.
1 2 3 4 5 6 7 8 9 10 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> </h:head> <h:body> </h:body> </html>

6.7

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado ComponentesVisuais seguindo os passos vistos no exerccio do captulo 5. www.k19.com.br 68

Componentes Visuais 2. Adicione um arquivo na pasta WebContent do projeto ComponentesVisuais para criar uma tela utilizando os principais componentes de formulrios. Este arquivo deve se chamar formulario.xhtml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <!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> <title>Cadastro de Usurio</title> </h:head> <h:body> <h:form> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="Pas: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:outputLabel value="Li e concordo." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <h:commandButton value="Cadastrar"/> </h:form> </h:body> </html>

Acesse a url adequada para visualizar o formulrio. 3. Utilize o componente h:panelGrid para alinhar melhor os itens do formulrio criado no exerccio anterior.
1 2 3 4 5 6 7 <h:form> <h:panelGrid columns="2"> <!-- CONTEDO DO FORMULRIO --> </h:panelGrid> </h:form>

Verique o resultado atravs de um navegador. 69 K19 Treinamentos

Componentes Visuais 4. Utilize o componente h:panelGroup para agrupar dois ou mais componentes em uma clula do Panel Grid criado no exerccio anterior. 5. Na pasta src crie um pacote chamado managedbeans. Nesse pacote, adicione uma classe com o seguinte contedo para modelar um simples Managed Bean que gera palavras.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @ManagedBean public class PalavrasBean { private List<String> palavras = new ArrayList<String>(); public PalavraBean() { this.palavras.add("K19 Treinamentos"); this.palavras.add("Rafael Cosentino"); this.palavras.add("Alexandre Macedo"); this.palavras.add("Jonas Hirata"); }

public List<String> getPalavras() { return this.palavras; } public void setPalavras(List<String> palavras) { this.palavras = palavras; } }

6. Crie uma tela aplicando o componente h:dataTable para apresentar as palavras geradas pelo Managed Bean do exerccio anterior.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!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> <title>Palavras apenas palavras</title> </h:head> <h:body> <h:dataTable value="#{palavrasBean.palavras}" var="palavra" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Palavras"></h:outputText> </f:facet> <h:outputText value="#{palavra}"></h:outputText> </h:column> </h:dataTable </h:body> </html>

Veja a tabela acessando a url correspondente.

www.k19.com.br

70

Captulo 7 Facelets
Certamente, voc j ouviu algum falar da importncia da reutilizao no desenvolvimento de software. Nesse contexto, os objetivos do reaproveitamento de software so: diminuir o tempo e o custo para desenvolver e facilitar a manuteno tambm diminuindo gastos e tempo. Levando a ideia do reaproveitamento adiante, algumas pessoas desenvolveram um projeto chamado Facelets que tem como principal objetivo facilitar todo o processo de desenvolvimento e manuteno das telas de uma aplicao JSF. O Facelets j faz parte do JSF 2 sendo a engine padro dessa tecnologia para a denio das telas das aplicaes web.

7.1

Templating

A reutilizao do cdigo das telas realizada principalmente pelo uso de templates. A ideia identicar um padro em um determinado conjunto de telas de uma aplicao JSF e deni-lo atravs de um esqueleto (template) que possua trechos dinmicos que possam ser preenchidos posteriormente. A criao de um template simples, basta criar um arquivo xhtml adicionando todos os componentes visuais que so xos e devem aparecer em um determinado conjunto de telas. Para os trechos dinmicos, devemos aplicar o componente ui:insert criando um espao que pode ser preenchido depois. 71

Facelets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!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:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>K19 Treinamentos</title> </h:head> <h:body> <div id="header"> <img src="k19-logo.png" /> <hr /> </div> <ui:insert name="conteudo"> Espao para o contedo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

Na linha 16, o atributo name do componente ui:insert utilizado para identicar o espao que ser preenchido depois. Aps escrever o template, devemos criar as telas que o utilizaro. Essas telas so denidas tambm atravs de arquivos xhtml. Para indicar que desejamos utilizar um template, devemos aplicar o componente ui:composition. Para preencher um espao deixado no template, devemos inserir o componente ui:dene no cdigo.
1 2 3 4 5 6 7 8 9 10 <html 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 template="/template.xhtml"> <ui:define name="conteudo"> <h:outputText value="Contedo da pgina que utiliza o template.xhtml"/> </ui:define> <ui:composition> </html>

7.2

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado Facelets seguindo os passos vistos no exerccio do captulo 5.

2. Crie um template na pasta WebContent chamado template.xhtml. Copie o arquivo k19-logo.png da pasta K19-Arquivos/imagens que est na rea de Trabalho para pasta WebContent do projeto Facelets. www.k19.com.br 72

Facelets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!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:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>K19 Treinamentos</title> </h:head> <h:body> <div id="header"> <img src="k19-logo.png" /> <hr /> </div> <ui:insert name="conteudo"> Espao para o contedo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

3. Monte uma tela que usa o template criado no exerccio anterior. O nome do arquivo deve ser teste-template.xhtml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h:form> <h:outputLabel value="Nome: " for="campo-nome"/> <h:inputText id="campo-nome"/> <h:commandButton value="Enviar"/> </h:form> </ui:define> </ui:composition> </html>

Verique o resultado acessando a url: http://localhost:8080/Facelets/teste-template.xhtml

7.3

Particionando as telas

Com o intuito de organizar melhor o cdigo das telas ou denir pedaos de telas que possam ser reaproveitados, podemos dividir o contedo de uma tela ou de um template em vrios arquivos atravs do componente ui:include. O recurso de separar uma tela ou um template em vrios arquivos se torna mais interessante e til quando temos a possibilidade de passar dados do arquivo principal para os secundrios. Essa passagem de dados realizada atravs do componente ui:param. 73 K19 Treinamentos

Facelets Por exemplo, estamos desenvolvendo uma aplicao e desejamos colocar o nome do usurio e um link para fazer logoff no canto superior direito sempre que algum estiver logado ou um link para a pgina de login caso contrrio. Veja o fragmento que teramos que acrescentar nos arquivos principais:
1 2 3 4 5 6 7 8 9 10 11 <div id="header"> <c:if test="#{usuarioBean.logado}"> <ui:include src="usuario-logado.xhtml"> <ui:param name="usuario" value="#{usuarioBean.usuario}"/> </ui:include> </c:if> <c:if test="#{!usuarioBean.logado}"> <ui:include src="usuario-nao-logado.xhtml"/> </c:if> </div>

Veja os fragmentos que teramos que acrescentar nos arquivos secundrios:


1 2 <h:outputText value="Ol #{usuario.nome}"/> <h:commandButton action="usuarioBean.logout" value="Log out"/>

1 2 3 4 5

<h:outputLabel value="Usurio: " for="campo-usuario"/> <h:inputText id="campo-usuario"/> <h:outputLabel value="Senha: " for="campo-senha"/> <h:inputSecret id="campo-senha"/> <h:commandButton action="usuarioBean.login" value="Log in"/>

7.4

Exerccios

4. Vamos implementar uma listagem de instrutores no nosso projeto Facelets. O primeiro passo criar uma classe para modelar os instrutores. Crie um pacote chamado model no projeto Facelets e adicione nele uma classe chamada Instrutor com seguinte cdigo:

1 2 3 4 5 6

public class Instrutor { private String nome; private String dataDeNascimento; // GETTERS AND SETTERS }

5. Faa um Managed Bean que fornea uma lista de instrutores para uma tela de listagem de instrutores. Crie um pacote chamado managedbeans no projeto Facelets e adicione nele uma classe chamada InstrutorBean com seguinte cdigo: www.k19.com.br 74

Facelets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @ManagedBean public class InstrutorBean { private List<Instrutor> instrutores = new ArrayList<Instrutor>(); public InstrutorBean() { Instrutor rafael = new Instrutor(); rafael.setNome("Rafael Cosentino"); rafael.setDataDeNascimento("30/10/1984"); Instrutor marcelo = new Instrutor(); marcelo.setNome("Marcelo Martins"); marcelo.setDataDeNascimento("02/04/1985"); this.instrutores.add(rafael); this.instrutores.add(marcelo); } public List<Instrutor> getInstrutores() { return instrutores; } public void setInstrutores(List<Instrutor> instrutores) { this.instrutores = instrutores; } }

6. Crie uma tela parcial para mostrar os dados de apenas um instrutor dentro de um item de uma lista HTML. O arquivo deve ser adicionado na pasta WebContent do projeto Facelets e se chamar instrutor-info.xhtml.

1 2 3 4 5 6 7 8 9 10

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <li> <h:outputText value="Nome: #{instrutor.nome}"/> <br/> <h:outputText value="Data Nascimento: #{instrutor.dataDeNascimento}"/> </li> </html>

7. Faa a tela principal da listagem de instrutores. Crie um arquivo na pasta WebContent do projeto Facelets e como o nome listagem-de-instrutores.xhtml e com o seguinte cdigo. 75 K19 Treinamentos

Facelets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <ul> <ui:repeat var="instrutor" value="#{instrutorBean.instrutores}"> <ui:include src="instrutor-info.xhtml"> <ui:param name="instrutor" value="#{instrutor}"/> </ui:include> </ui:repeat> </ul> </ui:define> </ui:composition> </html>

Veja o resultado acessando a url: http://localhost:8080/Facelets/listagem-de-instrutores.xhtml

www.k19.com.br

76

Captulo 8 Navegao
Navegar entre as telas de uma aplicao web preciso. O mecanismo de navegao do JSF bem sosticado e permite vrios tipos de transies entre telas. A ideia muito simples, no clique de um boto ou link, muda-se a tela apresentada ao usurio.

8.1

Navegao Esttica Implcita

Na navegao esttica implcita, quando o usurio clica em algum boto ou link, um sinal (outcome) xo denido no prprio boto ou link enviado para o JSF. Este sinal uma string que ser utilizada pelo tratador de navegao do JSF para denir a prxima tela que ser apresentada ao usurio. Nas navegaes implcitas, os nomes dos arquivos que denem as telas de resposta so montados com as strings dos outcomes. Por exemplo, se o usurio clica em um boto ou link de uma tela denida por um arquivo chamado pagina1.xhtml que envia o outcome pagina2 ento ele ser redirecionado para a tela denida pelo arquivo pagina2.xhtml dentro do mesmo diretrio que est o arquivo pagina1.xhtml. Veja como seria o cdigo da pagina1.xhtml e pagina2.xhtml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Pgina 1</title> </h:head> <h:body> <h1>K19 Pgina 1</h1> <h:form> <h:commandButton value="Pgina 2" action="pagina2"/> </h:form> </h:body> </html>

77

Navegao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!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"> <h:head> <title>K19 Pgina 2</title> </h:head> <h:body> <h1>K19 Pgina 2</h1> <h:form> <h:commandLink action="pagina1"> <h:outputText value="Pgina 1"/> </h:commandLink> </h:form> </h:body> </html>

8.2

Navegao Esttica Explcita

Na navegao implcita, os outcomes so os nomes dos arquivos que denem as telas. Para ter a liberdade de denir os nomes dos arquivos independentemente dos outcomes, podemos utilizar a navegao explcita. Porm, nesse tipo de navegao, devemos acrescentar algumas linhas no arquivo de conguraes do JSF, o faces-cong.xml.
1 2 3 4 5 6 7 8 <navigation-rule> <from-view-id>pagina1.xhtml</from-view-id> <navigation-case> <from-outcome>proxima</from-outcome> <to-view-id>pagina2.xhtml</to-view-id> </navigation-case> </navigation-rule>

O cdigo acima dene que quando a tela do arquivo pagina1.xhtml emitir o sinal(outcome) proxima a transio deve ser realizada para a tela do arquivo pagina2.xhtml. Na tela do arquivo pagina1.xhtml, basta acrescentar um boto ou link que emita o sinal next.
1 <h:commandButton value="Prxima tela" action="proxima"/>

8.3

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado Navegacao seguindo os passos vistos no exerccio do captulo 5. 2. Na pasta WebContent do projeto Navegacao, crie um arquivo chamado pagina1.xhtml com o seguinte cdigo: www.k19.com.br 78

Navegao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Pgina 1</title> </h:head> <h:body> <h1>K19 Pgina 1</h1> <h:form> <h:commandButton value="Pgina 2" action="pagina2"/> </h:form> </h:body> </html>

3. Novamente, na pasta WebContent do projeto Navegacao, crie um arquivo chamado pagina2.xhtml com o seguinte cdigo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!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"> <h:head> <title>K19 Pgina 2</title> </h:head> <h:body> <h1>K19 Pgina 2</h1> <h:form> <h:commandLink action="pagina1"> <h:outputText value="Pgina 1"/> </h:commandLink> </h:form> </h:body> </html>

4. Navegue atravs dos links e botes da url: http://localhost:8080/Navegacao/pagina1.xhtml 5. Congure uma navegao explcita no arquivo faces-cong.xml.
1 2 3 4 5 6 7 8 <navigation-rule> <from-view-id>pagina1.xhtml</from-view-id> <navigation-case> <from-outcome>proxima</from-outcome> <to-view-id>pagina2.xhtml</to-view-id> </navigation-case> </navigation-rule>

6. Adicione um boto na tela do arquivo pagina1.xhtml que emita o sinal proxima abaixo do outro boto. 79 K19 Treinamentos

Navegao
1 <h:commandButton value="Prxima tela" action="proxima"/>

7. Navegue atravs dos links e botes da url: http://localhost:8080/Navegacao/pagina1.xhtml

8.4

Navegao Dinmica Implcita

Na maioria dos casos, no queremos xar nas telas os outcomes que elas podem enviar para o JSF. Normalmente, a escolha dos outcomes so realizadas dentro dos Managed Beans. Na navegao dinmica, quando um usurio clica em um boto ou link, um Managed Bean chamado para escolher um outcome e enviar para o JSF. Para isso, associamos os botes ou os links a mtodos dos Managed Beans. O arquivo cara-ou-coroa.xhtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>K19 Cara ou Coroa</h1> <h:form> <h:commandButton value="Lanar Moeda" action="#{managedBean.proxima}"/> </h:form> </h:body> </html>

Nos Managed Beans, temos que denir a lgica de escolha dos outcomes.
1 2 3 4 5 6 7 8 9 10 11 @javax.faces.bean.ManagedBean public class ManagedBean { public String proxima(){ if(Math.random() < 0.5){ return "cara"; } else { return "coroa"; } } }

Os Managed Beans devem devolver uma string com o outcome escolhido. Se o outcome devolvido pelo Managed Bean no estiver congurado no faces-cong.xml o tratador de navegao do JSF assumir a navegao implcita, ou seja, o valor devolvido o nome do arquivo que ser processado para gerar a tela de resposta. O arquivo cara.xhtml: www.k19.com.br 80

Navegao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Cara!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html>

O arquivo coroa.xhtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Coroa!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html>

8.5

Navegao Dinmica Explcita

Para implementar a navegao dinmica explcita, basta seguir os passos da navegao dinmica implcita e acrescentar as regras de navegao no arquivo de conguraes do JSF.

8.6

Exerccios

8. Implemente um Managed Bean de forma aleatria escolha entre dois outcomes. Crie um pacote chamado managedbeans no projeto Navegacao e adicione uma classe chamada ManagedBean 81 K19 Treinamentos

Navegao
1 2 3 4 5 6 7 8 9 10 11 @javax.faces.bean.ManagedBean public class ManagedBean { public String proxima(){ if(Math.random() < 0.5){ return "cara"; } else { return "coroa"; } } }

9. Crie uma tela principal com um boto que chama o Managed Bean do exerccio anterior para escolher o outcome que deve ser emitido para o JSF. Para isso, faa um arquivo chamado cara-ou-coroa.xhtml na pasta WebContent do projeto Navegacao.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

<!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>K19 Cara ou Coroa</h1> <h:form> <h:commandButton value="Lanar Moeda" action="#{managedBean.proxima}"/> </h:form> </h:body> </html>

10. Crie os arquivos de sada. O arquivo cara.xhtml:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

<!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Cara!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html>

O arquivo coroa.xhtml: www.k19.com.br 82

Navegao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!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"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Coroa!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html>

11. Navegue atravs dos links e botes da url: http://localhost:8080/Navegacao/cara-ou-coroa.xhtml

83

K19 Treinamentos

Navegao

www.k19.com.br

84

Captulo 9 Managed Beans


Atravs das telas de uma aplicao, os usurios podem basicamente: enviar dados para o sistema; visualizar informaes da aplicao; e disparar aes ou eventos. S que as telas no realizam todas essas tarefas sozinhas. Nas aplicaes web JSF, h objetos que oferecem todo o suporte que as telas necessitam. Esses objetos so chamados de Managed Beans. As responsabilidades principais dos Managed Beans so: 1. Fornecer dados que sero apresentados aos usurios nas telas 2. Receber os dados enviados pelos usurios atravs das telas 3. Processar o tratamentos das aes e eventos disparados pelos usurios.

9.1

Criando Managed Beans

Para criar um Managed Bean, devemos escrever uma classe Java simples sem nenhum vnculo direto com classes ou interfaces do JSF. Dizemos, que as classes que implementam os Managed Beans so POJOs (Plain Old Java Object). A simplicidade a maior vantagem de utilizar POJOs. As classes dos Managed Beans precisam ser registradas no JSF. Na verso 2 do JSF, o registro feito atravs da anotao @ManagedBean.
1 2 3 4 5 6 package managedbeans; @ManagedBean class MeuManagedBean { }

Antes do JSF 2, o registro dos Managed Beans era realizado somente atravs do arquivo de conguraes do JSF, o faces-cong.xml.
1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans.MeuManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>

85

Managed Beans As duas possibilidades, anotao ou xml, esto disponveis no JSF 2.

9.2

Disponibilizando dados para as telas

Basta criar mtodos getters nas classes dos Managed Beans para disponibilizar dados para as telas.
1 2 3 4 5 6 7 8 9 10 package managedbeans; @ManagedBean class MeuManagedBean { private String informacao; public String getInformacao() { return this.informacao; } }

9.3

Recebendo dados das telas

Basta criar mtodos setters nas classes dos Managed Beans para receber dados das telas.
1 2 3 4 5 6 7 8 9 10 package managedbeans; @ManagedBean class MeuManagedBean { private String informacao; public void setInformacao(Strign informacao) { this.informacao = informacao; } }

9.4

Denindo o tratamento das aes

Para implementar as lgicas que devem ser executadas assim que o usurio clicar em um boto ou link, basta criar mtodos nas classes dos Managed Beans.
1 2 3 4 5 6 @ManagedBean class MeuManagedBean { public void logica() { // implemetao } }

Esses mtodos podem ser VOID quando desejamos manter os usurios na mesma tela ou devolver S TRING quando desejamos realizar uma navegao entre telas. www.k19.com.br 86

Managed Beans

9.5

Expression Language

De alguma forma as telas precisam referenciar os Managed Beans com os quais elas desejam interagir. H uma linguagem no JSF que podemos utilizar no cdigo das telas que apropriada para realizar a interao entre as pginas e os Managed Beans. Essa linguagem chamada de Expression Language. Dentro do cdigo de uma tela, delimitamos os trechos escritos em Expression Language atravs dos smbolos #{ }.

9.5.1

Nome dos Managed Beans

Todo Managed Bean possui um nome nico que utilizado para acess-lo dentro dos trechos escritos com Expression Language. Quando utilizamos a anotao @ManagedBean, por padro, o JSF assume que o nome do Managed Bean o nome da classe com a primeira letra minscula. Porm podemos alterar o nome acrescentado um argumento na anotao.
1 2 3 4 @ManagedBean(name="teste") class ManagedBean { }

9.5.2

Acessando as propriedades dos Managed Beans

As propriedades dos Managed Beans so acessadas tanto para leitura quanto para escrita da maneira mais natural possvel, pelo nome. Suponha o seguinte Managed Bean:
1 2 3 4 5 6 7 8 9 10 11 12 @ManagedBean(name="teste") class ManagedBean { private String informacao; public String getInformacao() { return this.informacao; } public void setInformacao(String informacao) { this.informacao = informacao; } }

A propriedade Language:
1 #{teste.informacao}

INFORMACAO

deve ser acessada da seguinte forma utilizando Expression

9.6

Binding

Os componentes que esto nas telas podem ser ligados aos Managed Beans. Normalmente, essa ligao estabelecida atravs de algum atributo das tags dos componentes. Por 87 K19 Treinamentos

Managed Beans exemplo, suponha que queremos ligar um campo de texto a uma propriedade de um Managed Bean, o cdigo seria mais ou menos assim:
1 <h:inputText value="#{teste.informacao}"/>

O atributo VALUE do H : INPUT T EXT cria o vnculo entre o input e a propriedade INFORMA do Managed Bean TESTE. Dessa forma, quando o usurio preencher algum valor nesse campo, esse dado ser armazenado no atributo INFORMACAO atravs do mtodo SET I NFOR MACAO (). Outro exemplo, suponha que desejamos associar um mtodo do nosso Managed Bean a um boto de uma tela qualquer. O cdigo seria mais ou menos assim:
CAO
1 2 3 4 5 6 @ManagedBean class MeuManagedBean { public void logica() { // implemetao } }

<h:commandButton action="#{meuManagedBean.logica}" value="Executar"/>

9.7

Escopo

Os Managed Beans so instanciados pelo JSF, ou seja, os desenvolvedores denem as classes e o JSF cuida do new. Porm, podemos determinar quando os Managed Beans devem ser criados e descartados. O tempo de vida de uma instncia afeta principalmente a durabilidade dos dados que ela armazena. Por isso, precisamos escolher qual escopo queremos utilizar em cada Managed Bean.

9.7.1

Request

No escopo Request, as instncias dos Managed Beans so criadas durante o processamento de uma requisio assim que forem necessrias e descartadas no nal desse mesmo processamento. Ou seja, os dados no so mantidos de uma requisio para outra. O JSF utiliza o escopo Request como padro. Dessa forma, se o desenvolvedor no denir nenhum escopo para um determinado Managed Bean o escopo Request ser adotado automaticamente. Mesmo sendo o padro, podemos deixar explcito a escolha do escopo Request atravs da anotao @RequestScoped ou da tag managed-bean-scope. www.k19.com.br 88

Managed Beans
1 2 3 4 5 6 7 package managedbeans; @ManagedBean @RequestScoped class MeuManagedBean { }

1 2 3 4 5

<managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans.MeuManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>

Antes do JSF 2, havia somente a opo da congurao atravs de xml.

9.7.2

Session

Certas informaes devem ser mantidas entre as requisies de um determinado usurio em um determinado navegador. Por exemplo, suponha uma aplicao que utiliza a ideia de carrinho de compras. Um usurio faz diversas requisies para escolher os produtos e coloclos no seu carrinho. Durante todo esse tempo, a aplicao deve manter a informao de quais produtos j foram escolhidos por este usurio. Da surge o escopo Session. Cada usurio possui um espao na memria do servidor que chamado de Session, ou seja, existe uma Session para cada usurio. Tecnicamente, possvel existir duas ou mais Sessions de um mesmo usurio, por exemplo, se ele estiver utilizando dois navegadores. As instncias dos Managed Beans congurados com o escopo Session so criadas quando necessrias durante o processamento de uma requisio e armazenadas na Session do usurio que fez a requisio. Essas instncias so eliminadas basicamente em duas situaes: a prpria aplicao decide por algum motivo especco apagar a Session de um usurio (por exemplo, o usurio fez logout) ou o Web Container decide apagar a Session de um usurio pois este no faz requisies a muito tempo. Esse tempo pode ser congurado com o Web Container. Para escolher o escopo Session, devemos utilizar a anotao @SessionScoped ou a tag managed-bean-scope.
1 2 3 4 5 6 7 package managedbeans; @ManagedBean @SessionScoped class MeuManagedBean { }

1 2 3 4 5

<managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans.MeuManagedBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>

89

K19 Treinamentos

Managed Beans Antes do JSF 2, havia somente a opo da congurao atravs de xml. Temos que tomar um cuidado maior ao utilizar o escopo Session pois podemos acabar sobrecarregando o servidor. Portanto, a dica evitar utilizar o escopo Session quando possvel. Para no consumir excessivamente os recursos de memria do servidor, o escopo Requeste mais apropriado.

9.7.3

Application

As instncias dos Managed Beans congurados com escopo Application so criadas no primeiro momento em que elas so utilizadas e mantidas at a aplicao ser nalizada. Os dados dessas instncias podem ser utilizados nas telas de todos os usurios durante toda a execuo da aplicao. Analogamente, para escolher o escopo Application, devemos utilizar a anotao @ApplicationScoped ou a tag managed-bean-scope.
1 2 3 4 5 6 7 package managedbeans; @ManagedBean @ApplicationScoped class MeuManagedBean { }

1 2 3 4 5

<managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans.MeuManagedBean</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean>

Antes do JSF 2, havia somente a opo da congurao atravs de xml.

9.7.4

View

O escopo View foi adicionado no JSF 2. A ideia manter determinados dados enquanto o usurio no mudar de tela. As instncia dos Managed Beans em escopo View so eliminadas somente quando h uma navegao entre telas. Analogamente, para escolher o escopo View, devemos utilizar a anotao @ViewScoped ou a tag managed-bean-scope.
1 2 3 4 5 6 7 package managedbeans; @ManagedBean @ViewScoped class MeuManagedBean { }

www.k19.com.br

90

Managed Beans
1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans.MeuManagedBean</managed-bean-class> <managed-bean-scope>view</managed-bean-scope> </managed-bean>

Antes do JSF 2, havia somente a opo da congurao atravs de xml.

9.8

Interdependncia e Injeo

Instncias de Managed Beans podem conversar entre si para dividir o processamento das requisies dos usurios de acordo a especialidade de cada uma delas. Para que duas instncias conversem, uma deve possuir a referncia da outra. Como a criao e eliminao das instncias dos Managed Beans so responsabilidade do JSF, ele o mais indicado para administrar as referncias entre as instncias do Managed Beans. Basicamente, o que o desenvolvedor deve fazer indicar ao JSF quais instncias devem ser conectadas atravs de referncias. Como exemplo, suponha dois Managed Beans:
1 2 3 4 @ManagedBean class PrimeiroManagedBean { }

1 2 3 4

@ManagedBean class SegundoManagedBean { }

Suponha tambm que o primeiro precisa chamar o segundo para resolver algum problema. Do ponto de vista da Orientao a Objetos, bastaria declarar um atributo na classe do primeiro Managed Bean relacionando-o ao segundo.
1 2 3 4 @ManagedBean class PrimeiroManagedBean { private SegundoManagedBean segundoManagedBean; }

Porm, como o JSF que vai administrar as ligaes entre os objetos, devemos indicar atravs de anotaes ou de xml o vnculo dos dois Managed Beans.
1 2 3 4 5 @ManagedBean class PrimeiroManagedBean { @ManagedProperty(value="#{segundoManagedBean}") private SegundoManagedBean segundoManagedBean; }

91

K19 Treinamentos

Managed Beans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <managed-bean> <managed-bean-name>primeiroManagedBean</managed-bean-name> <managed-bean-class>managedbeans.PrimeiroManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>segundoManagedBean</property-name> <value>#{segundoManagedBean}</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>segundoManagedBean</managed-bean-name> <managed-bean-class>managedbeans.SegundoManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>

Quando as instncias dos Managed Beans so criadas pelo JSF ele resolve todas as dependncias conectando os objetos.

9.9

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado ManagedBean seguindo os passos vistos no exerccio do captulo 5.

2. Na pasta src, faa um pacote chamado managedbeans.

3. No pacote managedbeans, adicione a seguinte classe:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

package managedbeans; @ManagedBean(name="impostometro") public class ImpostometroBean { private double total; private double valor; public void adicionaImposto() { this.total += this.valor; } // GETTERS AND SETTERS }

4. Crie uma tela com o suporte do Managed Bean impostometro. O arquivo da tela deve se chamar impostometro.xhtml. www.k19.com.br 92

Managed Beans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!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"> <h:head> <title>Impostometro</title> </h:head> <h:body> <h1>Impostometro</h1> <h:form> <h:panelGrid> <h:outputText value="Total: #{impostometro.total}" /> <h:outputLabel value="Digite o imposto a ser adicionado: " for="campo-imposto" /> <h:inputText id="campo-imposto" value="#{impostometro.valor}" /> <h:commandButton value="Adicionar" action="#{impostometro.adicionaImposto}" /> </h:panelGrid> </h:form> </h:body> </html>

Adicione alguns valores atravs do formulrio. Observe que o total no acumula os valores adicionados em requisies anteriores. Por qu?

5. Altere o escopo do impostometro para Session. Teste novamente.

1 2 3

@ManagedBean(name="impostometro") @SessionScoped public class ImpostometroBean {

6. Crie um Managed Bean para guardar os valores de algumas taxas.

1 2 3 4 5 6 7 8 9

package managedbeans; @ManagedBean(name="taxas") public class TaxasBean { private double selic = 3.5; // GETTERS AND SETTERS }

7. Faa um Managed Bean que calcula juros baseado na taxa selic. Para isso, ele deve ser relacionado com o Managed Bean do exerccio anterior. 93 K19 Treinamentos

Managed Beans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package managedbeans; @ManagedBean(name="calculadora") public class CalculadoraBean { @ManagedProperty(value="#{taxas}") private TaxasBean taxas; private double montante; private double juros; public void calculaJuros() { this.juros = this.montante * this.taxas.getSelic() / 100; } // GETTERS AND SETTERS }

8. Construa uma tela que utilize os Managed Beans criados nos exerccios anteriores.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!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"> <h:head> <title>Calculadora de Imposto</title> </h:head> <h:body> <h1>Calculadora de Imposto</h1> <h:form> <h:panelGrid> <h:outputText value="Selic: #{taxas.selic}" /> <h:outputText value="Juros: #{calculadora.juros}" /> <h:outputLabel value="Digite um montante: " /> <h:inputText value="#{calculadora.montante}" /> <h:commandButton value="Calcular" action="#{calculadora.calculaJuros}" /> </h:panelGrid> </h:form> </h:body> </html>

www.k19.com.br

94

Captulo 10 Converso e Validao


10.1 Converso

Quando um usurio preenche um formulrio, os valores escolhidos so enviados para uma aplicao. De acordo com o HTTP, protocolo de comunicao utilizado entre os navegadores e as aplicaes web, esses dados no possuem tipagem. Eles so tratados como texto puro. Dessa forma, quando uma aplicao recebe valores preenchidos em formulrios HTML, ela precisa realizar a converso dos dados que deseja tratar de forma especca. Por exemplo, suponha um formulrio que possui um campo para os usurios digitarem a sua idade. A informao digitada nesse campo tratada como texto puro at chegar na aplicao que deve converter esse dado para algum tipo adequado do Java como INT ou LONG. Eventualmente, os dados que chegam para as aplicaes no podem ser convertidos pois no esto no formato esperado. Por exemplo, se o texto preenchido em um campo numrico possui caracteres no numricos a converso falhar. Podemos observar o processo de converso de outro ponto de vista. Nem sempre o formato das informaes que esto em uma aplicao web Java corresponde ao formato que desejamos que seja apresentado para os usurios. Novamente, os dados devem ser convertidos antes de enviados para os navegadores. Felizmente, o JSF oferece um mecanismo automatizado de converso de dados. Veremos a seguir o funcionamento desse mecanismo.

10.1.1

Converso Padro Implcita

Para os tipos fundamentais da linguagem Java, o JSF dene conversores padres e os aplica de maneira implcita, ou seja, no precisamos fazer nada para o processo de converso acontecer. Os tipos fundamentais do Java so: BigDecimal BigInteger Boolean Byte Character 95

Converso e Validao Double Float Integer Long Short

1 2 3 4 5 6 7

@ManagedBean public class MeuManagedBean { private double numero; // GETTERS AND SETTERS }

1 2

<!-- O valor digitado nesse campo ser convertido para double --> <h:inputText value="#{meuManagedBean.numero}" />

10.1.2

Converso Padro Explcita

Em alguns casos, os conversores padres aplicados implicitamente nos tipos fundamentais do Java no so sucientes. Por exemplo, para trabalhar com valores monetrios precisamos de outros conversores. Por isso, o JSF dene dois outros conversores padres para serem aplicados de maneira explcita. f:convertNumber A tag f:convertNumber permite que converses mais sosticadas sejam feitas em valores numricos. Estipulando duas casas decimais no mnimo:
1 2 3 <h:outputText value="#{managedbean.valor}" > <f:convertNumber minFractionDigits="2" /> </h:outputText>

Dendo a formatao atravs de expresso regular:


1 2 3 <h:outputText value="#{managedbean.valor}" > <f:convertNumber pattern="#0.000" /> </h:outputText>

www.k19.com.br

96

Converso e Validao

Apresentando os dados em porcentagem:


1 2 3 <h:outputText value="#{managedbean.valor}" > <f:convertNumber type="percent" /> </h:outputText>

Utilizando o smbolo do Real para valores monetrios:


1 2 3 <h:outputText value="#{managedbean.valor}" > <f:convertNumber currencySymbol="R$" type="currency" /> </h:outputText>

f:convertDateTime A tag f:convertDateTime permite que converses de datas sejam realizadas. Esse conversor pode ser aplicado em dados do tipo java.util.Date.
1 2 3 <h:outputText value="#{managedbean.date}"> <f:convertDateTime pattern="dd/MM/yyyy" /> </h:outputText>

10.2

Mensagens de Erro

Eventualmente, as informaes preenchidas pelos usurios em formulrios no so adequadas impedindo a converso dos dados. Nesses casos, geralmente, desejamos apresentar para os usurios mensagens relacionadas aos erros no preenchimento das informaes.

10.2.1

h:message

Para adicionar nas telas erros relacionados a um determinado campo, devemos utilizar a componente h:message. Primeiro, temos que denir um id para o campo desejado. Depois, 97 K19 Treinamentos

Converso e Validao associar o h:message a esse id.


1 2 3 4 5 6 7 @ManagedBean public class MeuManagedBean { private double numero; // GETTERS AND SETTERS }

1 2

<h:inputText value="#{meuManagedBean.numero}" id="campo-numero"/> <h:message for="campo-numero"/>

10.2.2

h:messages

A tag h:message permite que os erros dos diversos campos de um formulrio sejam colocados um a um na tela. Inclusive, podemos colocar as mensagens de erro de campo em lugares diferentes na pgina que ser apresentada ao usurio. Em alguns casos, simplesmente, queremos colocar todos os erros de todos os campos de um formulrio juntos na tela. Para isso, devemos aplicar a tag h:messages.
1 <h:messages/>

10.2.3

Alterando as Mensagens de Erro

O texto de cada mensagem de erro de converso ou validao est denido na especicao do JSF 2 que pode ser obtida atravs da url: http://jcp.org/en/jsr/detail?id=314 www.k19.com.br 98

Converso e Validao Essas mensagens esto denidas em ingls. Normalmente, queremos personalizar essas mensagens. Para isso, devemos seguir dois passos:

1. Criar um arquivo de mensagens. 2. Registrar o arquivo de mensagens.

Criando um Arquivo de Mensagens Um arquivo de mensagens um conjunto de chaves e valores. Sendo que cada chave se refere a um tipo de erro e est associada a um valor que o texto que ser apresentado nas telas atravs das tags h:message ou h:messages. O maior problema para denir um arquivo de mensagens no JSF saber quais so as chaves que podemos utilizar. Para conhecer as chaves, devemos consultar a especicao do JSF que pode ser obtida atravs da url: http://jcp.org/en/jsr/detail?id=314. Veja um exemplo de arquivo de mensagens:
1 javax.faces.converter.BooleanConverter.BOOLEAN={1}: {0} must be true or false.

Os arquivos de mensagens devem possuir o suxo properties.

Registrando um Arquivo de Mensagens Suponha que voc tenha criado um arquivo de mensagem chamado Messages.properties num pacote chamado resources. Para registr-lo, voc deve acrescentar uma congurao no arquivo faces-cong.xml.
1 2 3 <application> <message-bundle>resources.Messages</message-bundle> </application>

10.3

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado ConversaoValidacao seguindo os passos vistos no exerccio do captulo 5. 2. Acrescente um pacote na pasta src chamado managedbean e adicione a seguinte classe nesse pacote: 99 K19 Treinamentos

Converso e Validao
1 2 3 4 5 6 7 8 9 10 11 @ManagedBean public class FuncionarioBean { private double salario; private int codigo; private Date aniversario; // GETTERS AND SETTERS }

3. Crie uma tela para cadastrar funcionrios. Adicione um arquivo na pasta WebContent chamado cadastro.xhtml.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

<!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> <title>Cadastro de Funcionrio</title> </h:head> <h:body> <h1>Cadastro de Funcionrio</h1> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="Salrio: R$ " for="campo-salario"/> <h:inputText id="campo-salario" value="#{funcionarioBean.salario}"> <!-- Sistema numrico do Brasil --> <f:convertNumber locale="pt_BR"/> </h:inputText> <h:message for="campo-salario"/> <h:outputLabel value="Cdigo: " for="campo-codigo"/> <h:inputText id="campo-codigo" value="#{funcionarioBean.codigo}"/> <h:message for="campo-codigo"/> <h:outputLabel value="Data: (dd/MM/yyyy)" for="campo-aniversario"/> <h:inputText id="campo-aniversario" value="#{funcionarioBean.aniversario}"> <f:convertDateTime pattern="dd/MM/yyyy"/> </h:inputText> <h:message for="campo-aniversario"/> <h:commandButton value="Cadastrar"/> </h:panelGrid> <h:messages/> </h:form> </h:body> </html>

Preencha o formulrio vrias vezes com valores errados e observe os erros. 4. Faa um pacote chamado resources na pasta src e adicione um arquivo de mensagens nesse pacote chamado Messages.properties com o seguinte contedo. www.k19.com.br 100

Converso e Validao
1 2 3 4 5 6 javax.faces.converter.NumberConverter.NUMBER=O valor {0} no adequado. javax.faces.converter.NumberConverter.NUMBER_detail={0} no nmero ou inadequado. javax.faces.converter.IntegerConverter.INTEGER=O valor {0} no adequado. javax.faces.converter.IntegerConverter.INTEGER_detail={0} no um nmero inteiro. javax.faces.converter.DateTimeConverter.DATE=A data {0} no est correta. javax.faces.converter.DateTimeConverter.DATE_detail= {0} no parece uma data.

5. Adicione a congurao necessria no faces-cong.xml para utilizar o arquivo de mensagens criado no exerccio anterior.
1 2 3 <application> <message-bundle>resources.Messages</message-bundle> </application>

Observao: a tag <application> deve ser colocada dentro de faces-cong. 6. Preencha o formulrio vrias vezes com valores errados e observe as novas mensagens.

10.4

Validao

Muitas vezes, apenas a converso de dados no suciente para vericar se uma informao preenchida em um formulrio por um usurio est correta. Por exemplo, suponha um campo para os usurios digitarem uma idade. Como visto anteriormente, o valor digitado ser tratado como texto at chegar na aplicao e l poder ser convertido para INT. Essa converso no verica se o nmero obtido negativo. Porm, nesse caso, no seria correto obter nmeros negativos pois a idade de uma pessoa sempre positiva. Dessa forma, depois da converso dos dados, mais uma etapa deve ser realizada para validar as informaes.

10.4.1

Validao Padro

O JSF tambm dene validadores padres para serem aplicados nos dados obtidos dos usurios. A seguir veremos a aplicao desses validadores:

10.4.2

Campo Obrigatrio (Required)

A validao mais comum de todas a de vericar se um determinado campo no deixou de ser preenchido. Podemos aplicar essa validao utilizando o atributo required dos inputs.
1 2 <h:inputText value="#{managedbean.nome}" id="campo-nome" required="true"/> <h:message for="campo-nome"/>

10.4.3

f:validateLongRange

O validador f:validateLongRange utilizado para vericar se um valor numrico inteiro pertence a um determinado intervalo de nmeros. 101 K19 Treinamentos

Converso e Validao
1 2 3 4 <h:inputText value="#{managedbean.idade}" id="campo-idade"> <f:validateLongRange minimum="10" maximum="130" /> </h:inputText> <h:message for="campo-idade"/>

10.4.4

f:validateDoubleRange

O validador f:validateDoubleRange utilizado para vericar se um valor numrico real pertence a um determinado intervalo de nmeros.
1 2 3 4 <h:inputText value="#{managedbean.preco}" id="campo-preco"> <f:validateDoubleRange minimum="20.57" maximum="200.56" /> </h:inputText> <h:message for="campo-preco"/>

10.4.5

f:validateLength

O validador f:validateLength utilizado para vericar se uma string possui uma quantidade mnima ou mxima de letras.
1 2 3 4 <h:inputText value="#{managedbean.nome}" id="campo-nome"> <f:validateLength minimum = "6" maximum = "20"/> </h:inputText> <h:message for="campo-nome"/>

10.4.6

f:validateRegex

O validador f:validateRegex utilizado para vericar se um texto respeita uma determinada expresso regular.
1 2 3 4 <h:inputText value="#{managedbean.nome}" id="campo-nome"> <f:validateRegex pattern="[a-zA-Z]{6,20}"/> </h:inputText> <h:message for="campo-nome"/>

10.4.7

Bean Validation

Uma nova abordagem para denir as validaes foi adicionada no JSF2. A ideia declarar as regras de validao nas classes de modelo ao invs de inser-las nas telas. A grande vantagem das validaes denidas nas classes de modelo que elas podem ser utilizadas em diversas partes da aplicao. Esse novo recurso chamado Bean Validation e foi denido pela especicao JSR 303 que pode ser obtida atravs da url: http://jcp.org/en/jsr/detail?id=303. Para denir as validaes com Bean Validation, basta adicionar anotaes nas classes de modelo. www.k19.com.br 102

Converso e Validao
1 2 3 4 5 6 public class Funcionario { @NotNull private String nome; ... }

@NotNull: o valor no pode ser nulo.

@Min: dene um valor mnimo.

@Max: dene um valor mximo.

@Size: dene um valor mnimo e mximo.

@Pattern: aplica uma expresso regular na validao.

Podemos acrescentar mensagens de erro atravs das anotaes.


1 2 3 4 5 public class Funcionario { @NotNull(message="O nome no pode ser nulo") private String nome; ... }

10.5

Exerccios

7. No projeto ConversaoValidacao, crie uma tela para cadastrar produtos de uma loja virtual. O arquivo que voc criar deve se chamar cadastra-produto.xhtml. 103 K19 Treinamentos

Converso e Validao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <!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> <title>Cadastro de Produto</title> </h:head> <h:body> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="Nome: " for="produto-nome"/> <h:inputText id="produto-nome" required="true" value="#{produtoBean.produto.nome}"/> <h:message for="produto-nome" /> <h:outputLabel value="Preo: " for="produto-preco"/> <h:inputText id="produto-preco" required="true" value="#{produtoBean.produto.preco}"> <f:validateDoubleRange minimum="0" /> </h:inputText> <h:message for="produto-preco" /> <h:commandButton value="Cadastrar" /> </h:panelGrid> </h:form> </h:body> </html>

8. Crie a classe de modelo para denir os produtos. Adicione essa classe dentro de um pacote chamado model.

1 2 3 4 5 6

public class Produto { private String nome; private double preco; // GETTERS AND SETTERS }

9. Depois, implemente o Managed Bean que dar suporte tela de cadastro de produtos. Faa a classe ProdutoBean dentro do pacote managedbeans.

1 2 3 4 5 6

@ManagedBean public class ProdutoBean { private Produto produto = new Produto(); // GETTERS AND SETTERS }

10. Teste o formulrio preenchendo diversos valores e observe as mensagens de erro. www.k19.com.br 104

Converso e Validao 11. Retire a validao realizada com a tag f:validateDoubleRange. Acrescente uma validao com as anotaes da especicao de Bean Validation na classe P RODUTO.
1 2 3 4 5 6 7 8 public class Produto { private String nome; @Min(value = 0) private double preco; // GETTERS AND SETTERS }

12. Teste novamente o formulrio. 13. (Opcional) Altere as mensagens de erros do formulrio de cadastro de produto.

105

K19 Treinamentos

Converso e Validao

www.k19.com.br

106

Captulo 11 Eventos
Normalmente, as pessoas preferem utilizar aplicaes que ofeream maior grau de interatividade. Consequentemente, as empresas buscam sistemas mais interativos para controlar os seus negcios e serem utilizados pelos seus funcionrios. A interatividade de uma aplicao est diretamente relacionada a sua capacidade de percepo e reao. O nvel mais alto de interatividade aconteceria se uma aplicao pudesse perceber e reagir aos pensamentos dos usurios. O JSF no oferece esse nvel de interao, na verdade, nenhuma tecnologia oferece. Mas, veremos que ele oferece um mecanismo bem sosticado para aumentar a interatividade com os usurios. Esse mecanismo baseado na ideia de eventos. No JSF, h duas categorias fundamentais de eventos: eventos de aplicao e eventos de ciclo de vida. Os eventos de aplicao correspondem s aes dos usurios que so pertinentes s aplicaes. Por exemplo, um usurio pressiona um boto ou altera o valor de preenchido em um campo de um formulrio. Os eventos de ciclo de vida correspondem s transies entre as diversas etapas do processamento de uma requisio ou s transies entre os estados dos componentes do JSF ou da prpria aplicao.

11.1

Eventos de Aplicao (Application Events)

Como dito anteriormente, os eventos de aplicao correspondem s aes dos usurios que interessam para as aplicaes. O JSF suporta dois tipos de eventos de aplicao: ActionEvent e ValueChangeEvent.

11.1.1

ActionEvent

Os ActionEvents so gerados por botes ou links quando esses so pressionados pelos usurios. O tratamento dos ActionEvents pode ser denido por mtodos dentro dos Managed Beans. Esses mtodos so classicados em dois tipos: Action Method ou Action Listener Method. Um Action Method deve ser utilizado quando desejamos efetuar uma navegao (mudar de tela) aps o tratamento do evento. Caso contrrio, devemos utilizar um Action Listener Method. 107

Eventos Action Method Um Action Method deve devolver uma String que ser utilizada como outcome para processar uma navegao. Veja um exemplo de Action Method.
1 <h:commandButton value="Salva" action="#{produtoBean.salva}" />

1 2 3 4

public String salva() { // implementao return "lista-produtos"; }

No h:commandButton denimos qual o Action Method que queremos associar ao boto atravs do atributo action. Action Listener Method Um Action Listener Method precisa ser void e aceita um ActionEvent como argumento. Um ActionEvent contem informaes sobre o evento disparado.
1 <h:commandButton value="Salva" actionListener="#{produtoBean.salva}" />

1 2 3

public void salva(ActionEvent event) { // implementao }

No h:commandButton denimos qual o Action Listener Method que queremos associar ao boto atravs do atributo actionListener.

11.1.2

ValueChangeEvent

Os ValueChangeEvent so gerados quando os usurios modicam o valor preenchido em um campo de um formulrio. O tratamento desse tipo de evento pode ser realizado por mtodos de um Managed Bean. Esses mtodos so chamados de Value Change Listeners. Um Value Change Listener precisa ser void e aceita um ValueChangeEvent como argumento. Um ValueChangeEvent contem informaes sobre o evento disparado.
1 2 <h:outputLabel value="Preo: "/> <h:inputText valueChangeListener="#{produtoBean.mudaPrecoListener}"/>

1 2 3

public void mudaPrecoListener(ValueChangeEvent event) { // implementao }

www.k19.com.br

108

Eventos No h:inputText denimos qual o Value Change Listener queremos associar ao campo atravs do atributo valueChangeListener.

11.2

Eventos de Ciclo de Vida (Lifecycle Events)

Os eventos de ciclo de vida so utilizados quando desejamos executar procedimentos antes ou depois de uma determinada etapa do processamento de uma requisio ou a cada mudana de estado de um componente do JSF e da prpria aplicao. Vamos discutir a respeito dos Phase Events que correspondem s transies entre as etapas do processamento das requisies. Um Phase Event tratado por um Phase Listener. Como o prprio JSF dispara automaticamente os Phase Events, devemos apenas criar um Phase Listener e registr-lo. Para criar um Phase Listener, devemos escrever uma classe que implemente a interface PhaseListener.
1 2 3 4 5 6 7 8 9 10 11 12 13 package listeners; public class MeuPhaseListener implements PhaseListener { public void beforePhase(PhaseEvent pe) { // implementao } public void afterPhase(PhaseEvent pe) { // implementao } public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } }

O mtodo getPhaseID() associa o listener a determinadas fases do processamento de uma requisio. Os mtodos beforePhase() e afterPhase() so executados respectivamente antes e depois das fases associadas ao listener. Para registrar o nosso Phase Listener devemos acrescentar algumas conguraes no facescong.xml.
1 2 3 <lifecycle> <phase-listener>listeners.MeuPhaseListener</phase-listener> </lifecycle>

11.3

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado Eventos seguindo os passos vistos no exerccio do captulo 5. 2. Vamos montar um formulrio de estados e cidades. Para isso, crie um pacote chamado model e adicione a seguinte classe para representar os estados. 109 K19 Treinamentos

Eventos
1 2 3 4 5 6 7 8 9 10 11 package model; public class Estado { private String nome; private String sigla; private List<String> cidades = new ArrayList<String>(); // GETTERS AND SETTERS }

3. Depois, crie um pacote managedbeans e adicione um Managed Bean para manipular os estados.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

package managedbeans; @ManagedBean @SessionScoped public class LocalidadeBean { private String cidade; private String siglaEstado; private Estado estado = new Estado(); private List<Estado> estados = new ArrayList<Estado>(); public LocalidadeBean() { Estado sp = new Estado(); sp.setSigla("SP"); sp.setNome("So Paulo"); sp.getCidades().add("So Paulo"); sp.getCidades().add("Campinas"); Estado rj = new Estado(); rj.setSigla("RJ"); rj.setNome("Rio de Janeiro"); rj.getCidades().add("Rio de Janeiro"); rj.getCidades().add("Niteri"); this.estados.add(sp); this.estados.add(rj); } public void mudaEstado(ValueChangeEvent vce) { this.siglaEstado = vce.getNewValue().toString(); for(Estado e : this.estados){ if(e.getSigla().equals(this.siglaEstado)){ this.estado = e; } } } // GETTERS AND SETTERS }

4. Faa a tela de busca de estados e cidade. Adicione um arquivo chamado busca-localidade.xhtml na pasta WebContent. www.k19.com.br 110

Eventos
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <!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> <title>Busca Localidade</title> </h:head> <h:body> <h1>Busca Localidade</h1> <h:form> <h:outputLabel value="Estado: " for="campo-estado" /> <h:selectOneMenu id="campo-estado" value="#{localidadeBean.siglaEstado}" valueChangeListener="#{localidadeBean.mudaEstado}" onchange="this.form.submit();"> <f:selectItems value="#{localidadeBean.estados}" var="e" itemLabel="#{e.nome}" itemValue="#{e.sigla}" /> </h:selectOneMenu> <h:outputLabel value="Cidade: " for="campo-cidade" /> <h:selectOneMenu id="campo-cidade" value="#{localidadeBean.cidade}"> <f:selectItems value="#{localidadeBean.estado.cidades}" /> </h:selectOneMenu> </h:form> </h:body> </html>

111

K19 Treinamentos

Eventos

www.k19.com.br

112

Captulo 12 Ajax
Quando as aplicaes possuem telas complexas com grande quantidade de contedo, no interessante recarregar uma pgina inteira s para modicar um pequeno pedao da tela pois isso deixar os usurios insatisfeitos. Novamente, com o intuito de melhorar a interatividade entre as aplicaes e os usurios, podemos aplicar o conceito do AJAX (Asynchronous Javascript And XML). Aplicando a ideia do AJAX obtemos duas capacidades muito uteis: a primeira poder fazer requisies sem recarregar as pginas completamente e sim a parte delas que nos interessa; a segunda poder realizar requisies sem pausar a navegao dos usurios. Por exemplo, suponha uma pgina de listagem de fotos que possua paginao. Quando o usurio pressiona o link para a prxima pgina, no necessrio recarregar todo o contedo da tela, podemos recarregar apenas os itens na listagem. Outro exemplo, suponha uma aplicao de Instant Message (gtalk, msn, ...). A listagem de contatos pode ser atualizada frequentemente sem os usurios pedirem e sem que eles tenham que para a navegao para essa atualizao. A verso 2 do JSF, diferentemente das anteriores, oferece suporte nativo a AJAX. Veremos como utilizar esse suporte.

12.1

Fazendo requisies AJAX

As requisies AJAX so realizadas quando determinados eventos denidos pela linguagem Javascript ocorrem. Esses eventos esto fortemente relacionados aos componentes visuais colocados nas telas. Precisamos indicar para o JSF quais componentes e eventos devem disparar requisies para o servidor. Para fazer isso, devemos utilizar a tag f:ajax (principal tag do suporte nativo do JSF para aplicar o conceito do AJAX).
1 2 3 <h:inputText> <f:ajax/> </h:inputText>

No exemplo acima, uma requisio AJAX ser disparada quando o valor do campo for modicado. Isso porque a tag f:ajax assume o evento padro do componente associado a ela. O componente h:inputText utiliza por padro o evento onchange. 113

Ajax Por outra lado, podemos explicitar o evento que deve disparar as requisies AJAX deixando o cdigo mais claro atravs do atributo event. Devemos tomar cuidado pois nem todos os eventos so aceitos por todos os componentes.
1 2 3 <h:inputText> <f:ajax event="keyup"/> </h:inputText>

Quando temos vrios componentes para os quais desejamos oferecer o suporte do AJAX, podemos agrup-los atravs da tag f:ajax.
1 2 3 4 5 <f:ajax> <h:inputText/> <h:inputSecret/> <h:commandButton value="OK"/> <f:ajax>

Novamente, se no escolhermos explicitamente o evento que vai disparar as requisies o JSF assumir o padro de cada componente. O padro dos componentes h:inputText e h:inputSecret onchange. O padro do componente h:commandButton onclick. Mas, podemos explicitar o evento que deve disparar as requisies AJAX para um determinado grupo de componentes da mesma forma que zemos anteriormente.
1 2 3 4 5 <f:ajax event="mouseout"> <h:inputText/> <h:inputSecret/> <h:commandButton value="OK"/> <f:ajax>

12.2

Recarregando alguns pedaos das telas

Aps realizar uma requisio AJAX, podemos pedir para o JSF redesenhar alguns pedaos da tela que est sendo mostrada para o usurio. Por exemplo, suponha uma listagem paginada de produtos, quando o usurio clica no boto que requisita atravs de AJAX a prxima pgina e a resposta chega, podemos mandar o JSF redesenhar a listagem e apenas a listagem com os dados que acabaram de chegar. A tag f:ajax atravs do atributo render permite escolher os ids dos componentes que devem ser recarregados aps uma requisio AJAX.
1 2 3 4 <h:commandButton value="Gera Nmero"> <f:ajax event="click" render="numero"/> <h:commandButton/> <h:outputText id="numero" value="managedBean.numero"/>

Podemos redesenhar vrios componentes, basta passar uma listagem de ids no valor do atributo render. www.k19.com.br 114

Ajax
1 2 3 4 5 <h:commandButton value="Gera Nmeros"> <f:ajax event="click" render="numero1 numero2"/> <h:commandButton/> <h:outputText id="numero1" value="managedBean.numero1"/> <h:outputText id="numero2" value="managedBean.numero2"/>

12.3

Processando alguns pedaos das telas

Quando uma requisio AJAX feita, podemos determinar quais componentes da tela devem ser avaliados pelo JSF. Por exemplo, quando enviamos um formulrio, provavelmente, s necessrio avaliar os componentes que esto no prprio formulrio. Podemos denir quais componentes devem ser avaliados pelo JSF atravs do atributo execute passando uma lista de ids. Quando escolhemos um componente para ser avaliados os componentes dentro dele tambm sero.
1 2 3 4 5 6 7 8 9 10 <h:form id="formulario"> <h:inputText/> <h:inputSecret/> <h:commandButton value="Entrar"> <f:ajax event="click" render="message" execute="formulario"/> <h:commandButton/> </h:form> <h:outputText id="message" value="#{loginBean.message}"/>

12.4

Palavras especiais

Como podemos passar uma lista de componentes para os atributos render e execute, o JSF criou palavras chaves associadas a grupos especiais de componente. Dessa forma, podemos trabalhar sem a necessidade de denir ids em alguns casos. @all : refere-se a todos os componentes da tela. @nome : refere-se a nenhum componente. @this : refere-se ao componente que disparou a requisio AJAX. @form : refere-se aos componentes do formulrio que contm o componente que disparou a requisio AJAX. Podemos alterar o cdigo do formulrio anterior para utilizar a palavra especial @form no lugar do id do formulrio. 115 K19 Treinamentos

Ajax
1 2 3 4 5 6 7 8 9 10 <h:form> <h:inputText/> <h:inputSecret/> <h:commandButton value="Entrar"> <f:ajax event="click" render="message" execute="@form"/> <h:commandButton/> </h:form> <h:outputText id="message" value="#{loginBean.message}"/>

12.5

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado Ajax seguindo os passos vistos no exerccio do captulo 5. 2. Vamos montar um formulrio de cadastro de automveis. Para isso, crie um pacote chamado model e adicione a seguinte classe para representar os automveis.
1 2 3 4 5 6 7 8 9 10 package model; public class Automovel { private String nome; private String marca; // GETTERS AND SETTERS }

3. Depois, crie um pacote managedbeans e adicione um Managed Bean para manipular os automveis.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package managedbeans; @ManagedBean @SessionScoped public class AutomovelBean { private Automovel automovel = new Automovel(); private List<Automovel> automoveis = new ArrayList<Automovel>(); public void adiciona(){ this.automoveis.add(this.automovel); this.automovel = new Automovel(); } // GETTERS AND SETTERS }

4. Faa a tela de listagem e cadastro de automveis. Adicione um arquivo chamado listacadastro-automovel.xhtml na pasta WebContent. www.k19.com.br 116

Ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <!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> <title>Automveis</title> </h:head> <h:body> <h1>Novo Automvel</h1> <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="campo-nome" /> <h:inputText id="campo-nome" value="#{automovelBean.automovel.nome}" /> <h:outputLabel value="Marca: " for="campo-marca" /> <h:inputText id="campo-marca" value="#{automovelBean.automovel.marca}" /> <h:commandButton value="Cadastrar"> <f:ajax event="click" render="lista" execute="@form" listener="#{automovelBean.adiciona}"/> </h:commandButton> </h:panelGrid> <h1>Lista de Automveis</h1> <h:dataTable id="lista" value="#{automovelBean.automoveis}" var="automovel"> <h:column> <f:facet name="header"> <h:outputText value="Nome" /> </f:facet> #{automovel.nome} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Marca" /> </f:facet> #{automovel.marca} </h:column> </h:dataTable> </h:form> </h:body> </html>

117

K19 Treinamentos

Ajax

www.k19.com.br

118

Captulo 13 Projeto
Nos captulos anteriores, vimos isoladamente recursos do JSF e do JPA. Agora, vamos mostrar em detalhes como esses recursos trabalham juntos e solidicar os conhecimentos obtidos. Alm disso, mostraremos alguns padres e conceitos relacionados ao desenvolvimento de aplicaes web. Como exemplo de aplicao desenvolveremos uma aplicao de cadastro de jogadores e selees de futebol.

13.1

Modelo

Por onde comear o desenvolvimento de uma aplicao? Essa uma questo recorrente. Um timo ponto de partida desenvolver as entidades principais da aplicao. No nosso caso, vamos nos restringir s entidades Selecao e Jogador. Devemos estabelecer um relacionamento entre essas entidades j que um jogador atua em uma seleo.

13.2

Exerccios

1. Crie um projeto do tipo Dynamic Web Project chamado K19-CopaDoMundo seguindo os passos vistos no exerccio do captulo 5. 2. Faa um pacote chamado modelo e adicione as duas classes principais da nossa aplicao.

1 2 3 4 5 6 7 8

public class Selecao { private String pais; private String tecnico; // GETTERS AND SETTERS }

119

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Jogador { private String nome; private String posicao; private Calendar nascimento = new GregorianCalendar(); private double altura; private Selecao selecao;

// GETTERS AND SETTERS }

13.3

Persistncia - Mapeamento

Depois de denir algumas entidades podemos comear o processo de implementao da persistncia da nossa aplicao. Vamos aplicar os recursos do JPA que aprendemos nos primeiros captulos. Inicialmente, vamos denir o mapeamento das nossas entidades atravs das anotaes adequadas.

13.4

Exerccios

3. Adicione as anotaes do JPA nas classes de modelo.

1 2 3 4 5 6 7 8 9 10 11 12

@Entity public class Selecao { @Id @GeneratedValue private Long id; private String pais; private String tecnico; // GETTERS AND SETTERS }

www.k19.com.br

120

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Entity public class Jogador { @Id @GeneratedValue private Long id; private String nome; private String posicao; private Calendar nascimento = new GregorianCalendar(); private double altura; @ManyToOne private Selecao selecao;

// GETTERS AND SETTERS }

A anotao @ManyToOne utilizada para indicar a cardinalidade do relacionamento entre jogadores e selees.

13.5

Persistncia - Congurao

Assim como nos captulos anteriores, implantaremos a nossa aplicao no Glasssh que um servidor de aplicao Java EE. Os servidores de aplicao Java EE j possuem uma implementao de JPA. Dessa forma, as aplicaes no precisam se preocupar em obter um provedor de JPA. Por outro lado, geralmente, os servidores de aplicao no so distribudos com os principais drivers JDBC que normalmente as aplicao desejam utilizar. Portanto, devemos adicionar o driver JDBC que desejamos utilizar nas bibliotecas do Glasssh. Depois disso, devemos congurar as propriedades do JPA atravs do arquivo persistence.xml.

13.6

Exerccios

4. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho e copie o arquivo MYSQL - CONNECTOR - JAVA -5.1.13- BIN . JAR para pasta glassshv3/glasssh/lib tambm da sua rea de Trabalho.

5. Adicione uma pasta chamada META-INF na pasta src do projeto K19-CopaDoMundo.

6. Congure o JPA adicionando o arquivo persistence.xml na pasta META-INF. 121 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="copadomundo" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect. MySQLInnoDBDialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver " /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="root" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql:// localhost:3306/copadomundo" /> </properties> </persistence-unit> </persistence>

7. Abra um terminal; entre no cliente do MySQL Server; apague se existir a base de dados copadomundo; e crie uma base de dados nova chamada copadomundo. Para entrar no MySQL Server: mysql -u root -p Para apagar uma base de dados: DROP DATABASE copadomundo; Para criar uma base de dados: CREATE DATABASE copadomundo;

13.7
13.7.1

Persistncia - Open Session in View


Gerenciando as fbricas de Entity Managers

Quando trabalhamos com JPA, devemos nos preocupar com a criao e destruio das fbricas de entity manager. Ao criar uma fbrica de Entity Manager, todas as conguraes e anotaes so processadas e armazenadas na memria. De fato, s necessrio realizar esse processo uma vez para cada execuo. Alm disso, como esse procedimento pode consumir signicativamente os recursos da mquina ento realiz-lo duas ou mais vezes na mesma execuo seria apenas desperdcio. No contexto de uma aplicao web implementada com JSF, podemos criar uma fbrica de entity manager exatamente antes da primeira requisio servlet do JSF e destru-la exatamente antes do encerramento da aplicao. Dessa forma, conseguiremos garantir a existncia da fbrica durante todo o perodo no qual a aplicao receber requisies. www.k19.com.br 122

Projeto

13.7.2

Filtros

Para implementar essa abordagem, podemos criar um ltro no Web Container associado servlet do JSF. Dessa forma, antes da primeira requisio a essa servlet ele ser iniciado e imediatamente antes da aplicao encerrar ele ser desativado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @WebFilter(servletNames={"Faces Servlet"}) public class JPAFilter implements Filter { private EntityManagerFactory factory; @Override public void init(FilterConfig filterConfig) throws ServletException { this.factory = Persistence.createEntityManagerFactory("copadomundo"); } @Override public void destroy() { this.factory.close(); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // por enquanto vazio } }

Um ltro registrado no Web Container atravs da anotao @WebFilter. Atravs dessa anotao denimos qual servlet est associada ao nosso ltro pelo nome da servlet. O mtodo INIT () chamado para inicializar o ltro imediatamente antes da primeira requisio ser enviada para a servlet do JSF. Criamos a fbrica de entity manager nesse mtodo. O mtodo DESTROY () chamado para desativar o ltro imediatamente antes do encerramento da aplicao. Fechamos a fbrica de entity manager nesse mtodo.

13.7.3

Gerenciando os Entity Managers

Provavelmente, a estratgia de gerenciamento de Entity Managers mais simples de entender e manter adotar o padro a Open Session in View. A ideia associar o tempo de vida de um Entity Manager durao do processamento de uma requisio. Ou seja, quando uma requisio realizada, criamos um Entity Manager para ser utilizado no tratamento dessa requisio, quando esse processamento terminar, fechamos o Entity Manager. Para implementar o padro Open Session in View, podemos utilizar o mesmo ltro que gerencia a criao e o fechamento das fbricas de Entity Manager pois as requisies passam por esse ltro antes de chegar at a servlet do JSF. Alm disso, antes da resposta ser enviada ao usurio, a execuo passa pelo ltro novamente. Na chegada de uma requisio, devemos criar um Entity Manager e adicion-lo na requisio para que ele possa ser acessado pela aplicao durante o processamento dessa requisio. Imediatamente, antes da resposta ser enviada, devemos abrir e conrmar uma transao no Entity Manager para que as alteraes decorrentes ao processamento da requisio sejam reetidas no banco de dados. 123 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @WebFilter(servletNames={"Faces Servlet"}) public class JPAFilter implements Filter { private EntityManagerFactory factory; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { EntityManager entityManager = this.factory.createEntityManager(); request.setAttribute("entityManager", entityManager); chain.doFilter(request, response); try { entityManager.getTransaction().begin(); entityManager.getTransaction().commit(); } catch (Exception e) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } @Override public void init(FilterConfig filterConfig) throws ServletException { this.factory = Persistence.createEntityManagerFactory("copadomundo"); } @Override public void destroy() { this.factory.close(); } }

13.8

Exerccios

8. Faa um pacote chamado ltros e adicione nele uma classe chamada JPAFilter. www.k19.com.br 124

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @WebFilter(servletNames={"Faces Servlet"}) public class JPAFilter implements Filter { private EntityManagerFactory factory; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { EntityManager entityManager = this.factory.createEntityManager(); request.setAttribute("entityManager", entityManager); chain.doFilter(request, response); try { entityManager.getTransaction().begin(); entityManager.getTransaction().commit(); } catch (Exception e) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); } } @Override public void init(FilterConfig filterConfig) throws ServletException { this.factory = Persistence.createEntityManagerFactory("copadomundo"); } @Override public void destroy() { this.factory.close(); } }

13.9

Persistncia - Repositrios

Vamos deixar os repositrios para acessar as entidades da nossa aplicao preparados. Os repositrios precisam de Entity Managers para realizar as operaes de persistncia. Ento, cada repositrio ter um construtor para receber um Entity Manager como parmetro. Como o padro Open Session in View foi adotado na nossa aplicao, o gerenciamento das transaes no uma tarefa dos repositrios. Mas, o funcionamento deles ainda afetado pelo controle de transaes. Se um usurio faz uma requisio para cadastrar uma seleo ela s existir no banco de dados quando o processamento voltar para o ltro que gerencia as transaes. Nesse momento, a tela de resposta j teria sido montada pelo Facelets com os dados do banco de dados sem a nova seleo. Em outras palavras, o usurio veria uma listagem sem a seleo que ele acabou de cadastrar. Para resolver este problema, o repositrio de selees pode enviar a nova seleo imediatamente para o banco de dados bem antes da montagem da tela de resposta. Dessa forma, essa tela de listagem de selees mostrar inclusive a nova seleo. A implementao desse repositrio deve utilizar o mtodo ush() que envia imediatamente para o banco de dados as alteraes realizadas dentro da transao corrente sem conrm-las (a conrmao s ocorre na chamada do mtodo commit()). 125 K19 Treinamentos

Projeto Para que esse processo funcione, devemos alterar o nosso ltro de gerenciamento transacional para que ele abra uma transao na chegada de uma nova requisio. Caso contrrio, o mtodo ush() no funcionar no repositrio de selees. Os outros repositrios podem adotar a mesma estratgia para garantir que os usurios vejam dados atualizados.

13.10

Exerccios

9. Faa um pacote chamado repositorios e adicione nele uma classe chamada SelecaoRepository.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class SelecaoRepository { private EntityManager entityManager; public SelecaoRepository(EntityManager entityManager) { this.entityManager = entityManager; } public void adiciona(Selecao selecao) { this.entityManager.persist(selecao); this.entityManager.flush(); } public List<Selecao> getSelecoes() { Query query = this.entityManager .createQuery("select s from Selecao as s"); return query.getResultList(); } }

10. Analogamente crie um repositrio de jogadores.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class JogadorRepository { private EntityManager entityManager; public JogadorRepository(EntityManager entityManager) { this.entityManager = entityManager; } public void adiciona(Jogador jogador) { this.entityManager.persist(jogador); this.entityManager.flush(); } public List<Jogador> getJogadores() { Query query = this.entityManager .createQuery("select j from Jogador as j"); return query.getResultList(); } }

11. Altere o ltro de gerenciamento de transaes. Abra uma transao na chegada de uma requisio. Veja como deve car o mtodo doFilter(). www.k19.com.br 126

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 EntityManager entityManager = this.factory.createEntityManager(); request.setAttribute("entityManager", entityManager); entityManager.getTransaction().begin(); chain.doFilter(request, response); try { entityManager.getTransaction().commit(); } catch (Exception e) { entityManager.getTransaction().rollback(); } finally { entityManager.close(); }

13.11

Apresentao - Template

Vamos denir um template para as telas da nossa aplicao utilizando os recursos do Facelets. Aplicaremos algumas regras CSS para melhorar a parte visual das telas.

13.12

Exerccios

12. Na pasta WebContent, crie um arquivo com algumas regras CSS chamado style.css. 127 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 .logo{ vertical-align: middle; } .botao { background-color: #064D83; margin: 0 0 0 20px; color: white; text-decoration: none; font-size: 20px; line-height: 20px; padding: 5px; vertical-align: middle; } .botao:hover{ background-color: #cccccc; color: #666666; } .formulario fieldset{ float: left; margin: 0 0 20px 0; border: 1px solid #333333; } .formulario fieldset legend{ color: #064D83; font-weight: bold; } .botao-formulario{ background-color: #064D83; color: #ffffff; padding: 5px; vertical-align: middle; border: none; } .mensagem-erro{ color: #ff0000; } .titulo { color: #064D83; clear: both; } .tabela{ border: 1px solid #064D83; border-collapse: collapse; } .tabela tr th{ background-color: #064D83; color: #ffffff; } .tabela tr th, .tabela tr td{ border: 1px solid #064D83; padding: 2px 5px; }

13. Copie o arquivo k19-logo.png da pasta K19-Arquivos da sua rea de Trabalho para a pasta WebContent. www.k19.com.br 128

Projeto 14. Agora implemente um template utilizando Facelets. Crie um arquivo chamado template.xhtml na pasta WebContent.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.png" /> <h:outputLink styleClass="botao" value="selecoes.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.xhtml">Jogadores</ h:outputLink> <hr/> </div> <ui:insert name="conteudo"> Espao para o contedo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

15. Adicione duas telas, uma para selees e outra para jogadores. Essas duas telas devem utilizar o template criado no exerccio anterior. Os arquivos devem se chamar: selecoes.xhtml e jogadores.xhtml e ambos devem possuir o seguinte contedo.
1 2 3 4 5 6 7 8 9 <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"> <ui:composition template="template.xhtml"> </ui:composition> </html>

16. Acesse as duas telas criadas anteriormente.

13.13

Cadastrando e Listando Selees

Na tela de selees, vamos adicionar um formulrio para cadastrar novas selees e uma tabela para apresentar as j cadastradas. Aplicaremos regras de validao especcas para garantir que nenhum dado incorreto seja armazenado no banco de dados. Alm disso, utilizaremos os recursos nativos do JSF 2 para aplicar as tcnicas de AJAX. 129 K19 Treinamentos

Projeto

13.14

Exerccios

17. Para garantir uma melhor legibilidade da nossa aplicao, criaremos uma tela parcial com os campos e o boto referentes ao cadastramento de selees. Adicione o arquivo cadastro-selecao.xhtml na pasta WebContent com o seguinte contedo.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

<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"> <fieldset> <legend>Nova Seleo</legend> <h:panelGrid columns="3"> <h:outputLabel value="Pas: " for="selecao-pais" /> <h:inputText id="selecao-pais" required="true" value="#{selecaoBean.selecao.pais}"> <f:validateLength minimum="3" /> </h:inputText> <h:message for="selecao-pais" styleClass="mensagem-erro" /> <h:outputLabel value="Tcnico: " for="selecao-tecnico" /> <h:inputText id="selecao-tecnico" required="true" value="#{selecaoBean.selecao.tecnico}"> <f:validateLength minimum="6" /> </h:inputText> <h:message for="selecao-tecnico" styleClass="mensagem-erro" /> <h:commandButton value="Cadastrar" styleClass="botao-formulario"> <f:ajax event="click" execute="@form" listener="#{selecaoBean.adiciona}" render="@form" /> </h:commandButton> </h:panelGrid> </fieldset> </html>

18. Analogamente ao exerccio anterior, vamos criar uma tela parcial para apresentar as selees dentro de uma tabela. Adicione o arquivo listagem-selecoes.xhtml na pasta WebContent com o seguinte contedo. www.k19.com.br 130

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <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"> <h3 class="titulo">Listagem de Selees</h3> <h:dataTable id="tabela" value="#{selecaoBean.selecoes}" var="selecao" styleClass="tabela"> <h:column> <f:facet name="header"> <h:outputText value="Id" /> </f:facet> #{selecao.id} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Pas" /> </f:facet> #{selecao.pais} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Tcnico" /> </f:facet> #{selecao.tecnico} </h:column> </h:dataTable> </html>

19. O prximo passo montar a tela principal de selees agrupando as telas parciais criadas anteriormente. Veja como deve car o arquivo selecoes.xhtml.

1 2 3 4 5 6 7 8 9 10 11 12 13 14

<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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <ui:include src="/cadastro-selecao.xhtml"/> <ui:include src="/listagem-selecoes.xhtml"/> </h:form> </ui:define> </ui:composition> </html>

20. Implemente um Managed Bean para dar suporte s funcionalidades da tela de selees. Adicione um pacote chamado managedbeans. 131 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @ManagedBean public class SelecaoBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager; private Selecao selecao = new Selecao(); public void adiciona() { SelecaoRepository repository = new SelecaoRepository(this.entityManager); repository.adiciona(this.selecao); this.selecao = new Selecao(); } public List<Selecao> getSelecoes() { SelecaoRepository repository = new SelecaoRepository(this.entityManager); return repository.getSelecoes(); } // GETTERS AND SETTERS }

OBS: O Filtro que implementa o padro Open Session in View armazena os Entity Managers em escopo de requisio. Dessa forma podemos injet-los nos Managed Beans com o mesmo escopo atravs da anotao @ManagedProperty. Por outro lado, os Managed Beans com escopos maiores devem utilizar o seguinte cdigo para acessar os Entity Managers.

1 2

ELContext elContext = FacesContext.getCurrentInstance().getELContext(); EntityManager entityManager = (EntityManager) FacesContext.getCurrentInstance(). getApplication().getELResolver().getValue(elContext, null, "entityManager");

13.15

Mensagens de Erro

Vamos personalizar as mensagens de erro criando um arquivo de mensagens em portugus. Devemos registrar esse arquivo no faces-cong.xml.

13.16

Exerccios

21. Crie um pacote na pasta src chamado resources. Adicione nesse pacote um arquivo chamadao Messages.properties com o seguinte contedo:

1 2

javax.faces.component.UIInput.REQUIRED = Campo obrigatrio javax.faces.validator.LengthValidator.MINIMUM = O nmero mnimo de caracteres "{0}".

22. Adicione o seguinte trecho no arquivo faces-cong.xml: www.k19.com.br 132

Projeto
1 2 3 <application> <message-bundle>resources.Messages</message-bundle> </application>

13.17

Removendo Selees

Vamos acrescentar a funcionalidade de remover selees utilizando o suporte de AJAX do JSF 2.

13.18

Exerccios

23. Acrescente uma coluna na tabela que apresenta das selees alterando o arquivo listagemselecoes.xhtml.
1 2 3 4 5 6 7 8 9 10 11 <h:column> <f:facet name="header"> <h:outputText value="Remover" /> </f:facet> <f:ajax event="click" render="@form" listener="#{selecaoBean.remove(selecao)}"> <h:commandLink>Remover</h:commandLink> </f:ajax> </h:column>

24. Implemente um mtodo para remover selees no repositrio de selees, SelecaoRepository.


1 2 3 4 public void remove(Selecao selecao) { this.entityManager.remove(selecao); this.entityManager.flush(); }

25. Adicione um mtodo para remover selees no Managed Bean SelecaoBean.


1 2 3 4 public void remove(Selecao selecao) { SelecaoRepository repository = new SelecaoRepository(this.entityManager); repository.remove(selecao); }

13.19

Otimizando o nmero de consultas

Os getters dos Managed Beans so chamados diversas vezes pelo JSF durante o processamento de uma requisio. Por exemplo, o mtodo getSelecoes() da classe SelecaoBean 133 K19 Treinamentos

Projeto chamado cerca de nove vezes durante o processamento da requisio pgina principal de selees. Esse mtodo chama o getSelecoes() do repositrio que por sua vez faz uma consulta no banco de dados, ou seja, so realizadas cerca de nove consultas iguais para gerar a tela principal de selees. Podemos diminuir o nmero de consultas fazendo os Managed Beans armazenarem o resultado de uma consulta para utiliz-lo o maior nmero possvel de vezes. Apenas devemos tomar cuidado para no manter informaes desatualizadas nos Managed Beans. Por exemplo, quando uma seleo for adicionada ou removida devemos descartar qualquer resultado armazenado no Managed Bean SelecaoBean.

13.20

Exerccios

26. Imprima uma mensagem no mtodo getSelecoes() do Managed Bean SelecaoBean para vericar a quantidade de vezes que ele chamado quando o usurio acessa a url:

http://localhost:8080/K19-CopaDoMundo/selecoes.xhtml.

1 2 3 4 5

public List<Selecao> getSelecoes() { System.out.println("CHAMANDO O REPOSITORIO"); SelecaoRepository repository = new SelecaoRepository(this.entityManager); return repository.getSelecoes(); }

27. Verique quantas vezes a mensagem impressa no console do eclipse acessando a url:

http://localhost:8080/K19-CopaDoMundo/selecoes.xhtml

28. Altere a classe SelecaoBean para esse Managed Bean guardar os resultados das consultas feitas nos repositrios. www.k19.com.br 134

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @ManagedBean public class SelecaoBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager; private Selecao selecao = new Selecao(); private List<Selecao> selecoes; public void adiciona() { SelecaoRepository repository = new SelecaoRepository(this.entityManager); repository.adiciona(this.selecao); this.selecao = new Selecao(); this.selecoes = null; } public void remove(Selecao selecao) { SelecaoRepository repository = new SelecaoRepository(this.entityManager); repository.remove(selecao); this.selecoes = null; } public List<Selecao> getSelecoes() { if (this.selecoes == null) { System.out.println("CHAMANDO O REPOSITORIO"); SelecaoRepository repository = new SelecaoRepository( this.entityManager); this.selecoes = repository.getSelecoes(); } return this.selecoes; } // GETTERS AND SETTERS }

29. Verique quantas vezes a mensagem impressa acessando novamente a url: http://localhost:8080/K19-CopaDoMundo/selecoes.xhtml

13.21

Cadastrando, Listando e Removendo Jogadores

Na tela de jogadores, vamos adicionar um formulrio para cadastrar novos jogadores e uma tabela para apresentar os j cadastrados. Aplicaremos regras de validao especcas para garantir que nenhum dado incorreto seja armazenado no banco de dados. Alm disso, utilizaremos os recursos nativos do JSF 2 para aplicar as tcnicas de AJAX.

13.22

Exerccios

30. Para garantir uma melhor legibilidade da nossa aplicao, criaremos uma tela parcial com os campos e o boto referentes ao cadastramento de jogadores. Adicione o arquivo cadastro-jogador.xhtml na pasta WebContent com o seguinte contedo. 135 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 <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"> <fieldset> <legend>Novo Jogador</legend> <h:panelGrid columns="3"> <h:outputLabel value="Nome: " for="jogador-nome" /> <h:inputText id="jogador-nome" required="true" value="#{jogadorBean.jogador.nome}"> <f:validateLength minimum="6" /> </h:inputText> <h:message for="jogador-nome" styleClass="mensagem-erro" /> <h:outputLabel value="Posio: " for="jogador-posicao" /> <h:inputText id="jogador-posicao" required="true" value="#{jogadorBean.jogador.posicao}"> </h:inputText> <h:message for="jogador-posicao" styleClass="mensagem-erro" /> <h:outputLabel value="Data de Nascimento: " for="jogador-nascimento" /> <h:inputText id="jogador-nascimento" required="true" value="#{jogadorBean.jogador.nascimento.time}"> <f:convertDateTime pattern="dd/MM/yyyy" /> </h:inputText> <h:message for="jogador-nascimento" styleClass="mensagem-erro" /> <h:outputLabel value="Altura (m): " for="jogador-altura" /> <h:inputText id="jogador-altura" required="true" value="#{jogadorBean.jogador.altura}"> </h:inputText> <h:message for="jogador-altura" styleClass="mensagem-erro" /> <h:outputLabel value="Seleo: " for="jogador-selecao" /> <h:selectOneMenu id="jogador-selecao" value="#{jogadorBean.selecaoID}"> <f:selectItems value="#{selecaoBean.selecoes}" var="selecao" itemLabel="#{selecao.pais}" itemValue="#{selecao.id}" /> </h:selectOneMenu> <h:message for="jogador-selecao" styleClass="mensagem-erro" /> <h:commandButton value="Cadastrar" styleClass="botao-formulario"> <f:ajax event="click" execute="@form" listener="#{jogadorBean.adiciona}" render="@form" /> </h:commandButton> </h:panelGrid> </fieldset> </html>

31. Analogamente ao exerccio anterior, vamos criar uma tela parcial para apresentar os jogadores dentro de uma tabela. Adicione o arquivo listagem-jogadores.xhtml na pasta WebContent com o seguinte contedo. www.k19.com.br 136

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 <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"> <h3 class="titulo">Listagem de Jogadores</h3> <h:dataTable id="tabela" value="#{jogadorBean.jogadores}" var="jogador" styleClass="tabela"> <h:column> <f:facet name="header"> <h:outputText value="Id" /> </f:facet> #{jogador.id} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Nome" /> </f:facet> #{jogador.nome} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Posio" /> </f:facet> #{jogador.posicao} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Nascimento" /> </f:facet> <h:outputText value="#{jogador.posicao}"> <f:convertDateTime pattern="dd/MM/yyyy"/> </h:outputText> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Altura" /> </f:facet> #{jogador.altura} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Seleo" /> </f:facet> #{jogador.selecao.pais} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Remover" /> </f:facet> <f:ajax event="click" render="@form" listener="#{jogadorBean.remove(jogador)}"> <h:commandLink>Remover</h:commandLink> </f:ajax> </h:column> </h:dataTable> </html>

137

K19 Treinamentos

Projeto 32. O prximo passo montar a tela principal de jogadores agrupando as telas parciais criadas anteriormente. Veja como deve car o arquivo jogadores.xhtml.

1 2 3 4 5 6 7 8 9 10 11 12 13 14

<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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <ui:include src="/cadastro-jogador.xhtml"/> <ui:include src="/listagem-jogadores.xhtml"/> </h:form> </ui:define> </ui:composition> </html>

33. Implemente um mtodo para remover jogadores no repositrio de jogadores, JogadorRepository.

1 2 3 4

public void remove(Jogador jogador) { this.entityManager.remove(jogador); this.entityManager.flush(); }

34. Adicione um mtodo no repositrio de selees para buscar por id.

1 2 3

public Selecao procura(Lond id) { return this.entityManager.find(Selecao.class, id); }

35. Crie um Managed Bean para trabalhar com a tela de jogadores. www.k19.com.br 138

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @ManagedBean public class JogadorBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager; private Jogador jogador = new Jogador(); private Long selecaoID; private List<Jogador> jogadores; public void adiciona() { SelecaoRepository selecaoRepository = new SelecaoRepository(this.entityManager); Selecao selecao = selecaoRepository.procura(this.selecaoID); this.jogador.setSelecao(selecao); JogadorRepository jogadorRepository = new JogadorRepository(this.entityManager); jogadorRepository.adiciona(this.jogador); this.jogador = new Jogador(); this.jogadores = null; } public void remove(Jogador jogador) { JogadorRepository repository = new JogadorRepository(this.entityManager); repository.remove(jogador); this.jogadores = null; } public List<Jogador> getJogadores() { if (this.jogadores == null) { System.out.println("CHAMANDO O REPOSITORIO"); JogadorRepository repository = new JogadorRepository( this.entityManager); this.jogadores = repository.getJogadores(); } return this.jogadores; } // GETTERS AND SETTERS }

13.23

Removendo Selees com Jogadores

Se uma seleo possui jogadores ela no poder ser removida pois teramos dados inconsistentes no banco de dados. Em outras palavras, teramos jogadores vinculados com selees que j teriam sido removidas. Nesse caso, uma possibilidade informar ao usurio que ele s pode remover selees sem jogadores. Outra possibilidade remover a seleo e os jogadores quando o usurio clicar no link para remover uma seleo. Na verdade, a maneira de proceder depende das regras da aplicao. Vamos supor que a regra da nossa aplicao remover tanto a seleo quanto os jogadores. Devemos alterar o repositrio de selees para aplicar essa regra.

13.24

Exerccios

36. Tente remover pela interface web uma seleo que possua jogadores. 139 K19 Treinamentos

Projeto 37. Altere a classe SelecaoRepository para que na remoo de selees os jogadores correspondentes tambm sejam removidos. A modicao deve ser feita no mtodo remove().

1 2 3 4 5 6 7 8 9 10 11 12 13 14

public void remove(Selecao selecao) { this.entityManager.remove(selecao); Query query = this.entityManager .createQuery("select j from Jogador as j where j.selecao = :selecao"); query.setParameter("selecao", selecao); List<Jogador> jogadores = query.getResultList(); for (Jogador jogador : jogadores) { this.entityManager.remove(jogador); } this.entityManager.flush(); }

13.25

Controle de Acesso

Na maioria dos casos, as aplicaes devem controlar o acesso dos usurios. Vamos implementar um mecanismo de autenticao na nossa aplicao utilizando ltro. As requisies feitas pelos usurios passaro por esse ltro antes de chegar ao controle do JSF. A funo do ltro vericar se o usurio est logado ou no. Se estiver logado o ltro autoriza o acesso. Caso contrrio, o ltro redirecionar o usurio para a tela de login.

13.26

Exerccios

38. Adicione no pacote ltros a seguinte classe: www.k19.com.br 140

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @WebFilter(servletNames = { "Faces Servlet" }) public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpSession session = req.getSession(); if (session.getAttribute("autenticado") != null || req.getRequestURI().endsWith("login.xhtml")) { chain.doFilter(request, response); } else { HttpServletResponse res = (HttpServletResponse) response; res.sendRedirect("login.xhtml"); } } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } }

39. Crie a tela de login adicionando um arquivo chamado login.xhtml na pasta WebContent.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

<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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <h:outputLabel value="Usurio: " for="usuario"/> <h:inputText id="usuario" value="#{loginBean.usuario}" /> <h:outputLabel value="Senha: " for="senha"/> <h:inputSecret id="senha" value="#{loginBean.senha}"/> <h:commandButton value="Entrar" action="#{loginBean.entrar}"/> </h:form> </ui:define> </ui:composition> </html>

40. Implemente o Managed Bean que autentica os usurios. Adicione uma classe no pacote managedbeans chamada LoginBean. 141 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @ManagedBean public class LoginBean { private String usuario; private String senha; public String entrar() { if ("k19".equals(this.usuario) && "k19".equals(this.senha)) { HttpSession session = (HttpSession) FacesContext .getCurrentInstance().getExternalContext() .getSession(false); session.setAttribute("autenticado", true); return "/selecoes"; } else { return "/login"; } } public String sair() { HttpSession session = (HttpSession) FacesContext.getCurrentInstance() .getExternalContext().getSession(false); session.removeAttribute("autenticado"); return "/ate-logo"; } // GETTERS AND SETTERS }

41. Crie uma tela de despedida que ser utilizada quando um usurio sair da aplicao. Adicione um arquivo chamado ate-logo.xhtml na pasta WebContent.

1 2 3 4 5 6 7 8 9 10 11

<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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h3 class="titulo" >At Logo</h3> </ui:define> </ui:composition> </html>

42. Modique o template das telas para acrescentar um boto de sair. www.k19.com.br 142

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <!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"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.png" /> <h:outputLink styleClass="botao" value="selecoes.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.xhtml">Jogadores</ h:outputLink> <h:form style="display: inline;"> <h:commandLink styleClass="botao" action="#{loginBean.sair}">Sair</ h:commandLink> </h:form> <hr/> </div> <ui:insert name="conteudo"> Espao para o contedo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

13.27

Ordem dos ltros

Em alguns casos a ordem de execuo dos ltros afeta o funcionamento da aplicao. No caso da nossa aplicao, a ordem correta de execuo dos ltros primeiro o ltro de autenticao e depois o de controle transacional. No podemos denir a ordem de execuo de uma conjunto de ltros atravs de anotaes. Podemos determinar essa sequncia se os ltros forem registrados no arquivo de conguraes do Web Container, web.xml. A ordem de execuo do ltros a ordem na qual eles aparecem no arquivo de congurao.

13.28

Exerccios

43. Remova a anotao @WebFilter das classes JPAFilter e LoginFilter que esto no pacote ltros.

44. Adicione o seguinte trecho de congurao no arquivo web.xml. 143 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <filter> <filter-name>LoginFilter</filter-name> <filter-class>jpa.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping> <filter> <filter-name>JPAFilter</filter-name> <filter-class>jpa.JPAFilter</filter-class> </filter> <filter-mapping> <filter-name>JPAFilter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping>

13.29

Controle de Erro

Quando uma exception ocorre durante o processamento de uma requisio, o ltro de controle transacional dispara um rollback para desfazer o que j havia sido alterado no banco de dados. Porm, o usurio no informado sobre o problema. Podemos congurar uma pgina de erro padro para ser utilizada toda vez que um erro ocorrer. O ltro de controle transacional deve lanar uma ServletException aps disparar o rollback para informar o Web Container que houve uma falha no processamento da requisio. Depois, devemos congurar uma pgina de erro padro no Web Container.

13.30

Exerccios

45. Modique o ltro de controle transacional para que ele informe o Web Container atravs de uma exception que houve um problema no processamento de uma requisio. www.k19.com.br 144

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class JPAFilter implements Filter { private EntityManagerFactory factory; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { EntityManager entityManager = this.factory.createEntityManager(); request.setAttribute("entityManager", entityManager); entityManager.getTransaction().begin(); chain.doFilter(request, response); try { entityManager.getTransaction().commit(); } catch (Exception e) { entityManager.getTransaction().rollback(); throw new ServletException(e); } finally { entityManager.close(); } } @Override public void init(FilterConfig filterConfig) throws ServletException { this.factory = Persistence.createEntityManagerFactory("copadomundo"); } @Override public void destroy() { this.factory.close(); } }

46. Congure a pgina de erro no arquivo web.xml. Acrescente o seguinte trecho.


1 2 3 4 <error-page> <exception-type>java.lang.Exception</exception-type> <location>/erro.xhtml</location> </error-page>

47. Crie a pgina de erro adicionando um arquivo chamado erro.xhtml na pasta WebContent com o seguinte contedo.
1 2 3 4 5 6 7 8 9 10 11 <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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h3 class="titulo" >Erro Interno</h3> </ui:define> </ui:composition> </html>

145

K19 Treinamentos

Projeto 48. Vamos criar um Managed Bean que sempre gera um problema para testar a pgina de erro. Adicione a classe ErroBean no pacote managedbeans com o seguinte contedo.

1 2 3 4 5 6

@ManagedBean public class ErroBean { public void erro(){ throw new NullPointerException(); } }

49. Modique o template para adicionar um boto que dispara o Managed Bean que sempre gera um erro.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

<!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"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.png" /> <h:outputLink styleClass="botao" value="selecoes.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.xhtml">Jogadores</ h:outputLink> <h:form style="display: inline;"> <h:commandLink styleClass="botao" action="#{loginBean.sair}">Sair</ h:commandLink> <h:commandLink styleClass="botao" action="#{erroBean.erro}">Erro</ h:commandLink> </h:form> <hr/> </div> <ui:insert name="conteudo"> Espao para o contedo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

13.31

Enviando email

Quando um erro ocorre na nossa aplicao, podemos permitir que o usurio envie uma email para os administradores do sistema. Devemos utilizar a especicao JavaMail para que a nossa aplicao JSF tenha a capacidade de enviar mensagems por email. www.k19.com.br 146

Projeto

13.32

Exerccios

50. Altere a tela de erro adicionando um formulrio para o usurio escrever uma mensagem para os administradores da aplicao.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

<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"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h3 class="titulo">Erro Interno</h3> <p>Envie uma mensagem para os administradores do sistema.</p> <h:form styleClass="formulario"> <h:panelGrid columns="3"> <h:outputLabel value="Mensagem: " for="campo-mensagem" /> <h:inputTextarea id="campo-mensagem" value="#{emailBean.mensagem}" required="true" rows="10" cols="30"/> <h:message for="campo-mensagem" /> <h:commandButton value="Enviar" action="#{emailBean.envia}" /> </h:panelGrid> </h:form> </ui:define> </ui:composition> </html>

51. Crie um Managed Bean que envie as mensagens por email utilizando a especicao JavaMail. Observao, utilize usurios, senhas e emails vlidos do gmail para este exerccio. 147 K19 Treinamentos

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @ManagedBean public class EmailBean { private String mensagem; private Properties properties = new Properties(); private Authenticator authenticator; public EmailBean() { this.properties.put("mail.smtp.auth", true); this.properties.put("mail.smtp.port", "465"); this.properties.put("mail.host", "smtp.gmail.com"); this.properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); this.properties.put("mail.smtp.socketFactory.fallback", "false"); this.authenticator = new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("USURIO DO GMAIL", "SENHA DO USURIO "); }; }; } public String envia() throws AddressException, MessagingException { Session session = Session.getInstance(this.properties, this.authenticator); MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress("EMAIL DE ORIGEM")); message.setRecipients(Message.RecipientType.TO, "EMAIL DE DESTINO"); message.setSentDate(new Date()); message.setSubject("Copa do Mundo - Erro"); message.setContent(this.mensagem, "text/plain"); Transport.send(message); return "/selecoes"; } // GETTERS AND SETTERS }

www.k19.com.br

148

You might also like