You are on page 1of 257

TREINAMENTOS

Desenvolvimento Web com JSF2 e JPA2

Desenvolvimento Web com JSF2 e JPA2

31 de janeiro de 2012

Sumrio Sobre a K19 Seguro Treinamento Termo de Uso Cursos 1 Banco de dados 1.1 Sistemas Gerenciadores de Banco de Dados . . 1.2 MySQL Server . . . . . . . . . . . . . . . . . . . 1.3 Bases de dados (Databases) . . . . . . . . . . . 1.4 Criando uma base de dados no MySQL Server 1.5 Tabelas . . . . . . . . . . . . . . . . . . . . . . . 1.6 Criando tabelas no MySQL Server . . . . . . . . 1.7 Operaes Bsicas . . . . . . . . . . . . . . . . . 1.8 Chaves Primria e Estrangeira . . . . . . . . . . 1.9 Exerccios de Fixao . . . . . . . . . . . . . . . 1.10 Exerccios Complementares . . . . . . . . . . . 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 de Fixao . . . . . . . . . . . . . 2.7 Exerccios Complementares . . . . . . . . . 2.8 SQL Injection . . . . . . . . . . . . . . . . . . 2.9 Exerccios de Fixao . . . . . . . . . . . . . 2.10 Exerccios Complementares . . . . . . . . . 2.11 Listando registros . . . . . . . . . . . . . . .
www.k19.com.br

i 1 2 3 4 1 1 2 2 2 3 3 4 5 5 9 25 26 27 28 28 29 29 31 31 32 33 33
i

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

S UMRIO

ii

2.12 2.13 2.14 2.15 2.16 2.17 3

Exerccios de Fixao . . . . Exerccios Complementares Connection Factory . . . . . Exerccios de Fixao . . . . Exerccios Complementares Desaos . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

34 35 35 36 37 38 39 39 39 40 41 41 42 42 44 44 46 48 49 50 53 53 55 55 55 56 57 57 57 58 58 61 61 61 62 66 69 71 77 77 78 78 81 81 88 90

JPA 2 e Hibernate 3.1 Mltiplas sintaxes da linguagem SQL . . . . 3.2 Orientao a Objetos VS Modelo Relacional 3.3 Ferramentas ORM . . . . . . . . . . . . . . . 3.4 O que JPA e Hibernate? . . . . . . . . . . . 3.5 Bibliotecas . . . . . . . . . . . . . . . . . . . 3.6 Congurao . . . . . . . . . . . . . . . . . . 3.7 Mapeamento . . . . . . . . . . . . . . . . . . 3.8 Gerando Tabelas . . . . . . . . . . . . . . . . 3.9 Exerccios de Fixao . . . . . . . . . . . . . 3.10 Manipulando entidades . . . . . . . . . . . 3.11 Exerccios de Fixao . . . . . . . . . . . . . 3.12 Repository . . . . . . . . . . . . . . . . . . . 3.13 Exerccios de Fixao . . . . . . . . . . . . . Web Container 4.1 Necessidades de uma aplicao web 4.2 Web Container . . . . . . . . . . . . . 4.3 Servlet e Java EE . . . . . . . . . . . . 4.4 Exerccios de Fixao . . . . . . . . . 4.5 Aplicao Web Java . . . . . . . . . . 4.6 Exerccios de Fixao . . . . . . . . . 4.7 Processando requisies . . . . . . . 4.8 Servlet . . . . . . . . . . . . . . . . . . 4.9 Exerccios de Fixao . . . . . . . . . 4.10 Frameworks . . . . . . . . . . . . . . Viso Geral do JSF 2 5.1 MVC e Front Controller . . . . . . . 5.2 Congurando uma aplicao JSF . 5.3 Managed Beans . . . . . . . . . . . 5.4 Processamento de uma requisio 5.5 Exemplo Prtico . . . . . . . . . . . 5.6 Exerccios de Fixao . . . . . . . .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

Componentes Visuais 6.1 Estrutura Bsica de uma Pgina JSF 6.2 Formulrios . . . . . . . . . . . . . . 6.3 Caixas de Texto . . . . . . . . . . . . . 6.4 Campos Ocultos . . . . . . . . . . . . 6.5 Caixas de Seleo . . . . . . . . . . . 6.6 Botes e Links . . . . . . . . . . . . . 6.7 Exerccios de Fixao . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

ii

www.k19.com.br

iii

S UMRIO

6.8 6.9 6.10 6.11 6.12 6.13 6.14 6.15 6.16 6.17 6.18 6.19 7

Exerccios Complementares . . Textos e Imagens . . . . . . . . . Exerccios de Fixao . . . . . . Componentes de Organizao . Tabelas . . . . . . . . . . . . . . Exerccios de Fixao . . . . . . Exerccios Complementares . . Mensagens . . . . . . . . . . . . Adicionando JavaScript e CSS . Outros Componentes . . . . . . Exerccios de Fixao . . . . . . Exerccios Complementares . .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

93 93 95 96 97 100 102 102 102 103 104 105 107 107 110 111 113 114 117 117 119 120 123 125 127 129 129 130 131 133 133 139 139 139 141 143 143 146 146 147 148 150 150 153 154 156
iii

Templates e Modularizao 7.1 Templates . . . . . . . . . . . 7.2 Exerccios de Fixao . . . . 7.3 Modularizao . . . . . . . . 7.4 Exerccios de Fixao . . . . 7.5 Exerccios Complementares

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

Navegao 8.1 Navegao Implcita . . . . . . . . 8.2 Navegao Explcita . . . . . . . . 8.3 Exerccios de Fixao . . . . . . . 8.4 Navegaes Esttica e Dinmica 8.5 Exerccios de Fixao . . . . . . . 8.6 Exerccios Complementares . . . Escopos 9.1 Request . . . . . . . . 9.2 View . . . . . . . . . . 9.3 Session . . . . . . . . 9.4 Application . . . . . . 9.5 Exerccios de Fixao

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

10 Converso e Validao 10.1 Converso . . . . . . . . . . . . . 10.2 Conversores Padro . . . . . . . . 10.3 Exerccios de Fixao . . . . . . . 10.4 Exerccios Complementares . . . 10.5 Mensagens de Erro . . . . . . . . 10.6 Exerccios de Fixao . . . . . . . 10.7 Validao . . . . . . . . . . . . . . 10.8 Validadores Padro . . . . . . . . 10.9 Exerccios de Fixao . . . . . . . 10.10 Exerccios Complementares . . . 10.11 Bean Validation . . . . . . . . . . 10.12 Exerccios de Fixao . . . . . . . 10.13 Criando o seu Prprio Conversor 10.14 Exerccios de Fixao . . . . . . .
www.k19.com.br

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

S UMRIO

iv

10.15 Exerccios Complementares . . . . . . 10.16 Criando o seu Prprio Validador . . . 10.17 Exerccios de Fixao . . . . . . . . . . 10.18 Exerccios Complementares . . . . . . 10.19 Criando o seu Prprio Bean Validator 10.20 Exerccios de Fixao . . . . . . . . . . 11 Eventos 11.1 FacesEvent . . . . . . 11.2 Exerccios de Fixao 11.3 PhaseEvent . . . . . . 11.4 Exerccios de Fixao 11.5 SystemEvent . . . . . 11.6 Exerccios de Fixao 11.7 Immediate . . . . . . 11.8 Exerccios de Fixao 12 Ajax 12.1 12.2 12.3 12.4 12.5 12.6

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

158 158 161 162 163 164 167 167 170 172 173 173 175 177 177 181 181 182 183 183 183 184 187 187 187 188 188 189 190 190 194 196

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

Fazendo requisies AJAX . . . . . . . . . . . . . . . . Processando uma parte especca da tela . . . . . . . Recarregando parte da tela . . . . . . . . . . . . . . . . Associando um procedimento a uma requisio AJAX Palavras especiais . . . . . . . . . . . . . . . . . . . . . Exerccios de Fixao . . . . . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

13 Integrao JSF e JPA 13.1 Bibliotecas . . . . . . . . . . . . . . . . . . . . 13.2 Congurao . . . . . . . . . . . . . . . . . . . 13.3 Mapeamento . . . . . . . . . . . . . . . . . . . 13.4 Inicializao e Finalizao . . . . . . . . . . . 13.5 Transaes . . . . . . . . . . . . . . . . . . . . 13.6 Recuperando o EntityManager da Requisio 13.7 Exerccios de Fixao . . . . . . . . . . . . . . 13.8 Otimizando o nmero de consultas ao SGDB 13.9 Exerccios de Fixao . . . . . . . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

A Autenticao 199 A.1 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 B Pginas de Erro 205 B.1 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 C Projeto Futebol K19 C.1 Integrao JSF e JPA . C.2 Exerccios de Fixao C.3 Modelo . . . . . . . . C.4 Exerccios de Fixao C.5 Managed Beans . . . C.6 Exerccios de Fixao C.7 Telas . . . . . . . . . .
iv

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

207 207 207 209 209 211 211 213

www.k19.com.br

S UMRIO

C.8 C.9

Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Autenticao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 223

D Respostas

www.k19.com.br

S UMRIO

vi

vi

www.k19.com.br

S UMRIO

Sobre a K19
A K19 uma empresa especializada na capacitao de desenvolvedores de software. Sua equipe composta por prossionais formados em Cincia da Computao pela Universidade de So Paulo (USP) e que possuem vasta experincia em treinamento de prossionais para rea de TI. O principal objetivo da K19 oferecer treinamentos de mxima qualidade que relacionados s principais tecnologias utilizadas pelas empresas. Atravs desses treinamentos, seus alunos se tornam capacitados para atuar no mercado de trabalho. Visando a mxima qualidade, a K19 mantm as suas apostilas em constante renovao e melhoria, oferece instalaes fsicas apropriadas para o ensino e seus instrutores esto sempre atualizados didtica e tecnicamente.

www.k19.com.br

S UMRIO

Seguro Treinamento
Na K19 o aluno faz o curso quantas vezes quiser! Comprometida com o aprendizado e com a satisfao dos seus alunos, a K19 a nica que possui o Seguro Treinamento. Ao contratar um curso, o aluno poder refaz-lo quantas vezes desejar mediante a disponibilidade de vagas e pagamento da franquia do Seguro Treinamento. As vagas no preenchidas at um dia antes do incio de uma turma da K19 sero destinadas ao alunos que desejam utilizar o Seguro Treinamento. O valor da franquia para utilizar o Seguro Treinamento 10% do valor total do curso.

www.k19.com.br

S UMRIO

Termo de Uso
Termo de Uso
Todo o contedo desta apostila propriedade da K19 Treinamentos. A apostila pode ser utilizada livremente para estudo pessoal . Alm disso, este material didtico pode ser utilizado como material de apoio em cursos de ensino superior desde que a instituio correspondente seja reconhecida pelo MEC (Ministrio da Educao) e que a K19 seja citada explicitamente como proprietria do material. proibida qualquer utilizao desse material que no se enquadre nas condies acima sem o prvio consentimento formal, por escrito, da K19 Treinamentos. O uso indevido est sujeito s medidas legais cabveis.

www.k19.com.br

S UMRIO

TR

S TO EN AM EIN TREINAMENTOS TR EIN AM EN TO S

Conhea os nossos cursos


K01- Lgica de Programao

K11 - Orientao a Objetos em Java

K12 - Desenvolvimento Web com JSF2 e JPA2

K21 - Persistncia com JPA2 e Hibernate

K22 - Desenvolvimento Web Avanado com JFS2, EJB3.1 e CDI

K23 - Integrao de Sistemas com Webservices, JMS e EJB

K31 - C# e Orientao a Objetos

K32 - Desenvolvimento Web com ASP.NET MVC

www.k19.com.br/cursos

www.k19.com.br

CAPTULO

B ANCO DE DADOS

Em geral, as aplicaes necessitam armazenar dados de forma persistente para consult-los posteriormente. Por exemplo, a aplicao de uma livraria precisa armazenar os dados dos livros e dos autores de forma persistente. Suponha que esses dados sejam armazenados em arquivos do sistema operacional. Vrios fatores importantes nos levam a descartar tal opo. A seguir, apresentamos as principais diculdades a serem consideradas na persistncia de dados.

Segurana: O acesso s informaes potencialmente condenciais deve ser controlado de forma que apenas usurios e sistemas autorizados possam manipul-las. Integridade: Restries relacionadas aos dados armazenados devem ser respeitadas para que as informaes estejam sempre consistentes. Consulta: O tempo gasto para realizar as consultas aos dados armazenados deve ser o menor possvel. Concorrncia: Em geral, diversos sistemas e usurios acessaro concorrentemente as informaes armazenadas. Apesar disso, a integridade dos dados deve ser preservada.

Considerando todos esses aspectos, conclumos que um sistema complexo seria necessrio para persistir as informaes de uma aplicao de maneira adequada. Felizmente, tal tipo de sistema j existe e conhecido como Sistema Gerenciador de Banco de Dados (SGBD).

Figura 1.1: Sistema Gerenciador de Banco de Dados

Sistemas Gerenciadores de Banco de Dados


No mercado, h diversas opes de sistemas gerenciadores de banco de dados. Os mais populares so: Oracle
www.k19.com.br

B ANCO DE DADOS

SQL Server MySQL Server PostgreSQL

MySQL Server
Neste treinamento, utilizaremos o MySQL Server, que mantido pela Oracle e amplamente utilizado em aplicaes comerciais. Para instalar o MySQL Server, voc pode utilizar o artigo disponvel em nosso site: http://www.k19.com.br/artigos/instalando-mysql/

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 ou dos livros de uma livraria. Suponha que os dados fossem mantidos sem nenhuma separao lgica. Implementar regras de segurana especcas seria extremamente complexo. Tais regras criam restries quanto ao contedo que pode ser acessado por cada usurio. Por exemplo, determinado usurio poderia ter permisso de acesso aos dados dos clientes do banco, mas no s informaes dos produtos da loja virtual, ou dos livros da livraria. Para obter uma organizao melhor, os dados so armazenados separadamente em um SGDB. Da surge o conceito de base de dados (database). Uma base de dados um agrupamento lgico das informaes de um determinado domnio.

Criando uma base de dados no MySQL Server


Para criar uma base de dados no MySQL Server, podemos utilizar o comando CREATE DATABASE.
mysql > CREATE DATABASE livraria ; Query OK , 1 row affected ( . 2 sec )

Terminal 1.1: Criando uma base de dados.

Podemos utilizar o comando SHOW DATABASES para listar as bases de dados existentes.
mysql > show databases ; + - - - - - - - - - - - - - - - - - - - -+ | Database | + - - - - - - - - - - - - - - - - - - - -+ | information_schema | | livraria | | mysql | | test | + - - - - - - - - - - - - - - - - - - - -+ 4 rows in set ( . 3 sec )

Terminal 1.2: Listando as bases de dados existentes.

www.k19.com.br

B ANCO 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 armazenar conguraes. Quando uma base de dados no mais necessria, ela pode ser removida atravs do comando DROP DATABASE.
mysql > DROP DATABASE livraria ; Query OK , rows affected ( . 8 sec )

Terminal 1.3: Destruindo uma base de dados.

Tabelas
Um servidor de banco de dados dividido em bases de dados com o intuito de separar as informaes de domnios 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. Cliente idade cpf 27 31875638735 32 30045667856 Conta saldo 1000 2000

nome Jos Maria

numero 1 2

limite 500 700

Tabela 1.1: Tabelas para armazenar os dados relacionados aos clientes e s contas

Uma tabela formada por registros (linhas) e os registros so formados por campos (colunas). Por exemplo, considere 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.
mysql > CREATE TABLE livraria . Livro ( -> titulo VARCHAR (255) , -> preco DOUBLE -> ) -> ENGINE = MyISAM ; Query OK , rows affected ( .14 sec )

Terminal 1.4: Criando uma tabela.

As tabelas de uma base de dados podem ser listadas atravs do comando SHOW TABLES. Antes de utilizar esse comando, devemos selecionar uma base de dados atravs do comando USE.
mysql > USE livraria ; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed

www.k19.com.br

B ANCO DE DADOS
mysql > SHOW TABLES ; + - - - - - - - - - - - - - - - - - - - -+ | Tables_in_livraria | + - - - - - - - - - - - - - - - - - - - -+ | Livro | + - - - - - - - - - - - - - - - - - - - -+ 1 row in set ( . sec )

Terminal 1.5: Listando as tabelas de uma base de dados.

Se uma tabela no for mais desejada, ela pode ser removida atravs do comando DROP TABLE.
mysql > DROP TABLE Livro ; Query OK , rows affected ( . sec )

Terminal 1.6: Destruindo uma tabela.

Operaes Bsicas
As operaes bsicas para manipular os dados persistidos so: inserir, ler, alterar e remover. Essas operaes so realizadas atravs de uma linguagem de consulta denominada SQL (Structured Query Language). Essa linguagem oferece quatro comandos bsicos: INSERT, SELECT, UPDATE e DELETE. Esses comandos so utilizados para inserir, ler, alterar e remover registros, respectivamente.
mysql > INSERT INTO Livro ( titulo , preco ) VALUES ( Java , 98.75); Query OK , 1 row affected ( . sec )

Terminal 1.7: Inserindo um registro.

mysql > SELECT * FROM Livro ; + - - - - - - - -+ - - - - - - -+ | titulo | preco | + - - - - - - - -+ - - - - - - -+ | Java | 98.75 | + - - - - - - - -+ - - - - - - -+ 1 row in set ( . sec )

Terminal 1.8: Selecionando registros.

mysql > UPDATE Livro SET preco = 115.9 WHERE titulo = Java ; Query OK , 1 row affected ( . sec ) Rows matched : 1 Changed : 1 Warnings :

Terminal 1.9: Alterando registros.

mysql > SELECT * FROM Livro ; + - - - - - - - -+ - - - - - - -+ | titulo | preco | + - - - - - - - -+ - - - - - - -+ | Java | 115.9 | + - - - - - - - -+ - - - - - - -+ 1 row in set ( . sec )

Terminal 1.10: Selecionando registros.

mysql > DELETE FROM Livro WHERE titulo = Java ; Query OK , 1 row affected ( . sec )

Terminal 1.11: Removendo registros.

www.k19.com.br

5
mysql > SELECT * FROM Livro ; Empty set ( . sec )

B ANCO DE DADOS

Terminal 1.12: Selecionando registros.

Chaves Primria e Estrangeira


Suponha que os livros da nossa livraria sejam classicados por editoras. As editoras possuem nome e telefone. Para armazenar esses dados, uma nova tabela deveria ser criada. Nesse momento, teramos duas tabelas (Livro e Editora). Constantemente, a aplicao da livraria dever 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 dos livros. 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 vinculados a editoras inexistentes, pois no h nenhuma relao explcita entre as tabelas. Para solucionar esses 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 da tabela Livro deve ser uma chave estrangeira associada chave primria da tabela Editora. 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 fazer isso, obteramos uma mensagem de erro.

Exerccios de Fixao
5

www.k19.com.br

B ANCO DE DADOS

Abra um terminal, crie e acesse uma pasta com o seu nome.


cosen@k19 :~ $ mkdir rafael cosen@k19 :~ $ cd rafael / cosen@k19 :~/ rafael$

Terminal 1.13: Criando e acessando uma pasta com o seu nome.

Estando dentro da sua pasta, acesse o MySQL Server utilizando o usurio root e a senha root.
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password :

Terminal 1.14: Logando no MySQL Server.

Caso exista uma base de dados chamada livraria, remova-a. Utilize o comando SHOW DATABASES para listar as bases de dados existentes e o comando DROP DATABASE para remover a base livraria se ela existir.
3
mysql > SHOW DATABASES ; + - - - - - - - - - - - - - - - - - - - -+ | Database | + - - - - - - - - - - - - - - - - - - - -+ | information_schema | | livraria | | mysql | | test | + - - - - - - - - - - - - - - - - - - - -+ 4 rows in set ( . sec ) mysql > DROP DATABASE livraria ; Query OK , 1 row affected ( .12 sec )

Terminal 1.15: Listando as bases de dados existentes e removendo a base livraria.

4 Crie uma nova base de dados chamada livraria. Utilize o comando CREATE DATABASE. Voc vai utilizar esta base nos exerccios seguintes.
mysql > CREATE DATABASE livraria ; Query OK , 1 row affected ( . sec )

Terminal 1.16: Criando a base livraria.

Abra um editor de texto e digite o cdigo abaixo para criar uma tabela com o nome Editora. Depois salve o arquivo com o nome create-table-editora.sql dentro da pasta com o seu nome.
5

1 2 3 4 5 6 7 8

USE livraria ; CREATE TABLE Editora ( id BIGINT NOT NULL AUTO_INCREMENT , nome VARCHAR (255) NOT NULL , email VARCHAR (255) NOT NULL , PRIMARY KEY ( id ) ) ENGINE = InnoDB ;
Cdigo SQL 1.1: Criando a tabela Editora

Dentro do terminal, use o comando source para executar o arquivo que voc acabou de criar.
mysql > source create - table - editora . sql Database changed

www.k19.com.br

7
Query OK , rows affected ( . 8 sec )

B ANCO DE DADOS

Terminal 1.17: Executando a tabela Editora.

Abra um novo editor de texto e digite o cdigo abaixo para criar uma tabela com o nome Livro. Em seguida, salve o arquivo com o nome create-table-livro.sql dentro da pasta com o seu nome.
7

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

USE livraria ; CREATE TABLE Livro ( id BIGINT NOT NULL AUTO_INCREMENT , titulo VARCHAR (255) NOT NULL , preco DOUBLE NOT NULL , editora_id BIGINT NOT NULL , PRIMARY KEY ( id ) , CONSTRAINT fk_editora FOREIGN KEY fk_editora ( editora_id ) REFERENCES Editora ( id ) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB ;
Cdigo SQL 1.2: Criando a tabela Livro

Dentro do terminal, use o comando source para executar o cdigo do arquivo create-table-livro.sql.
mysql > source create - table - livro . sql Database changed Query OK , rows affected ( . 8 sec )

Terminal 1.18: Executando a tabela Livro.

Abra um novo editor de texto e digite o cdigo abaixo para adicionar alguns registros na tabela Editora. Depois salve o arquivo com o nome adicionando-registros-editora.sql dentro da pasta com o seu nome.
9

1 2 3 4 5

INSERT INTO Editora ( nome , email ) VALUES ( Oreilly , oreilly@email . com ) ; INSERT INTO Editora ( nome , email ) VALUES ( Wrox , wrox@email . com ) ; INSERT INTO Editora ( nome , email ) VALUES ( Apress , apress@email . com ) ;
Cdigo SQL 1.3: Adicionando registros na tabela Editora

10 Dentro do terminal, execute o arquivo que voc acabou de criar para adicionar alguns registro na tabela Editora.
mysql > source adicionando - registros - editora . sql Query OK , 1 row affected ( . 3 sec ) Query OK , 1 row affected ( . 4 sec ) Query OK , 1 row affected ( . 4 sec )

Terminal 1.19: Inserindo editoras.

Abra um novo editor de texto e digite o cdigo abaixo para adicionar alguns registros na tabela Livro. Depois salve o arquivo com o nome adicionando-registros-livro.sql dentro da pasta com o seu nome.
11

1 2

INSERT INTO Livro ( titulo , preco , editora_id ) VALUES ( Aprendendo C # , 89.9 , 1) ;

www.k19.com.br

B ANCO DE DADOS
3 4 5 6 INSERT INTO Livro ( titulo , preco , editora_id ) VALUES ( Introduo ao JSF 2 , 122.9 , 3) ; INSERT INTO Livro ( titulo , preco , editora_id ) VALUES ( JSF 2 Avanado , 149.9 , 3) ;
Cdigo SQL 1.4: Adicionando alguns registros na tabela Livro

Dentro do terminal, execute o arquivo que voc acabou de criar para adicionar alguns registros na Livro.
12
mysql > source adicionando - registros - livro . sql Query OK , 1 row affected ( . 2 sec ) Query OK , 1 row affected ( . 4 sec ) Query OK , 1 row affected ( . 4 sec )

Terminal 1.20: Inserindo livros.

13

Consulte os registros da tabela Editora e da tabela Livro. Utilize o comando SELECT.


mysql > SELECT * FROM Editora ; + - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | id | nome | email | + - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | 1 | Oreilly | oreilly@email . com | | 2 | Wrox | wrox@email . com | | 3 | Apress | apress@email . com | + - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ 3 rows in set ( . sec )

Terminal 1.21: Selecionando as editoras.

mysql > SELECT * FROM Livro ; + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ | id | titulo | preco | editora_id | + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ | 1 | Aprendendo C # | 89.9 | 1 | | 2 | Introduo ao JSF 2 | 122.9 | 3 | | 3 | JSF 2 Avanado | 149.9 | 3 | + - - - -+ - - - - - - - - - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ 3 rows in set ( . sec )

Terminal 1.22: Selecionando os livros.

14

Altere alguns dos registros da tabela Livro. Utilize o comando UPDATE.


mysql > UPDATE Livro SET preco =92.9 WHERE id =1; Query OK , 1 row affected ( . 7 sec ) Rows matched : 1 Changed : 1 Warnings :

Terminal 1.23: Alterando livros.

15

Altere alguns dos registros da tabela Editora. Utilize o comando UPDATE.


mysql > UPDATE Editora SET nome = OReilly WHERE id =1; Query OK , 1 row affected ( . 9 sec ) Rows matched : 1 Changed : 1 Warnings :

Terminal 1.24: Alterando editoras.

16

Remova alguns registros da tabela Livro. Utilize o comando DELETE.


mysql > DELETE FROM Livro WHERE id =2; Query OK , 1 row affected ( . 7 sec )

www.k19.com.br

B ANCO DE DADOS

Terminal 1.25: Removendo livros.

17 Remova alguns registros da tabela Editora. Preste ateno para no remover uma editora que tenha algum livro relacionado j adicionado no banco. Utilize o comando DELETE.
mysql > DELETE FROM Editora WHERE id =2; Query OK , 1 row affected ( . 5 sec )

Terminal 1.26: Removendo editoras.

18

Faa uma consulta para buscar todos os livros de uma determinada editora.
mysql > SELECT * FROM Livro as L , Editora as E WHERE L . editora_id = E . id and E . id = 1; + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | id | titulo | preco | editora_id | id | nome | email | + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ | 1 | Aprendendo C # | 92.9 | 1 | 1 | OReilly | oreilly@email . com | + - - - -+ - - - - - - - - - - - - - - -+ - - - - - - -+ - - - - - - - - - - - -+ - - - -+ - - - - - - - - -+ - - - - - - - - - - - - - - - - - - -+ 1 row in set ( . sec )

Terminal 1.27: Selecionando os livros de uma editora.

Exerccios Complementares
Utilize o MySQL Query Browser para refazer os exerccios anteriores.
1 Abra o MySQL Query Browser utilizando localhost como Server Hostname, root como Username e root como Password.

Caso exista uma base de dados chamada livraria, remova-a conforme a gura abaixo.
www.k19.com.br

B ANCO DE DADOS

10

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

10

www.k19.com.br

11

B ANCO DE DADOS

Selecione a base de dados livraria como padro.


www.k19.com.br

11

B ANCO DE DADOS

12

Crie uma tabela chamada Editora conforme as guras abaixo.

12

www.k19.com.br

13

B ANCO DE DADOS

Altere o modo de criao da tabela para InnoDB, conforme mostrado na gura.

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.
www.k19.com.br

13

B ANCO DE DADOS

14

Aps clicar no boto Apply Changes, aparecer uma janela mostrando os comandos SQL gerados. Clique no boto Execute.

Crie uma tabela chamada Livro conforme as guras abaixo. Altere o modo de criao da tabela para InnoDB, conforme mostrado na gura.
6

14

www.k19.com.br

15

B ANCO 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.
www.k19.com.br

15

B ANCO DE DADOS

16

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

17

B ANCO DE DADOS

Adicione alguns registros na tabela Editora. Veja exemplos na gura abaixo.


www.k19.com.br

17

B ANCO DE DADOS

18

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


www.k19.com.br

18

19

B ANCO DE DADOS

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

www.k19.com.br

19

B ANCO DE DADOS

20

20

www.k19.com.br

21
10

B ANCO DE DADOS

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

21

B ANCO DE DADOS

22

12

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

22

www.k19.com.br

23
13

B ANCO DE DADOS

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:

Faa uma consulta para buscar todos os livros associados as suas respectivas editoras. Veja um exemplo na gura abaixo.
14

www.k19.com.br

23

B ANCO DE DADOS

24

24

www.k19.com.br

CAPTULO
SELECT * FROM tbl_funcionarios WHERE nome LIKE %jonas%; INSERT INTO tbl_funcionarios (nome, codigo, salario) VALUES (Rafael, 1234, 1000);

JDBC

No captulo anterior, aprendemos que utilizar bancos de dados uma tima alternativa para armazenar os dados de uma aplicao. Entretanto, voc deve ter percebido que as interfaces disponveis para interagir com o MySQL Server no podem ser utilizadas por qualquer pessoa. Para utiliz-las, necessrio conhecer a linguagem SQL e os conceitos do modelo relacional. Em geral, as interfaces dos outros SGDBs exigem os mesmos conhecimentos.

Figura 2.1: Usurios comuns no possuem conhecimento sobre SQL ou sobre o modelo relacional

Para resolver esse problema, podemos desenvolver aplicaes com interfaces que no exijam conhecimentos tcnicos de SQL ou do modelo relacional para serem utilizadas. Dessa forma, usurios comuns poderiam manipular as informaes do banco de dados atravs dessas aplicaes. Nessa abordagem, os usurios interagem com as aplicaes e as aplicaes interagem com os SGDBs.

www.k19.com.br

Cadastro de Funcionrios Nome: Cdigo: Salrio:

Figura 2.2: Usurios comuns devem utilizar interfaces simples

www.k19.com.br

25

JDBC

26

Driver
As aplicaes interagem com os SGDBs atravs de troca de mensagens. Os SGDBs denem o formato das mensagens. Para no sobrecarregar o canal de comunicao entre as aplicaes e os SGDBs, as mensagens trocadas devem ocupar o menor espao possvel. Geralmente, protocolos binrios so mais apropriados para reduzir o tamanho das mensagens e consequentemente diminuir a carga do canal de comunicao. Por isso, os SGDBs utilizam protocolos binrios.

getReference persist begin getTransaction commit

nd

rollback

10110 111000 10010

Figura 2.3: Diminuindo o tamanho das mensagens para no sobrecarregar o meio de comunicao

Mensagens binrias so facilmente interpretadas por computadores. Por outro lado, so complexas para um ser humano compreender. Dessa forma, o trabalho dos desenvolvedores seria muito complexo, aumentando o custo para o desenvolvimento e manuteno das aplicaes.

11 01 01 01 00 01 11 11 11 0 10 010 11 110 01 0 10 01 10 1 10 111 10 110 11 0 01 01 00 01 101 11 1 010 0

Figura 2.4: Mensagens binrias so altamente complexas para os seres humanos

26

www.k19.com.br

1011010111 0010110001 1010111101 0111011100 0101101001 1101011101 0010110011

1011010111 0010110001 1010111101 0111011100 0101101001 1101011101 0010110011

27

JDBC

Para resolver esse problema e facilitar o desenvolvimento das aplicaes, as empresas proprietrias dos SGDBs, normalmente, desenvolvem e distribuem drivers de conexo. Um driver de conexo atua como um intermedirio entre as aplicaes e os SGDBs. Os drivers de conexo so tradutores de comandos escritos em uma determinada linguagem de programao para comandos denidos de acordo com o protocolo de um SGDB. Utilizando um driver de conexo, os desenvolvedores das aplicaes no manipulam diretamente as mensagens binrias trocadas entre as aplicaes e os SGDBs.

Mais Sobre
Em alguns casos, o protocolo binrio de um determinado SGDB fechado. Consequentemente, a nica maneira de se comunicar com ele atravs de um driver de conexo oferecido pelo fabricante desse SGDB.

JDBC
Suponha que os drivers de conexo fossem desenvolvidos sem nenhum padro. Cada driver teria sua prpria interface, ou seja, seu prprio conjunto de instrues. Consequentemente, os desenvolvedores teriam de conhecer a interface de cada um dos drivers dos respectivos SGDBs que fossem utilizar.

createConnection() Driver MySQL

01110010101110011

openConnection() Driver Oracle

00010011101110010

Figura 2.5: Drivers de conexo sem padronizao

Para facilitar o trabalho do desenvolvedor da aplicao, a plataforma Java possui uma especicao que padroniza os drivers de conexo. A sigla dessa especicao JDBC (Java Database Connectivity). Em geral, as empresas proprietrias dos SGBDs desenvolvem e distribuem drivers de conexo que seguem a especicao JDBC.
www.k19.com.br

27

JDBC

28

getConnection() Driver Oracle JDBC

Driver MySQL JDBC

getConnection()

01110010101110011

00010011101110010

Figura 2.6: Drivers de conexo padronizados pela especicao JDBC

Instalando o Driver JDBC do MySQL Server


Podemos obter um driver de conexo JDBC para o MySQL Server na seguinte url:

http://www.mysql.com/downloads/connector/j/.
A instalao desse driver consiste em descompactar o arquivo obtido no site acima e depois incluir o arquivo jar com o driver no class path da aplicao.

Criando uma conexo


Com o driver de conexo JDBC adicionado aplicao, j possvel criar uma conexo. Abaixo, esto as informaes necessrias para a criao de uma conexo JDBC. Nome do driver JDBC. Endereo (IP e porta) do SGDB. Nome da base de dados. Um usurio do SGBD. Senha do usurio. O nome do driver JDBC, o endereo do SGDB e nome da base de dados so denidos na string de conexo ou url de conexo. Veja o exemplo abaixo:
1 String stringDeConexao = " jdbc : mysql :// localhost / livraria " ;
Cdigo Java 2.1: String de conexo

28

www.k19.com.br

29

JDBC

A classe responsvel pela criao de uma conexo JDBC a DriverManager do pacote java.sql. A string de conexo, o usurio e a senha devem ser passados ao mtodo esttico getConnection() da classe DriverManager para que ela possa criar uma conexo JDBC.
1 2 3 4 5 6 7 8 String urlDeConexao = " jdbc : mysql :// localhost / livraria " ; String usuario = " root " ; String senha = " " ; try { Connection conexao = DriverManager . getConnection ( urlDeConexao , usuario , senha ) ; } catch ( SQLException e ) { e . printStackTrace () ; }
Cdigo Java 2.2: Criando uma conexo JDBC

Inserindo registros
Aps estabelecer uma conexo JDBC, podemos executar operaes. A primeira operao que realizaremos a insero de registros em uma tabela. O primeiro passo para executar essa operao denir o cdigo SQL correspondente.
1 String sql = " INSERT INTO Editora ( nome , email ) VALUES ( K19 , contato@k19 . com . br ) ; " ;
Cdigo Java 2.3: Cdigo SQL correspondente operao de insero

O cdigo SQL correspondente operao que desejamos executar deve ser passado como parmetro para o mtodo prepareStatement() de uma conexo JDBC. Esse mtodo criar um objeto que representa a operao que ser executada. A operao poder ser executada posteriormente atravs do mtodo execute().
1 2 3 4 5 6 // criando um prepared statement PreparedStatement comando = conexao . prepareStatement ( sql ) ; // executando o prepared statement comando . execute () ; comando . close () ;
Cdigo Java 2.4: Criando um prepared statement

Importante
A mesma conexo pode ser reaproveitada para executar vrias operaes. Quando no houver mais operaes a serem executadas, devemos nalizar a conexo JDBC atravs do mtodo close(). Finalizar as conexes JDBC que no so mais necessrias importante pois libera recursos no SGBD.
1 conexao . close () ;
Cdigo Java 2.5: Finalizando uma conexo JDBC

Exerccios de Fixao
www.k19.com.br

29

JDBC

30

1 2 3

No Eclipse, crie um projeto Java chamado JDBC. Crie uma pasta chamada lib no projeto JDBC.

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 a pasta lib do projeto JDBC.
4

Adicione o arquivo mysql-connector-java-5.1.13-bin.jar ao build path. Veja a imagem abaixo.

Crie uma classe chamada InsereEditora, e adicione o seguinte contedo ao arquivo:


import import import import java . sql . Connection ; java . sql . DriverManager ; java . sql . PreparedStatement ; java . util . Scanner ;

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

public class InsereEditora { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; System . out . println ( " Digite o nome da editora : " ) ;

30

www.k19.com.br

31
2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 String nome = entrada . nextLine () ; System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; String sql = " INSERT INTO Editora ( nome , email ) " + " VALUES ( " + nome + " , " + email + " ) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.6: InsereEditora.java

JDBC

Execute e verique se o registro foi inserido com sucesso na base de dados.

Exerccios Complementares
1

Crie uma classe chamada InsereLivros para cadastrar livros na base de dados.

SQL Injection
A implementao da insero de registros feita anteriormente possui uma falha grave. Os dados obtidos do usurio atravs do teclado no so tratados antes de serem enviados para o SGDB. Esses dados podem conter caracteres especiais. Se esses caracteres no so tratados, o comportamento esperado da operao afetado. Eventualmente, registros no so inseridos como deveriam ou brechas de segurana podem se abrir. Por exemplo, considere a classe InsereEditora do exerccio de xao. Se o usurio digitar OReilly e oreilly@email.com, o cdigo SQL gerado pela aplicao seria:
1 INSERT INTO Editora ( nome , email ) VALUES ( O Reilly , oreilly@email . com )

Observe que o caractere aspas simples aparece cinco vezes no cdigo SQL acima. O SGDB no saberia dizer onde de fato termina o nome da editora. Ao tentar executar esse cdigo, um erro de sintaxe lanado pelo MySQL Server. Para resolver esse problema manualmente, devemos adicionar o caractere \ antes do caractere aspas simples que faz parte do nome da editora. Na sintaxe do MySQL Server, o caractere \ deve ser acrescentado imediatamente antes de todo caractere especial que deve ser tratado como um caractere comum.
1 INSERT INTO Editora ( nome , email ) VALUES ( O \ Reilly , oreilly@email . com )

Os valores recebidos dos usurios devem ser analisados e os caracteres especiais contidos nesses
www.k19.com.br

31

JDBC

32

valores devem ser tratados. Esse processo extremamente trabalhoso, pois o conjunto de caracteres especiais e a forma de trat-los diferente em cada SGDB. A responsabilidade do tratamento dos caracteres especiais contidos nos valores de entrada dos usurios pode ser repassada para os drivers JDBC. Dessa forma, o cdigo das aplicaes se torna independente das particularidades desse processo para cada SGDB.

Mais Sobre
O processo de tratamento dos caracteres especiais das entradas dos usurios denominado sanitize.

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

// lendo as entradas do usurio System . out . println ( " Digite o nome da editora : " ) ; String nome = entrada . nextLine () ; System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; // cdigo sql com marcadores para as entradas do usurio String sql = " INSERT INTO Editora ( nome , email ) VALUES (? , ?) " ; // criando um comando a partir do cdigo SQL PreparedStatement comando = conexao . prepareStatement ( sql ) ; // adicionando as entradas do usurios no comando // o processo de sanitizao ocorre aqui comando . setString (1 , nome ) ; comando . setString (2 , email ) ;
Cdigo Java 2.10: Sanitizando as entradas dos usurios

Observe que o cdigo SQL foi denido com parmetros atravs do caractere ?. Antes de executar o comando, necessrio determinar os valores dos parmetros. Essa tarefa pode ser realizada atravs do mtodo setString(), que recebe o ndice (posio) do parmetro no cdigo SQL e o valor correspondente. Esse mtodo faz o tratamento dos caracteres especiais contidos nos valores de entrada do usurio de acordo com as regras do SGDB utilizado.

Exerccios de Fixao
Provoque um erro de SQL Injection na classe InsereEditoras. (Dica: tente entradas com aspas simples.)
6 7

Altere o cdigo para eliminar o problema do SQL Injection.


import import import import java . sql . Connection ; java . sql . DriverManager ; java . sql . PreparedStatement ; java . util . Scanner ;

1 2 3 4 5 6 7 8 9 1 11

public class InsereEditora { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ;

32

www.k19.com.br

33
12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41

JDBC

Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; 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 sql = " INSERT INTO Editora ( nome , email ) VALUES (? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , nome ) ; comando . setString (2 , email ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.11: InsereEditora.java

Exerccios Complementares
Provoque um erro de SQL Injection na classe InsereLivros. (Dica: tente entradas com aspas simples.)
2 3 4

Altere o cdigo para eliminar o problema do SQL Injection. Agora tente causar novamente o problema de SQL Injection ao inserir novos livros.

Listando registros
O processo para executar um comando de consulta bem parecido com o processo de inserir registros. O primeiro passo denir a consulta em SQL.
1 2 3 4 5 6 String sql = " SELECT * FROM Editora ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; ResultSet resultado = comando . executeQuery () ;
Cdigo Java 2.13: Realizando uma consulta.

A diferena que para executar um comando de consulta necessrio utilizar o mtodo executeQuery() ao invs do execute(). Esse mtodo devolve um objeto da interface java.sql.Resultwww.k19.com.br

33

JDBC

34

Set, que responsvel por armazenar os resultados da consulta.


Os dados contidos no ResultSet podem ser acessados atravs de mtodos, como o getString, getInt, getDouble, 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 " ) ;
Cdigo Java 2.14: Recuperando os dados de um ResultSet

O cdigo acima mostra como os campos do primeiro registro da consulta so recuperados. Para recuperar os dados dos outros registros necessrio avanar o ResultSet 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 " ) ;
Cdigo Java 2.15: Avanando o ResultSet

O prprio mtodo next() devolve um valor booleano para indicar se o ResultSet 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 " ) ; }
Cdigo Java 2.16: Iterando os registros do ResultSet

Exerccios de Fixao
8

Insira algumas editoras utilizando a classe InsereEditora que voc criou anteriormente.

9 Adicione uma nova classe ao projeto chamada ListaEditoras. O objetivo listar as editoras que foram salvas no banco.

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

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 :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; try {

34

www.k19.com.br

35
13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38

2.14. C ONNECTION FACTORY


System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; String sql = " SELECT * FROM Editora ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; 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 conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.17: ListaEditoras.java

Exerccios Complementares
5

Crie uma classe para listar os livros cadastrados na base de dados.

Connection 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, cada ocorrncia da url de conexo precisaria ser modicada. A probabilidade de algum ponto no ser corrigido grande. Para diminuir o trabalho de manuteno, podemos implementar uma classe responsvel pela criao e distribuio de conexes. A url de conexo deve ser denida nessa classe e somente nela. Consequentemente, alteraes nas informaes contidas na url de conexo afetariam apenas uma classe da aplicao.
1 2 3 4 5 6 7 8 9 import java . sql . Connection ; import java . sql . DriverManager ; import java . sql . SQLException ; public class ConnectionFactory { public static Connection createConnection () { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ;

www.k19.com.br

35

JDBC
1 11 12 13 14 15 16 17 18 19 2

36

Connection conexao = null ; try { conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; } catch ( SQLException e ) { e . printStackTrace () ; } return conexao ; } }
Cdigo Java 2.19: ConnectionFactory.java

Agora, podemos obter uma nova conexo apenas chamando o mtodo createConnection(). 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.

Exerccios de Fixao
10

Adicione uma nova classe chamada ConnectionFactory com o cdigo abaixo.


import java . sql . Connection ; import java . sql . DriverManager ; import java . sql . SQLException ; public class ConnectionFactory { public static Connection createConnection () { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; Connection conexao = null ; try { conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; } catch ( SQLException e ) { e . printStackTrace () ; } return conexao ; } }
Cdigo Java 2.20: ConnectionFactory.java

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

Altere as classes InsereEditora e ListaEditoras para que elas utilizem a fbrica de conexo. Depois, execute-as novamente.
11

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

import java . sql . Connection ; import java . sql . PreparedStatement ; import java . util . Scanner ; public class InsereEditora { public static void main ( String [] args ) { Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; System . out . println ( " Digite o nome da editora : " ) ; String nome = entrada . nextLine () ;

36

www.k19.com.br

37
15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35

2.14. C ONNECTION FACTORY

System . out . println ( " Digite o email da editora : " ) ; String email = entrada . nextLine () ; String sql = " INSERT INTO Editora ( nome , email ) " + " VALUES (? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , nome ) ; comando . setString (2 , email ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.21: InsereEditora.java

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

import java . sql . Connection ; import java . sql . PreparedStatement ; import java . sql . ResultSet ; public class ListaEditoras { public static void main ( String [] args ) { try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; String sql = " SELECT * FROM Editora ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; 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 conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.22: ListaEditoras.java

Exerccios Complementares
Altere as classes InsereLivro e ListaLivros para que elas utilizem a fbrica de conexo. Depois, execute-as novamente.
6

www.k19.com.br

37

JDBC

38

Desaos
1 2

Implemente a remoo de editoras pelo id. Implemente a alterao dos dados das editoras pelo id.

38

www.k19.com.br

CAPTULO
Driver Oracle JDBC Driver MySQL JDBC

JPA 2 E H IBERNATE

Mltiplas sintaxes da linguagem SQL


No captulo anterior, utilizamos a especicao JDBC para fazer uma aplicao Java interagir com os SGDBs. Nessa interao, as consultas so denidas com a linguagem SQL. A sintaxe dessa linguagem diferente em cada SGDB. Dessa forma, a complexidade do trabalho dos desenvolvedores aumenta. Para resolver esse problema, as consultas deveriam ser denidas atravs de um mecanismo independente da linguagem SQL.

SELECT columns FROM livros ORDER BY autor ASC LIMIT 100

SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY autor ASC) AS rownumber, id, titulo, autor FROM livros ) WHERE rownumber <= 100

Figura 3.1: Diferentes sintaxes da linguagem SQL

Orientao a Objetos VS Modelo Relacional


Outro problema na comunicao entre uma aplicao Java e um SGDB o conito de paradigmas. Os SGDBs so organizados seguindo o modelo relacional. Por outro lado, as aplicaes Java
www.k19.com.br

39

JPA 2 E H IBERNATE

40

utilizam o modelo orientado a objetos. A transio de dados entre o modelo relacional 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.

tbl_editoras Livro id = 1 titulo = Os Lusadas autor = Lus Vaz de Cames editora = 1 Editora id = 1 nome = Livraria Cultura Livro id = 2 titulo = Vidas Secas autor = Graciliano Ramos editora = 1 tbl_livros id 1 2 3 4 titulo Os Lusadas Vidas Secas Dom Casmurro O Cortio autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo editora_id 1 1 3 2 id 1 2 3 4 nome Cultura FTDA Globo Scipione

ORIENTAO A OBJETOS

MODELO RELACIONAL

Figura 3.2: Modelo Orientado a Objetos vs Modelo Relacional

Ferramentas ORM
Para facilitar a comunicao entre aplicaes Java que seguem o modelo orientado a objetos e os SGDBs que seguem o modelo relacional, podemos utilizar ferramentas que automatizam a transio de dados entre as aplicaes e os SGDBs. Essas ferramentas so conhecidas como ferramentas ORM (Object Relational Mapper). As ferramentas ORM oferecem mecanismos de consultas independentes da linguagem SQL. Dessa forma, o acoplamento entre as aplicaes e os SGDBs diminui drasticamente. A principal ferramenta ORM para Java utilizada no mercado o Hibernate. Mas, existem outras que possuem o mesmo objetivo.
40
www.k19.com.br

41

JPA 2 E H IBERNATE

tbl_livros id 1 2 3 4 titulo Os Lusadas Vidas Secas Dom Casmurro O Cortio autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo editora_id 1 1 3 2

FERRAMENTA id = 1 ORM titulo = Os Lusadas autor = Lus Vaz de


Cames editora = 1

Livro

Livro id = 2 titulo = Vidas Secas autor = Graciliano Ramos editora = 1

Figura 3.3: Transformao dos dados do Modelo Relacional para o Modelo Orientado a Objetos

tbl_livros

Livro id = 1 titulo = Os Lusadas autor = Lus Vaz de Cames editora = 1

Livro id = 2 titulo = Vidas Secas autor = Graciliano Ramos editora = 1

FERRAMENTA 1 Os Lusadas 2 ORM Vidas Secas


3 4 Dom Casmurro O Cortio

id

titulo

autor Lus Vaz de Cames Graciliano Ramos Machado de Assis Alusio Azevedo

editora_id 1 1 3 2

Figura 3.4: Transformao dos dados do Modelo Orientado a Objetos para o Modelo Relacional

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 especica um conjunto de classes e mtodos que as ferramentas 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 EclipseLink e OpenJPA. Optamos por utilizar o Hibernate por ele ser o mais antigo e mais utilizado atualmente. Caso voc queira utilizar outra ferramenta ORM, poder aplicar os conceitos aqui aprendidos justamente porque 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.

Bibliotecas
Antes de comear a utilizar o Hibernate, necessrio baixar do site ocial o bundle que inclui os
www.k19.com.br

41

JPA 2 E H IBERNATE

42

jars do hibernate e todas as suas dependncias. Neste curso, utilizaremos a verso 3.5.1. A url do site ocial do Hibernate http://www.hibernate.org/.

Congurao
Para congurar o Hibernate em uma aplicao, devemos criar um arquivo chamado persistence.xml. O contedo desse arquivo possuir 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 persistence.xml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " 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:33 6 / K19 - DB " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 3.1: persistence.xml

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

Mais Sobre
Consulte o artigo da K19 sobre congurao do Hibernate e MySQL na seguinte url: http://www.k19.com.br/artigos/configurando-hibernate-com-mysql/.

Mapeamento
Um dos principais objetivos das ferramentas ORM estabelecer o mapeamento entre os conceitos do modelo orientado a objetos e os conceitos do modelo relacional. Esse mapeamento pode ser denido atravs de XML ou de maneira mais prtica com anotaes Java.
42
www.k19.com.br

43

JPA 2 E H IBERNATE

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 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 @Entity 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 @Entity so mapeados para colunas na tabela correspondente classe. Outra vez, por conveno, as colunas possuem os mesmos nomes dos atributos. Novamente, podemos alterar esse padro utilizando a anotao @Column. @Id Utilizada para indicar qual atributo de uma classe anotada com @Entity ser mapeado para a chave primria da tabela correspondente classe. Geralmente o atributo anotado com @Id do tipo Long. @GeneratedValue Geralmente vem acompanhado da anotao @Id. Serve para indicar que o atributo gerado pelo banco, no momento em que um novo registro inserido. @Table Utilizada para alterar o nome padro da tabela. Ela recebe o parmetro name para indicar qual nome deve ser utilizado na tabela. Veja o exemplo:
1 2 3 4 5 @Table ( name = " Publisher " ) @Entity public class Editora { // ... }
Cdigo Java 3.1: Editora.java

@Column Utilizado para alterar o nome da coluna que ser usado 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 5 6 @Entity public class Editora { @Column ( name = " publisher_name " , nullable = false ) private String nome ; }
Cdigo Java 3.2: Editora.java

@Transient Serve para indicar que um atributo no deve ser persistido, ou seja, os atributos anotados com @Transient 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 String, Byte[], byte[] ou java.sql.Blob. @Temporal Utilizado para atributos do tipo Calendar ou Date. Por padro, tanto data quanto hora so armazenados no banco de dados. Mas, com a anotao @Temporal, podemos mandar persistir somente a data ou somente a hora.
www.k19.com.br

43

JPA 2 E H IBERNATE
1 2 3 4 5 6 7 @Entity public class Livro { @Temporal ( TemporalType . DATE ) private Calendar publicacao ; // ... }
Cdigo Java 3.3: Livro.java

44

Gerando Tabelas
Uma das vantagens de se 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 um mtodo da classe Persistence, o createEntityManagerFactory(String entityUnit). O parmetro entityUnit permite escolher, pelo nome, uma unidade de persistncia denida no persistence.xml. A poltica de criao das tabelas pode ser alterada modicando o valor a propriedade hibernate.hbm2ddl.auto no arquivo persistence.xml. Podemos, por exemplo, fazer com que o Hibernate sempre sobrescreva as tabelas existentes, bastando denir a propriedade hibernate.hbm2ddl.auto com o valor create-drop.
1 < property name = " hibernate . hbm2ddl . auto " value = " create - drop " / >

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 hibernate.hbm2ddl.auto deve ser update.
1 < property name = " hibernate . hbm2ddl . auto " value = " update " / >

Exerccios de Fixao
Crie um projeto no Eclipse chamado JPA2-Hibernate e feche o projeto JDBC para no gerar confuso na hora de manipular os arquivos.
1 2 3

Crie uma pasta chamada lib dentro do projeto JPA2-Hibernate.

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 JPA2-Hibernate. 5

Entre na pasta K19-Arquivos/SLF4J da rea de Trabalho e copie os jars para pasta lib do
www.k19.com.br

44

45

JPA 2 E H IBERNATE

projeto JPA2-Hibernate.
6 Entre na pasta K19-Arquivos/Log4J da rea de Trabalho e copie o arquivo log4j-1.2.16.jar para pasta lib do projeto JPA2-Hibernate.

Adicione os jars da pasta lib ao build path do projeto JPA2-Hibernate. Voc deve selecionar os arquivos e adicion-los no build path.
7 8 9

Crie uma pasta chamada META-INF na pasta src no projeto JPA2-Hibernate. Crie o arquivo de conguraes persistence.xml na pasta META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " livraria - pu " 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:33 6 / livraria " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 3.4: persistence.xml

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

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.
10

1 2 3 4 5 6 7 8 9 1 11

@Entity public class Editora { @Id @GeneratedValue private Long id ; private String nome ; private String email ; // GETTERS AND SETTERS }
Cdigo Java 3.4: Editora.java

11 12

Apague a tabela Livro e depois a Editora.

Congure o Log4J criando um arquivo chamado log4j.properties na pasta src do projeto JPA2-Hibernate.

www.k19.com.br

45

JPA 2 E H IBERNATE
1 2 3 4 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 ] % -5 p % c - % m % n
Arquivo de Propriedades 3.1: log4j.properties

46

Gere as tabelas atravs da classe Persistence. Para isso, crie uma classe com mtodo main. Obs: As classes devem ser importadas do pacote javax.persistence.
13

1 2 3 4 5 6 7 8

public class GeraTabelas { public static void main ( String [] args ) { EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " livraria - pu " ) ; factory . close () ; } }
Cdigo Java 3.5: GeraTabelas.java

Atravs do MySQL Query Browser, verique se a tabela Editora foi criada corretamente.

Manipulando entidades
Para manipular as entidades da nossa aplicao, devemos utilizar um EntityManager que obtido atravs de uma EntityManagerFactory.
1 2 3 4 EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " K19 " ) ; EntityManager manager = factory . createEntityManager () ;
Cdigo Java 3.6: Obtendo um EntityManager

Persistindo
Para armazenar as informaes de um objeto no banco de dados, o primeiro passo utilizar o mtodo persist() do EntityManager.
1 2 3 4 5 Editora novaEditora = new Editora () ; novaEditora . setNome ( " K19 - Livros " ) novaEditora . setEmail ( " contato@k19 . com . br " ) ; manager . persist ( novaEditora ) ;
Cdigo Java 3.7: Marcando um objeto para ser persistido

importante destacar que o mtodo persist() apenas marca os objetos que devem ser armazenados no banco de dados. Os objetos sero armazenados aps a chamada do mtodo commit(), como veremos adiante.
46
www.k19.com.br

47

JPA 2 E H IBERNATE

Buscando
Para obter um objeto que contenha informaes do banco de dados, podemos utilizar o mtodo find() ou o mtodo getReference() do EntityManager.
1 2 Editora editora1 = manager . find ( Editora . class , 1 L ) ; Editora editora2 = manager . getReference ( Editora . class , 2 L ) ;
Cdigo Java 3.8: Obtendo objetos com informaes do banco de dados

H uma diferena entre os dois mtodos bsicos de busca find() e getReference(). O mtodo find() recupera os dados desejados imediatamente. J o mtodo getReference() posterga essa tarefa at a primeira chamada de um mtodo get do objeto.

Removendo
Para remover o registro correspondente a um objeto, devemos utilizar o mtodo remove() do EntityManager.
1 2 Editora editora1 = manager . find ( Editora . class , 1 L ) ; manager . remove ( editora1 ) ;
Cdigo Java 3.9: Marcando um objeto para ser removido

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

Listando
Para obter uma listagem com todos os objetos referentes aos registros de uma tabela, podemos utilizar a linguagem de consulta do JPA, a JPQL, que muito parecida com a linguagem SQL. A principal vantagem do JPQL em relao ao SQL que a sintaxe do JPQL no depende do SGDB utilizado.
1 2 Query query = manager . createQuery ( " SELECT e FROM Editora e " ) ; List < Editora > editoras = query . getResultList () ;
Cdigo Java 3.11: Obtendo uma lista de objetos com informaes do banco de dados

www.k19.com.br

47

JPA 2 E H IBERNATE

48

Transaes
As modicaes realizadas nos objetos administrados por um EntityManager 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 EntityManager que administra os objetos que desejamos sincronizar. Para abrir uma transao, utilizamos o mtodo begin().
1 manager . getTransaction () . begin () ;
Cdigo Java 3.12: Abrindo uma transao

Com uma transao aberta, podemos sincronizar os dados da memria com os dados do banco atravs do mtodo commit().
1 2 3 4 5 Editora editora = manager . find ( Editora . class , 1 L ) ; editora . setNome ( " K19 - Livros e Publicaes " ) ; manager . getTransaction () . begin () ; manager . getTransaction () . commit () ;
Cdigo Java 3.13: Sincronizando com o mtodo commit()

Exerccios de Fixao
No arquivo de conguraes persistence.xml, altere o valor da propriedade hibernate.hbm2ddl.auto para update. Assim, as tabelas no sero recriadas a cada execuo e sim apenas atualizadas.
14 15

Crie um teste para inserir editoras no banco de dados.


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 () ; manager . close () ; factory . close () ; } }

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

48

www.k19.com.br

49

JPA 2 E H IBERNATE

Cdigo Java 3.14: InsereEditoraComJPA.java

16

Crie um teste para listar as editoras inseridas no banco de dados.


public class ListaEditorasComJPA { public static void main ( String [] args ) { EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " livraria - pu " ) ; 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 () ) ; } manager . close () ; factory . close () ; } }
Cdigo Java 3.15: ListaEditorasComJPA.java

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

Repository
A interface EntityManager 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 EntityManager 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 ferramentas ORM como o Hibernate.
1 2 3 4 5 6 7 8 9 1 11 12 13 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 ) ; }

www.k19.com.br

49

JPA 2 E H IBERNATE
14 15 16 17 18 public List < Editora > buscaTodas () { Query query = this . manager . createQuery ( " SELECT e FROM Editora e " ) ; return query . getResultList () ; } }
Cdigo Java 3.16: EditoraRepository.java

50

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 () ;
Cdigo Java 3.17: Utilizando um repositrio

Exerccios de Fixao
17

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


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 () ; } }
Cdigo Java 3.18: EditoraRepository.java

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

18

Altere a classe InsereEditoraComJPA para que ela utilize o repositrio de editoras.


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 () ) ;

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

50

www.k19.com.br

51
18 19 2 21 22 23 24 25 26 27 28 29 System . out . println ( " Digite o email da editora : " ) ; novaEditora . setEmail ( entrada . nextLine () ) ; editoraRepository . adiciona ( novaEditora ) ; manager . getTransaction () . begin () ; manager . getTransaction () . commit () ; manager . close () ; factory . close () ; } }
Cdigo Java 3.19: InsereEditoraComJPA.java

JPA 2 E H IBERNATE

19

Altere a classe ListaEditorasComJPA para que ela utilize o repositrio de editoras.


public class ListaEditorasComJPA { public static void main ( String [] args ) { EntityManagerFactory factory = Persistence . createEntityManagerFactory ( " livraria " ) ; EntityManager manager = factory . createEntityManager () ; EditoraRepository editoraRepository = new EditoraRepository ( manager ) ; List < Editora > editoras = editoraRepository . buscaTodas () ; for ( Editora e : editoras ) { System . out . println ( " EDITORA : " + e . getNome () + " - " + e . getEmail () ) ; } manager . close () ; factory . close () ; } }
Cdigo Java 3.20: ListaEditorasComJPA.java

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

www.k19.com.br

51

JPA 2 E H IBERNATE

52

52

www.k19.com.br

CAPTULO

W EB C ONTAINER

Necessidades de uma aplicao web

HTTP

Os usurios de uma aplicao web utilizam navegadores (browsers) para interagir com essa aplicao. A comunicao entre navegadores e uma aplicao web realizada atravs de requisies e respostas denidas pelo protocolo HTTP Dessa forma, os desenvolvedores de aplicao web devem . estar preparados para trabalhar com o protocolo HTTP.

Acesso simultneo

Alm disso, na grande maioria dos casos, as aplicaes web devem ser acessadas por diversos usurios ao mesmo tempo. Consequentemente, os desenvolvedores web devem criar ou utilizar algum mecanismo eciente que permita esse tipo de acesso.

Contedo dinmico

As pginas de uma aplicao web devem ser geradas dinamicamente. Por exemplo, quando um usurio de uma aplicao de email acessa a sua caixa de entrada, ele deseja ver todos os emails enviados at aquele momento. A pgina contendo a lista de emails deve ser gerada novamente toda vez que essa pgina for requisitada. Consequentemente, os desenvolvedores web devem criar ou utilizar algum mecanismo eciente que permita que o contedo das pginas das aplicaes web seja gerado dinamicamente.
www.k19.com.br

53

W EB C ONTAINER

54

Aplicao Web
Requisio HTTP

TP

HT

qu

isi

Re

www.k19.com.br

www.k19.com.br

Cursos

Artigos

Apostilas

Figura 4.1: Necessidades de uma aplicao web

Soluo
Resolver os trs problemas apresentados tomaria boa parte do tempo de desenvolvimento, alm de exigir conhecimentos tcnicos extremamente especcos por parte dos desenvolvedores. Para facilitar o desenvolvimento de aplicaes web, a plataforma Java oferece uma soluo genrica que pode ser utilizada para desenvolver aplicaes web. Conheceremos essa soluo a seguir.

Aplicao Web
Web Container
Requisio HTTP

TP

HT

qu

isi

www.k19.com.br

Re

www.k19.com.br

Cursos

Artigos

Apostilas

Figura 4.2: Web Container

54

www.k19.com.br

q Re P TT
www.k19.com.br

ui sp Re os H ta

o i

HT

TP

qu Re aH st TT P
www.k19.com.br

isi Re o sp

HT

TP
Resposta HTTP Resposta HTTP

Re sp o st a HT TP Re s po st a HT TP

55

W EB C ONTAINER

Web Container
Uma aplicao web Java deve ser implantada em um Web Container para obter os recursos fundamentais que ela necessita. Um Web Container responsvel: Pelo envio e recebimento de mensagens HTTP. Por permitir que as aplicaes sejam acessadas simultaneamente por vrios usurios de uma maneira eciente. Por permitir que as pginas de uma aplicao web sejam geradas 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.

Servlet e Java EE
Como comum na plataforma Java, foi denida uma especicao para padronizar a interface dos recursos oferecidos pelos Web Containers. Essa especicao chamada Servlet e atualmente est na verso 3. Para consult-la, acesse http://jcp.org/en/jsr/detail?id=315. A especicao Servlet faz parte do Java EE. O Java EE uma especicao que agrupa diversas outras especicaes. Para consult-la, acesse http://jcp.org/en/jsr/detail?id=316. Apesar das especicaes, os Web Containers possuem algumas diferenas nas conguraes que devem ser realizadas pelos desenvolvedores. Dessa forma, no h 100% de portabilidade. Contudo, a maior parte das conguraes e do modelo de programao padronizado. Sendo assim, se voc conhece bem um dos Web Containers, tambm conhece bastante dos outros. Neste treinamento, optamos pela utilizao do servidor de aplicao Glasssh 3.0. Esse servidor segue a especicao Java EE 6 e portanto contm um Web Container. Mostraremos, a seguir, a sua instalao e congurao.

Mais Sobre
Consulte os artigos da K19 sobre instalao e congurao do Glasssh para mais detalhes.

http://www.k19.com.br/artigos/instalando-glassfish/ http://www.k19.com.br/artigos/configurando-o-gassfish-no-ide-eclipse/

Exerccios de Fixao
1

Na rea de Trabalho, entre na pasta K19-Arquivos e copie o arquivo glassfish-3. .1-with-hiwww.k19.com.br

55

W EB C ONTAINER

56

bernate.zip para o seu Desktop. Descompacte-o na prpria rea de Trabalho.


2

Ainda na rea de Trabalho, entre na pasta glassfishv3/glassfish/bin e execute o script

startserv para iniciar o Glasssh.


Verique se o Glasssh est em execuo, acessando http://localhost:8 8 atravs de um navegador.
3 4

Finalize 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.

Inicialize o Glasssh pela view Servers e verique se ele est funcionando, acessando http: //localhost:8 8 .
6 7

Finalize o Glasssh pela view Servers.

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/ WEB-INF/ classes/ lib/ web.xml A pasta K19-App a raiz da aplicao. Ela pode ter qualquer nome. A pasta WEB-INF deve ser criada dentro da pasta raiz. O contedo da pasta WEB-INF no pode ser acessado diretamente pelos usurios da aplicao. Por outro lado, os arquivos dentro da pasta raiz da aplicao mas fora da pasta WEB-INF podem ser acessados diretamente atravs de um navegador. As pastas classes e lib devem ser criadas dentro da pasta WEB-INF. O cdigo compilado da aplicao deve ser salvo na pasta classes. Os jars das bibliotecas extras que sero utilizadas devem ser colocados na pasta lib. O arquivo web.xml contm conguraes do Web Container e deve ser criado na pasta WEB-INF. Em geral, as IDEs criam toda a estrutura de pastas exigidas pelos Web Containers. Ento, na prtica, no temos o trabalho de criar esses diretrios manualmente.

Mais Sobre
Consulte o artigo da K19 sobre criao de projetos web utilizando o Eclipse.

http://www.k19.com.br/artigos/criando-um-dynamic-web-project/

56

www.k19.com.br

57

W EB C ONTAINER

Exerccios de Fixao
No Eclipse, crie um projeto do tipo Dynamic Web Project chamado K19-App. Escolha Glasssh como opo para Target runtime. Na ltima tela de criao do projeto, selecione a opo Generate web.xml deployment descriptor.
8

Adicione o projeto K19-App no Glasssh atravs da view Servers. Clique com o boto direito do mouse no Glasssh e selecione Add and Remove. . . .
9

Inicialize o Glasssh atravs da view Servers. Clique com o boto direito do mouse sobre o Glasssh e escolha a opo Start.
10

Verique o funcionamento da nossa aplicao acessando http://localhost:8 8 /K19-App/ atravs de um navegador.


11

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 das pginas da aplicao gerado. Para isso, podemos criar uma Servlet.

Servlet
Para criar uma Servlet, podemos seguir os seguintes passos: 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 Servlet 3.0. Antes, essa congurao era realizada atravs do arquivo web.xml.

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 } }
Cdigo Java 4.1: OlaMundo.java

www.k19.com.br

57

W EB C ONTAINER

58

O mtodo service() executado toda vez que uma requisio HTTP realizada para a url denida na anotao @WebServlet. Esse mtodo recebe dois parmetros. O primeiro a referncia do objeto da classe HttpServletRequest que armazena todos os dados da requisio. O segundo parmetro a referncia do objeto da classe HttpServletResponse que armazenar o contedo gerado pela Servlet.

Inserindo contedo na resposta


Para inserir contedo texto na resposta HTTP que ser enviada para o navegador do usurio, devemos utilizar os mtodos getWriter() e println(). Em geral, o contedo inserido na resposta HTTP texto HTML. Veja o cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 @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 > " ) ; } }
Cdigo Java 4.2: OlaMundo.java

Exerccios de Fixao
12 13

Crie um pacote chamado servlets no projeto K19-App. Crie uma classe chamada OlaMundo no pacote servlets.
@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 > " ) ; } }
Cdigo Java 4.3: OlaMundo.java

1 2 3 4 5 6 7 8 9 1

14

Verique o funcionamento da Servlet acessando a url abaixo atravs de um navegador.

http://localhost:8 8 /K19-App/OlaMundo

Frameworks
Hoje em dia, improvvel que uma empresa decida comear um projeto utilizando diretamente Servlets, pois a produtividade seria pequena e a manuteno muito custosa. Vrios frameworks fo58
www.k19.com.br

59

W EB C ONTAINER

ram criados para facilitar o desenvolvimento e a manuteno de aplicaes web. Apesar de serem baseados em Servlets, esses frameworks oferecem diversos recursos adicionais para as aplicaes. Eis uma lista dos principais frameworks para aplicaes web Java: JSF Struts 1.x Struts 2.x Spring MVC

Aplicao Web Framework


Web Container
Requisio HTTP

TP

HT

isi

qu

www.k19.com.br

Re

www.k19.com.br

Cursos

Artigos

Apostilas

Figura 4.3: Framework para aplicaes web

Nos prximos captulos, mostraremos o funcionamento e explicaremos os conceitos relacionados ao framework JSF.

Re HT TP
www.k19.com.br

qu Re sp ta os

o isi

HT

TP
Resposta HTTP

Re sp os ta

www.k19.com.br

HT TP

59

W EB C ONTAINER

60

60

www.k19.com.br

CAPTULO

V ISO G ERAL DO JSF 2

Atualmente, o principal framework para desenvolvimento de aplicaes web em Java o JSF (Java Server Faces). A especicao desse framework pode ser obtida em http://www.jcp.org/en/jsr/ detail?id=314. Alm disso, recomendamos a consulta ao javadoc da API do JSF que pode ser obtido no mesmo link. O JSF fortemente baseado nos padres MVC e Front Controller.

MVC e Front Controller


O MVC (model-view-controller) um padro de arquitetura que tem por objetivo isolar a lgica de negcio da lgica de apresentao de uma aplicao. Esse padro (ou alguma variao) amplamente adotado nas principais plataformas de desenvolvimento atuais. Em particular, ele bastante utilizado na plataforma Java. O padro MVC divide uma aplicao em trs tipos de componentes: modelo, viso e controlador.

Modelo: encapsula os dados e as funcionalidades da aplicao. Viso: responsvel pela exibio de informaes, cujos dados so obtidos do modelo. Controlador: recebe as requisies do usurio e aciona o modelo e/ou a viso.

Para mais detalhes sobre o padro MVC, uma boa referncia o livro Pattern-Oriented Software Architecture Volume 1: A System of Patterns (editora Wiley, 1996) dos autores Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, Michael Stal e Michael Stal. No padro Front Controller, todas as requisies do usurio so recebidas pelo mesmo componente. Dessa forma, tarefas que devem ser realizadas em todas as requisies podem ser implementadas por esse componente. Isso evita a repetio de cdigo e facilita a manuteno do sistema. Para mais informaes sobre esse padro, consulte, por exemplo, o livro Core J2EE Patterns: Best Practices and Design Strategies (editora Prentice Hall, 2003, segunda edio) dos autores Deepak Alur, Dan Malks e John Crupi.

Congurando uma aplicao JSF


Uma aplicao JSF deve respeitar a estrutura geral de uma aplicao web Java que foi descrita no captulo anterior. Essa estrutura dena pela especicao Servlet que est disponvel em http: //www.jcp.org/en/jsr/detail?id=315.
www.k19.com.br

61

V ISO G ERAL DO JSF 2

62

web.xml
A Faces Servlet deve ser congurada no arquivo WEB-INF/web.xml, indicando a classe que a implementa e o padro de url que ser associado a essa servlet. Por exemplo, na congurao abaixo, todas as requisies cujas urls possuam o suxo .xhtml sero processadas pela Faces Servlet.
1 2 3 4 5 6 7 8 < servlet > < servlet - name > Faces Servlet </ servlet - name > < servlet - class > javax . faces . webapp . FacesServlet </ servlet - class > </ servlet > < servlet - mapping > < servlet - name > Faces Servlet </ servlet - name > <url - pattern > *. xhtml </ url - pattern > </ servlet - mapping >
Cdigo XML 5.1: web.xml

faces-cong.xml
Devemos adicionar um arquivo chamado faces-config.xml no diretrio WEB-INF. Nesse arquivo, podemos alterar diversas conguraes do JSF. Mas, a princpio, podemos deix-lo apenas com a tag faces-config.
1 2 3 4 5 6 <? xml version = " 1. " encoding = " utf -8 " ? > < faces - config xmlns = " http: // java . sun . com / xml / ns / javaee " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / javaee http: // java . sun . com / xml / ns / javaee / web - facesconfig_2_ . xsd " version = " 2. " > </ faces - config >
Cdigo XML 5.2: faces-cong.xml

Bibliotecas
Para utilizar os recursos do JSF, necessrio que a aplicao possua uma implementao JSF. Essa implementao pode ser adicionada manualmente no diretrio WEB-INF/lib da aplicao. Se um servidor de aplicao Java EE for utilizado, a incluso de uma implementao JSF manualmente no necessria, j que esse tipo de servidor possui, por padro, uma implementao de JSF.

Managed Beans
Os managed beans so objetos fundamentais de uma aplicao JSF. Suas principais tarefas so: 1. Fornecer dados que sero exibidos nas telas. 2. Receber os dados enviados nas requisies.
62
www.k19.com.br

63

V ISO G ERAL DO JSF 2

3. Executar tarefas de acordo com as aes dos usurios.

Criando um Managed Bean


Um managed bean pode ser denido de duas maneiras. A primeira maneira criar uma classe Java e registr-la no arquivo faces-config.xml. Veja o exemplo abaixo.
1 2 3 4 5 package br . com . k19 ; public class TesteBean { ... }
Cdigo Java 5.1: TesteBean.java

1 2 3 4 5 6 7

... < managed - bean > < managed - bean - name > testeBean </ managed - bean - name > < managed - bean - class > br . com . k19 . TesteBean </ managed - bean - class > < managed - bean - scope > request </ managed - bean - scope > </ managed - bean > ...
Cdigo XML 5.3: faces-cong.xml

No registro de um managed bean, devemos denir o nome, a classe e o escopo do managed bean. O nome que ser utilizado para acessar esse managed bean nas pginas da aplicao. O escopo ser explicado em detalhes no Captulo 9. A segunda forma criar uma classe Java com a anotao @ManagedBean do pacote javax.faces.bean. Essa anotao s pode ser utilizada a partir da verso 2 do JSF. Observe o exemplo abaixo.
1 2 3 4 @ManagedBean public class TesteBean { ... }
Cdigo Java 5.2: TesteBean.java

Utilizando a anotao @ManagedBean, por padro, o JSF assumir que o nome do managed bean o nome da classe com a primeira letra minscula. Para o exemplo acima, o nome padro do managed bean testeBean. Alm disso, o escopo request ser assumido como padro.

Propriedades
Considere o seguinte managed bean.
1 2 3 4 @ManagedBean public class TesteBean { private int numero ; }
Cdigo Java 5.3: TesteBean.java

www.k19.com.br

63

V ISO G ERAL DO JSF 2

64

Para acessar o valor do atributo numero em uma tela JSF, precisamos denir um mtodo de leitura. Esse mtodo deve seguir a conveno de nomenclatura do Java. Veja o exemplo abaixo:
1 2 3 4 5 6 7 8 @ManagedBean public class TesteBean { private int numero ; public int getNumero () { return numero ; } }
Cdigo Java 5.4: TesteBean.java

Note que o nome do mtodo comea com get e seguido pelo nome do atributo com a primeira letra em caixa alta. Para alterar o valor do atributo numero com valores obtidos atravs de uma tela JSF, precisamos denir um mtodo de escrita.
1 2 3 4 5 6 7 8 9 1 11 12 @ManagedBean public class TesteBean { private int numero ; public int setNumero ( int numero ) { this . numero = numero ; } public int getNumero () { return numero ; } }
Cdigo Java 5.5: TesteBean.java

O nome do mtodo de escrita deve necessariamente comear com a palavra set e terminar com o nome do atributo com a primeira letra em caixa alta. Com os mtodos de acesso j implementados, podemos exibir o valor do atributo numero utilizando expression language (#{}). Veja o exemplo a seguir.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > Valor : #{ testeBean . numero } </ h : body > </ html >
Cdigo XHTML 5.1: Exibindo o valor do atributo numero

Para alterar o valor do atributo numero do managed bean testeBean, podemos vincul-lo, por exemplo, a uma caixa de texto em um formulrio. Observe o cdigo abaixo.

64

www.k19.com.br

65
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > Valor : #{ testeBean . numero } <h : form > <h : inputText value = " #{ testeBean . numero } " / > <h : commandButton value = " Altera " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 5.2: Alterando o valor do atributo numero

V ISO G ERAL DO JSF 2

Importante
importante destacar que o vnculo com uma propriedade de um managed bean d-se por meio dos nomes dos mtodos getters e setters, e no pelo nome do atributo. No exemplo acima, se mantivssemos o nome do atributo do managed bean mas substitussemos os nomes dos mtodos getNumero() e setNumero() por getValor() e setValor(), respectivamente, ento os trechos de cdigo XHTML em destaque deveriam ser alterados para o seguinte:
1 2 Valor : #{ testeBean . valor } <h : inputText value = " #{ testeBean . valor } " / >

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. Seguindo o exemplo acima, podemos criar um mtodo que incrementa o valor do atributo numero, como no cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 @ManagedBean public class TesteBean { private int numero ; public void incrementaNumero () { this . numero = numero + 1; } // GETTERS E SETTERS }
Cdigo Java 5.6: TesteBean.java

www.k19.com.br

65

V ISO G ERAL DO JSF 2

66

Esses mtodos podem ser void quando desejamos manter os usurios na mesma tela ou devolver String quando desejamos realizar uma navegao entre telas. Veremos mais detalhes em captulos posteriores. Para incrementar o valor do atributo numero do managed bean testeBean, podemos criar uma pgina que possui um boto para executar essa ao e associ-lo ao mtodo incrementaNumero(), conforme o cdigo abaixo.
1 2 3 <h : form > <h : commandButton value = " Incrementa " action = " #{ testeBean . incrementaNumero } " / > </ h : form >
Cdigo XHTML 5.4: Boto associado a um mtodo de um managed bean

Mais Sobre
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 em caixa baixa. Porm, podemos alterar esse nome acrescentado um argumento na anotao.
1 2 3 4 @ManagedBean ( name = " teste " ) class TesteBean { ... }
Cdigo Java 5.7: Alterando o nome de um managed bean

Processamento de uma requisio


Em uma aplicao JSF, toda requisio realizada atravs de um navegador recebida pela Faces Servlet. Ao receber uma requisio, a Faces Servlet executa os seguintes passos:

Restore View: Na primeira requisio de um usurio, uma nova rvore de componentes que representa a tela desse usurio gerada. Nas demais requisies (postback) desse mesmo usurio, a rvore de componentes que representa a tela anteriormente enviada a ele reconstruda. Apply Request Values: Nesta etapa, a rvore construda na etapa anterior percorrida e cada um dos seus componentes decodicado. No processo de decodicao, cada componente extrai da requisio atual os dados associados a essa componente e se atualiza com essas informaes. Ainda nessa etapa, os eventos de ao (como um clique em um link ou em um boto, por exemplo) so identicados. Por padro, esses eventos so adicionados s las correspondentes para serem tratados posteriormente (na fase Invoke Application). Process Validations: Nesta fase, os componentes que possuem valores submetidos pelo usurio atravs de formulrios so convertidos e validados (caso haja algum validador registrado para esse componente).
66
www.k19.com.br

67

V ISO G ERAL DO JSF 2

Se ocorrer algum erro de converso ou validao, mensagens de erro so adicionadas no contexto da requisio atual e o uxo redirecionado para a fase Render Response. Caso contrrio, processo continua na fase Update Model Values.

Ainda nesta fase, os eventos de mudana de valor so identicados e tratados ao nal da mesma.

Update Model Values: Os valores contidos em cada componente da rvore, j convertidos e validados na fase anterior, so armazenados em propriedades de objetos denidos pela aplicao (managed beans)

Invoke Application: Uma vez que os dados dos componentes j foram convertidos, validados e armazenados nos objetos do modelo, as tarefas correspondentes ao evento que disparou a requisio (normalmente um clique em um boto ou link) sero executadas.

Tambm nesta fase, a prxima tela a ser apresentada ao usurio determinada pelo resultado do mtodo que implementa a lgica de negcio executado nesta fase.

Render Response: Nesta etapa, a prxima tela gerada e enviada ao navegador do usurio. Uma representao desta tela tambm armazenada a m de ser usada na fase Restore View da prxima requisio.

O diagrama abaixo ilustra a estrutura geral de uma aplicao JSF. O processamento de uma requisio enviada por um navegador comea na Faces Servlet logo aps a sua chegada. A Faces Servlet controla a execuo das seis etapas descritas acima.
www.k19.com.br

67

V ISO G ERAL DO JSF 2

68

www.k19.com.br

L HTMscript a Jav CSS

Requisio HTTP

Resposta HTTP

Faces Servlet

Restore View

Apply Request Values

Process Validation

Update Model

Ivoke Application

Render Response

MANAGED BEANS

CONTROLE MODELO VISO

TELAS ENTIDADES TEMPLATES

REPOSITRIOS

TELAS PARCIAIS

Figura 5.1: Estrutura geral de uma aplicao JSF

68

www.k19.com.br

69

V ISO G ERAL DO JSF 2

Os managed beans esto disposio da Faces Servlet durante todo o processamento da requisio. Por exemplo, nas etapas Render Response e Restore View, a Faces Servlet aciona os managed beans para recuperar os dados que devem ser usados na construo ou reconstruo da rvore de componentes. Na etapa Update Model, a Faces Servlet armazena nos managed beans os dados j convertidos e validados. Na etapa Invoke Application, a Faces Servlet dispara um mtodo em um managed bean responsvel pelo processamento da regra de negcio correspondente requisio atual. Todas as regras de negcio so implementadas no modelo, que tambm administra os dados da aplicao. Os managed beans acionam o modelo para executar alguma regra de negcio, recuperar ou alterar os dados administrados pelo modelo. As telas da aplicao so denidas na camada de viso. A Faces Servlet acessa essa camada toda vez que necessita construir ou reconstruir a rvore de componentes de uma determinada tela. Isso ocorre nas etapas Restore View e Render Response.

Exemplo Prtico
Com as conguraes j realizadas, implementaremos uma aplicao que mostra o funcionamento bsico do JSF. Essa aplicao dever receber um texto do usurio e exibi-lo em letras maisculas.

Managed Bean
Vamos comear criando um managed bean para armazenar o texto enviado pelo usurio e a lgica para transform-lo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 import javax . faces . bean . ManagedBean ; @ManagedBean public class TextoBean { private String texto ; public String transformaEmCaixaAlta () { this . texto = this . texto . toUpperCase () ; return " resposta " ; } public String getTexto () { return this . texto ; } public void setTexto ( String texto ) { this . texto = texto ; } }
Cdigo Java 5.8: TextoBean.java

A classe que implementa o managed bean deve ser anotada com @ManagedBean. O atributo texto armazenar o texto enviado pelo usurio e esse texto ser modicado pelo mtodo transformaEmCaixaAlta(). Esse mtodo devolve uma string para indicar qual deve ser a prxima tela a ser enviada para o usurio.
www.k19.com.br

69

V ISO G ERAL DO JSF 2

70

A Faces Servlet utilizar o mtodo setTexto() para armazenar o texto enviado pelo usurio no managed bean. Por outro lado, utilizar o mtodo getTexto() para recuperar o texto e exibi-lo aps a sua modicao.

Telas
Uma vez que o managed bean foi criado, podemos associ-lo a um formulrio que receber o texto do usurio.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Texto : " / > <h : inputTextarea value = " #{ textoBean . texto } " / > <h : commandButton value = " Transformar " action = " #{ textoBean . transformaEmCaixaAlta } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 5.5: formulario.xhtml

Observe nas linhas em destaque a ligao entre essa tela e o managed bean. A caixa de entrada de texto foi associada propriedade texto do managed bean TextoBean. O boto, por sua vez, foi associado ao mtodo transformaEmCaixaAlta() do managed bean TextoBean. Para exibir o texto transformado, podemos criar uma outra tela.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : outputText value = " #{ textoBean . texto } " / > </ h : body > </ html >
Cdigo XHTML 5.6: resposta.xhtml

Analogamente, a caixa de sada de texto est associada propriedade texto do managed bean

TextoBean.
70
www.k19.com.br

71

V ISO G ERAL DO JSF 2

Exerccios de Fixao
Como exerccio, desenvolva uma aplicao JSF que (i) receba um nmero inteiro do usurio, (ii) produza um nmero aleatrio entre zero e o nmero recebido, e (iii) exiba esse nmero na tela do navegador do usurio. No Eclipse, crie um Dynamic Web Project chamado K19-Visao-Geral. Na primeira tela, devemos denir o nome do projeto, selecionar o target runtime e a congurao.
1

Figura 5.2: Criando um Dynamic Web Project

Na tela seguinte, apenas clique em Next.


www.k19.com.br

71

V ISO G ERAL DO JSF 2

72

Figura 5.3: Criando um Dynamic Web Project

Novamente, clique em Next.


72
www.k19.com.br

73

V ISO G ERAL DO JSF 2

Figura 5.4: Criando um Dynamic Web Project

Na ltima tela, devemos desabilitar as conguraes de biblioteca e mapear a Faces Servlet para as urls que seguem o padro *.xhtml.
www.k19.com.br

73

V ISO G ERAL DO JSF 2

74

Figura 5.5: Criando um Dynamic Web Project

Na pasta src, crie um managed bean para armazenar o nmero inteiro n enviado pelo usurio, gerar um nmero aleatrio entre zero e n e armazen-lo numa propriedade.
2

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

import javax . faces . bean . ManagedBean ; @ManagedBean public class NumeroAleatorioBean { private int maximo ; private int numeroAleatorio ; public String geraNumeroAleatorio () { this . numeroAleatorio = ( int ) ( Math . random () * this . maximo ) ; return " resposta " ; } // GETTERS E SETTERS }

74

www.k19.com.br

75

V ISO G ERAL DO JSF 2

Cdigo Java 5.9: NumeroAleatorioBean.java

Agora, na pasta WebContent, crie um formulrio para que o usurio possa enviar o dado de entrada.
3

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Nmero mximo : " / > <h : inputText value = " #{ numeroAleatorioBean . maximo } " / > <h : commandButton value = " Gera nmero aleatrio " action = " #{ numeroAleatorioBean . geraNumeroAleatorio } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 5.7: formulario.xhtml

Tambm na pasta WebContent, dena uma tela para exibir o nmero gerado aleatoriamente.
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : outputText value = " #{ numeroAleatorioBean . numeroAleatorio } " / > </ h : body > </ html >
Cdigo XHTML 5.8: resposta.xhtml

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

Adicione o projeto no GlassFish e teste-o, seguindo os passos abaixo.

1. Abra a aba Servers. Para isso, pressione Ctrl+3. Na janela que abrir, digite Servers e pressione Enter. 2. Na aba Servers, clique com o boto direito do mouse no GlassFish e selecione a opo Add and Remove. . . . 3. Selecione o projeto K19-Visao-Geral e clique em Add >. Em seguida, clique em Finish.
www.k19.com.br

75

V ISO G ERAL DO JSF 2

76

4. Inicialize o servidor. Para isso, clique mais uma vez no GlassFish com o boto direito e selecione Start. 5. Acesse a aplicao no endereo

http://localhost:8 8 /K19-Visao-Geral/formulario.xhtml.

76

www.k19.com.br

CAPTULO

C OMPONENTES V ISUAIS

No JSF 2, as telas so denidas em arquivos XHTML. Os componentes visuais que constituem as telas so adicionados por meio de tags. A especicao do JSF dene uma grande quantidade de tags e as classica em bibliotecas. As principais bibliotecas de tags do JSF so: Core (http://java.sun.com/jsf/core) HTML (http://java.sun.com/jsf/html) Facelets (http://java.sun.com/jsf/facelets) A seguir, apresentaremos o funcionamento geral das principais tags dessas trs bibliotecas. A documentao completa pode ser encontrada em http://www.jcp.org/en/jsr/detail?id=314.

Estrutura Bsica de uma Pgina JSF


A estrutura bsica de uma pgina JSF muito semelhante estrutura de uma pgina HTML. Observe o cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : outputText value = " Estrutura bsica de uma tela JSF " / > </ h : body > </ html >
Cdigo XHTML 6.1: Estrutura Bsica de uma Tela JSF

O contedo da pgina denido no corpo da tag <html>. Esse contedo dividido em duas partes: o cabealho, delimitado pela tag <h:head> (e no pela tag <head>), e o corpo, delimitado pela tag <h:body> (e no pela tag <body>). As bibliotecas de tags que sero utilizadas para construir a pgina devem ser importadas atravs do pseudo-atributo xmlns aplicado tag <html>. Observe no exemplo acima que as trs principais bibliotecas do JSF foram importadas.

www.k19.com.br

77

C OMPONENTES V ISUAIS

78

Mais Sobre
Devemos utilizar a declarao <!DOCTYPE> para informar aos navegadores qual a verso do HTML utilizado na pgina. Com essa informao, os navegadores podem processar o documento corretamente.

Mais Sobre
Quando uma biblioteca de tags importada atravs do pseudo-atributo xmlns, possvel denir um prexo para essa biblioteca. Esse prexo utilizado, no documento, para acessar as tags da biblioteca.

Importante
A utilizao das tags <h:head> e <h:body> fundamental para o funcionamento completo das pginas HTML geradas pelo JSF. Ao processar essas tags, na etapa Render Response, o JSF adiciona recursos como scripts e arquivos de estilo na tela HTML que ser enviada para o usurio. Esses recursos so necessrios para o funcionamento correto dos componentes.

Formulrios
Os formulrios no JSF so denidos atravs da tag <h:form> (e no pela tag <form>). Um formulrio composto basicamente por caixas de texto, caixas de seleo, rtulos, botes e links. Ao ser processado, o componente <h:form> gera um formulrio HTML congurado para o mtodo POST do HTTP. Nas sees a seguir, descreveremos os elementos de um formulrio.

Caixas de Texto
O JSF dene trs tipos de caixas de texto para coletar dados do usurio. <h:inputText> Permite que o usurio digite uma linha de texto. <h:inputTextarea> Permite que o usurio digite vrias linhas de texto. <h:inputSecret> Igual ao <h:inputText> mas no exibi o que foi digitado. Uma caixa de texto pode ser associada a uma propriedade de um managed bean atravs do atributo value. Esse vnculo denominado binding. Considere o seguinte managed bean.
1 2 3 @ManagedBean public class UsuarioBean { private String nome ;

78

www.k19.com.br

79
4 5 6 7 8 9 1 11 12

C OMPONENTES V ISUAIS

public String getNome () { return nome ; } public void setNome ( String nome ) { this . nome = nome ; } }
Cdigo Java 6.1: UsuarioBean.java

Devemos utilizar expression language (#{}) para estabelecer uma associao entre a propriedade nome a uma caixa de texto. Observe o cdigo abaixo.
1 <h : inputText value = " #{ usuarioBean . nome } " / >

Quando o JSF constri a tela a ser enviada para o usurio, ele recupera o valor da propriedade nome atravs do mtodo getNome() e guarda esse valor na caixa de texto correspondente. Analogamente, no processamento de uma requisio, o JSF extrai o valor presente na caixa de texto e utiliza o mtodo setNome() para armazenar esse valor na propriedade nome do managed bean UsuarioBean.

Rtulos
Rtulos so utilizados para indicar ao usurio o que ele deve preencher em determinada caixa de texto. Para acrescentar um rtulo em uma pgina, devemos utilizar o componente <h:outputLabel>. O texto do rtulo denido pelo atributo value e pode ser associado a uma caixa de texto atravs do atributo for. O valor do atributo for deve ser igual ao valor do atributo id da caixa de texto que desejamos associar ao rtulo.
1 2 <h : outputLabel value = " Nome : " for = " nome " / > <h : inputText id = " nome " / >
Cdigo XHTML 6.3: Exemplo de uso do <h:outputLabel>

Exemplos
A seguir, alguns exemplos de utilizao das caixas de texto sero apresentados. Mostraremos o cdigo XHTML das telas, o cdigo HTML produzido pelo JSF e as telas renderizadas por um navegador. 1. XHTML:
<h : outputLabel value = " Nome : " for = " nome " / > <h : inputText value = " Jonas K . Hirata " id = " nome " / >

HTML gerado:
< label for = " j_idt6 : nome " > Nome : </ label > < input id = " j_idt6 : nome " type = " text " name = " j_idt6 : nome " value = " Jonas K . Hirata " / >

www.k19.com.br

79

C OMPONENTES V ISUAIS

80

Resultado:
Nome: Jonas K. Hirata

2. XHTML:
<h : outputLabel value = " Nome : " for = " nome " / > <h : inputText value = " #{ usuarioBean . nome } " id = " nome " / >

HTML gerado:
< label for = " j_idt6 : nome " > Nome : </ label > < input id = " j_idt6 : nome " type = " text " name = " j_idt6 : nome " value = " Jonas Hirata " / >

Resultado:
Nome: Jonas Hirata

3. XHTML:
<h : outputLabel value = " Nome : " for = " nome " / > <h : inputText value = " #{ usuarioBean . nome } " readonly = " true " id = " nome " / >

HTML gerado:
< label for = " j_idt6 : nome " > Nome : </ label > < input id = " j_idt6 : nome " type = " text " name = " j_idt6 : nome " value = " Jonas Hirata " readonly = " readonly " / >

Resultado:
Nome: Jonas Hirata

4. XHTML:
<h : outputLabel value = " CEP : " for = " cep " / > <h : inputText value = " #{ usuarioBean . cep } " maxlength = " 9 " id = " cep " / >

HTML gerado:
< label for = " j_idt6 : cep " > Cep : </ label > < input id = " j_idt6 : cep " type = " text " name = " j_idt6 : cep " value = " 1452 1 " maxlength = " 9 " / >

Resultado:
CEP: 01452-001

5. XHTML:
<h : outputLabel value = " Texto : " for = " texto " / > <h : inputTextarea value = " Um texto de vrias linhas " id = " texto " / >

HTML gerado:
< label for = " j_idt6 : texto " > Texto : </ label > < textarea id = " j_idt6 : texto " name = " j_idt6 : texto " > Um texto de vrias linhas </ textarea >

80

www.k19.com.br

81

C OMPONENTES V ISUAIS

Resultado:
Texto: Um texto de vrias linhas

6. XHTML:
<h : outputLabel value = " Texto : " for = " texto " / > <h : inputTextarea value = " Um texto de vrias linhas " cols = " 1 " rows = " 3 " id = " texto " / >

HTML gerado:
< label for = " j_idt6 : texto " > Texto : </ label > < textarea id = " j_idt6 : texto " name = " j_idt6 : texto " cols = " 1 " rows = " 3 " > Um texto de vrias linhas </ textarea >

Resultado:
Texto: Um texto de vrias linhas

7. XHTML:
<h : outputLabel value = " Senha : " for = " senha " / > <h : inputSecret value = " #{ usuarioBean . senha } " id = " senha " / >

HTML gerado:
< label for = " j_idt6 : senha " > Senha : </ label > < input id = " j_idt6 : senha " type = " password " name = " j_idt6 : senha " value = " " / >

Resultado:
Senha:

Campos Ocultos
Podemos adicionar informaes que so submetidas automaticamente quando um formulrio enviado ao servidor. Essas informaes podem ser inseridas com o componente <h:inputHidden>. Essa tag possui dois atributos principais: value e id. Podemos vincular um campo oculto a uma propriedade de um managed bean, como no exemplo abaixo.
1 <h : inputHidden id = " curso - id " value = " #{ cursosBean . curso . id } " / >
Cdigo XHTML 6.11: Exemplo de um campo oculto vinculado a uma propriedade de um managed bean

Caixas de Seleo
www.k19.com.br

81

C OMPONENTES V ISUAIS

82

O JSF dene sete tipos de caixas de seleo. <h:selectBooleanCheckbox> Permite que o usurio faa selees do tipo sim ou no. <h:selectManyCheckbox> Permite que o usurio faa mltiplas selees do tipo sim ou no. <h:selectOneRadio>, <h:selectOneMenu>, <h:selectOneListbox> Permitem a seleo de uma nica opo de um conjunto de opes. A principal diferena entre essas tags modo como elas so apresentadas visualmente. <h:selectManyListbox>, <h:selectManyMenu> Possibilita a seleo de diversas opes de um conjunto de opes. A diferena principal entre essas duas tags modo como elas so apresentadas visualmente. Podemos vincular uma caixa de seleo a uma propriedade de um managed bean atravs do atributo value. No exemplo abaixo, uma caixa de seleo associada propriedade aceito do managed bean ContratoBean.
1 <h : selectBooleanCheckbox value = " #{ contratoBean . aceito } " / >
Cdigo XHTML 6.12: Caixa de seleo vinculada propriedade aceito do managed bean ContratoBean

Caixas de seleo do tipo <h:selectBooleanCheckbox> devem ser vinculadas a propriedades booleanas.

Opes Estticas e Dinmicas


As opes de uma caixa de seleo (com exceo da <h:selectBooleanCheckbox>) podem ser denidas esttica ou dinamicamente. Estaticamente, cada opo pode ser adicionada atravs da tag <f:selectItem>. Considere o seguinte exemplo.
1 2 3 4 <h : selectOneMenu value = " #{ cursosBean . siglaDoCursoEscolhido } " > <f : selectItem itemValue = " K11 " itemLabel = " Orientao a Objetos em Java " > <f : selectItem itemValue = " K12 " itemLabel = " Desenvolvimento Web com JSF2 e JPA2 " > </ h : selectOneMenu >
Cdigo XHTML 6.13: Caixa de seleo com opes denidas estaticamente

O atributo itemValue dene o que ser enviado para a aplicao se a opo correspondente for selecionada. O atributo itemLabel dene a descrio associada opo correspondente. Essa descrio exibida para o usurio. Denir as opes estaticamente pode dicultar a adio ou remoo de opes. Por exemplo, o cadastramento ou a remoo de um curso no sistema implicaria em uma mudana no arquivo XHTML. Seria interessante eliminar essa dependncia fazendo com que o arquivo XHTML recupere dinamicamente todos os cursos cadastrados. Isso pode ser realizado atravs da tag <f:selectItems>.

82

www.k19.com.br

83
1 2 3 4 5 6 7 <h : selectOneMenu value = " #{ cursosBean . siglaDoCursoEscolhido } " > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " > </ h : selectOneMenu >
Cdigo XHTML 6.14: Caixa de seleo com opes denidas dinamicamente

C OMPONENTES V ISUAIS

A atributo value da tag <f:selectItems> deve ser associado a uma coleo de itens. Todos os itens sero percorridos e adicionados como opo na caixa de seleo. O atributo var utilizado para denir a varivel que armazenar, a cada rodada, o item atual. Essa varivel permite que o itemValue e o itemLabel de cada opo sejam denidos.

Seleo nica ou Mltipla


Algumas caixas de seleo permitem que apenas uma opo seja selecionada, enquanto outras permitem que mltiplas opes sejam selecionadas. Considere um formulrio que permita ao usurio escolher apenas um dos cursos de uma lista. Como vimos, esse formulrio pode ter a seguinte estrutura:
1 2 3 4 5 6 7 <h : selectOneListbox value = " #{ cursosBean . siglaDoCursoEscolhido } " > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectOneListbox >
Cdigo XHTML 6.15: Seleo de um nico curso

1 2 3 4 5 6 7

@ManagedBean public class CursosBean { private String siglaDoCursoEscolhido ; private List < Curso > cursos ; // GETTERS E SETTERS }
Cdigo Java 6.2: CursosBean.java

1 2 3 4 5 6

public class Curso { private String sigla ; private String nome ; // GETTERS E SETTERS }
Cdigo Java 6.3: Curso.java

A propriedade associada caixa de seleo deve ser compatvel com o tipo de dado utilizado no atributo itemValue. No exemplo acima, as siglas dos cursos so do tipo String. Consequentemente, a propriedade que armazenar a sigla do curso escolhido tambm deve ser to tipo String. Agora, suponha que o usurio possa escolher mais do que um curso. Nesse caso, o managed bean deve estar preparado para guardar uma lista de siglas de cursos ao invs de uma nica sigla. Para isso,
www.k19.com.br

83

C OMPONENTES V ISUAIS

84

devemos adicionar uma propriedade no managed bean CursosBean, como mostra o cdigo abaixo.
1 2 3 4 5 6 7 @ManagedBean public class CursosBean { private List < String > siglasDosCursosEscolhidos ; private List < Curso > cursos ; // GETTERS E SETTERS }
Cdigo Java 6.4: CursosBean.java

Para permitir a seleo mltipla, devemos utilizar uma caixa de seleo do tipo <h:selectManyListbox> ou <h:selectManyMenu>. Essa caixa deve ento ser vinculada nova propriedade do managed bean CursoBean. Por exemplo, se optarmos pela <h:selectManyListbox>, poderamos ter o seguinte cdigo.
1 2 3 4 5 6 7 <h : selectManyListbox value = " #{ cursosBean . siglasDosCursosEscolhidos } " > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectManyListbox >
Cdigo XHTML 6.16: Seleo de diversos cursos

Caixa de Seleo com Pseudo-opo


Por padro, a caixa de seleo do tipo <h:selectOneMenu> sempre tem uma opo selecionada. Contudo, em alguns casos, faz sentido para o usurio no selecionar nenhuma das opes disponveis. Para resolver esse problema, podemos adicionar uma pseudo-opo na caixa de seleo. Considere o cdigo abaixo.
1 2 3 4 5 6 7 8 <h : selectOneMenu value = " #{ cursosBean . siglaDoCursoEscolhido } " > <f : selectItem itemLabel = " Nenhum " noSelectionOption = " true " / > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectOneMenu >
Cdigo XHTML 6.17: Pseudo-opo

Para adicionar uma pseudo-opo, basta utilizar a tag <f:selectItem> com o atributo noSelectionOption igual a true. Se essa pseudo-opo estiver selecionada no momento em que o formulrio for submetido, a propriedade correspondente receber o valor null. Muitas vezes, a pseudo-opo utilizada simplesmente para exibir uma mensagem ao usurio, como Escolha uma opo ou Selecione um item.

Exemplos
A seguir, mostraremos exemplos de cada tipo de caixa de seleo.
84
www.k19.com.br

85

C OMPONENTES V ISUAIS

1. XHTML:
1 2 <h : outputLabel value = " Ex - aluno " for = " exaluno " / > <h : selectBooleanCheckbox value = " #{ cursosBean . exAluno } " id = " exaluno " / >

HTML gerado:
1 2 < label for = " j_idt6 : exaluno " >Ex - aluno </ label > < input id = " j_idt6 : exaluno " type = " checkbox " name = " j_idt6 : exaluno " / >

Resultado:

Ex-aluno
2. XHTML:
1 2 3 4 5 6 7 8 <h : selectManyCheckbox value = " #{ cursosBean . siglasDosCursosEscolhidos } " layout = " pageDirection " > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectManyCheckbox >

HTML gerado:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 < table > < tr > < td > < input name = " j_idt6 : j_idt27 " id = " j_idt6 : j_idt27 : " value = " K11 " type = " checkbox " / > < label for = " j_idt6 : j_idt27 : " class = " " > Orientao a Objetos em Java </ label > </ td > </ tr > < tr > < td > < input name = " j_idt6 : j_idt27 " id = " j_idt6 : j_idt27 :1 " value = " K12 " type = " checkbox " / > < label for = " j_idt6 : j_idt27 :1 " class = " " > Desenvolvimento Web com JSF2 e JPA2 </ label > </ td > </ tr > < tr > < td > < input name = " j_idt6 : j_idt27 " id = " j_idt6 : j_idt27 :2 " value = " K51 " type = " checkbox " / > < label for = " j_idt6 : j_idt27 :2 " class = " " > Design Patterns em Java </ label > </ td > </ tr > </ table >

Resultado:

Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java
3. XHTML:
1 2 3 <h : selectOneRadio value = " #{ cursosBean . siglasDosCursosEscolhidos } " layout = " lineDirection " > <f : selectItems value = " #{ cursosBean . cursos } "

www.k19.com.br

85

C OMPONENTES V ISUAIS
4 5 6 7 var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectOneRadio >

86

HTML gerado:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 < table > < tr > < td > < input < label </ td > < td > < input < label </ td > < td > < input < label </ td > </ tr > </ table >

type = " radio " name = " j_idt6 : j_idt3 " id = " j_idt6 : j_idt3 : " value = " K11 " / > for = " j_idt6 : j_idt3 : " > Orientao a Objetos em Java </ label >

type = " radio " name = " j_idt6 : j_idt3 " id = " j_idt6 : j_idt3 :1 " value = " K12 " / > for = " j_idt6 : j_idt3 :1 " > Desenvolvimento Web com JSF2 e JPA2 </ label >

type = " radio " name = " j_idt6 : j_idt3 " id = " j_idt6 : j_idt3 :2 " value = " K51 " / > for = " j_idt6 : j_idt3 :2 " > Design Patterns em Java </ label >

Resultado:
Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java

4. XHTML:
1 2 3 4 5 6 7 8 <h : selectOneMenu value = " #{ cursosBean . siglasDosCursosEscolhidos } " > <f : selectItem itemLabel = " Escolha um curso " noSelectionOption = " true " / > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectOneMenu >

HTML gerado:
1 2 3 4 5 6 < select name = " j_idt6 : j_idt33 " size = " 1 " > < option value = " " > Escolha um curso </ option > < option value = " K11 " > Orientao a Objetos em Java </ option > < option value = " K12 " > Desenvolvimento Web com JSF2 e JPA2 </ option > < option value = " K51 " > Design Patterns em Java </ option > </ select >

Resultado:
Escolha um curso

Escolha um curso Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java

5. XHTML:
1 2 3 <h : selectOneListbox value = " #{ cursosBean . siglasDosCursosEscolhidos } " > <f : selectItems value = " #{ cursosBean . cursos } "

86

www.k19.com.br

87
4 5 6 7 var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectOneListbox >

C OMPONENTES V ISUAIS

HTML gerado:
1 2 3 4 5 < select name = " j_idt6 : j_idt37 " size = " 3 " > < option value = " K11 " > Orientao a Objetos em Java </ option > < option value = " K12 " > Desenvolvimento Web com JSF2 e JPA2 </ option > < option value = " K51 " > Design Patterns em Java </ option > </ select >

Resultado:
Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java

6. XHTML:
1 2 3 4 5 6 7 <h : selectManyListbox value = " #{ cursosBean . siglasDosCursosEscolhidos } " > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectManyListbox >

HTML gerado:
1 2 3 4 5 < select name = " j_idt6 : j_idt4 " multiple = " multiple " size = " 3 " > < option value = " K11 " > Orientao a Objetos em Java </ option > < option value = " K12 " > Desenvolvimento Web com JSF2 e JPA2 </ option > < option value = " K51 " > Design Patterns em Java </ option > </ select >

Resultado:
Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java

7. XHTML:
1 2 3 4 5 6 7 8 <h : selectManyMenu value = " #{ cursosBean . siglasDosCursosEscolhidos } " style = " height : 7 px ; " > <f : selectItem itemLabel = " Escolha um curso " noSelectionOption = " true " / > <f : selectItems value = " #{ cursosBean . cursos } " var = " curso " itemValue = " #{ curso . sigla } " itemLabel = " #{ curso . nome } " / > </ h : selectManyMenu >

HTML gerado:
1 2 3 < select name = " j_idt6 : j_idt43 " multiple = " multiple " size = " 1 " style = " height : 7 px ; " > < option value = " " selected = " selected " > Escolha um curso </ option > < option value = " K11 " > Orientao a Objetos em Java </ option >

www.k19.com.br

87

C OMPONENTES V ISUAIS
4 5 6 < option value = " K12 " > Desenvolvimento Web com JSF2 e JPA2 </ option > < option value = " K51 " > Design Patterns em Java </ option > </ select >

88

Resultado:
Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Design Patterns em Java

Botes e Links
O JSF dene cinco tipos de botes e links: <h:commandButton> e <h:commandLink> Enviam os dados de um formulrio HTML para o servidor atravs do mtodo POST do HTTP . <h:button> e <h:link> Realizam requisies HTTP do tipo GET. As URLs das requisies so geradas pelo JSF a partir do atributo outcome. <h:outputLink> Tambm realiza requisies HTTP do tipo GET, mas exige que a URL de destino seja explicitamente especicada. Os componentes <h:commandButton> e <h:commandLink> so usados para submeter formulrios HTML por meio do mtodo POST do HTTP. Esses dois componentes podem ser associados a mtodos de ao de um managed bean atravs dos atributos action e actionListener. Esses atributos sero detalhados em outro captulo.
1 2 <h : commandButton value = " Adiciona curso " action = " #{ cursosBean . adicionaCurso } " / > <h : commandLink value = " Remove curso " action = " #{ cursosBean . removeCurso } " / >
Cdigo XHTML 6.25: Exemplos de utilizao do <h:commandButton> e do <h:commandLink>

A diferena bsica entre o <h:commandButton> e o <h:commandLink> o modo como eles so apresentados visualmente. Os componentes <h:button> e <h:link>, por sua vez, so usados para realizar requisies atravs do mtodo GET. O JSF utiliza o atributo outcome de um <h:button> ou <h:link> para denir a pgina de destino. Esses componentes no so utilizados para submeter formulrios HTML.
1 2 <h : button value = " Lista de cursos " outcome = " lista - cursos " / > <h : link value = " Home " outcome = " home " / >
Cdigo XHTML 6.26: Exemplos de utilizao do <h:button> e do <h:link>

Novamente, a diferena fundamental entre o <h:button> e o <h:link> o modo como eles so exibidos visualmente.
88
www.k19.com.br

89

C OMPONENTES V ISUAIS

O componente <h:outputLink> permite apenas a criao de links HTML que realizam requisies do tipo GET. Diferentemente dos componentes <h:button> e <h:link>, a URL da requisio denida explicitamente no atributo value.
1 <h : outputLink value = " http :// www . k19 . com . br " / >
Cdigo XHTML 6.27: Um link para a pgina da K19

Exemplos
1. XHTML:
1 <h : commandButton value = " Adiciona curso " action = " #{ cursosBean . adicionaCurso } " / >

HTML gerado:
1 < input type = " submit " name = " j_idt59 : j_idt6 " value = " Adiciona curso " / >

Resultado:
Adiciona curso

2. XHTML:
1 <h : commandLink value = " Remove curso " action = " #{ cursosBean . removeCurso } " / >

HTML gerado:
1 2 3 <a href = " # " onclick = " mojarra . jsfcljs ( document . getElementById ( j_idt62 ) ,{ j_idt62 : j_idt66 : j_idt62 : j_idt66 } , ) ; return false " > Remove curso </ a >

Resultado:
Remove curso

3. XHTML:
1 <h : button value = " Lista de cursos " outcome = " lista - cursos " / >

HTML gerado:
1 2 3 4 < input type = " button " onclick = " window . location . href = / K19 - Componentes - Visuais / lista - cursos . xhtml ; return false ; " value = " Lista de cursos " / >

Resultado:
Lista de cursos

4. XHTML:
www.k19.com.br

89

C OMPONENTES V ISUAIS
1 <h : link value = " Home " outcome = " home " / >

90

HTML gerado:
1 <a href = " / K19 - Componentes - Visuais / home . xhtml " > Home </ a >

Resultado:
Home

5. XHTML:
1 <h : outputLink value = " http :// www . k19 . com . br " > K19 </ h : outputLink >

HTML gerado:
1 <a href = " http :// www . k19 . com . br " > K19 </ a >

Resultado:
K19

Exerccios de Fixao
1 2

No Eclipse, crie um Dynamic Web Project chamado K19-Componentes-Visuais.

Crie uma classe chamada UsuarioBean. Essa classe deve possuir dois atributos: um atributo do tipo String para armazenar o nome do usurio e um atributo do tipo int para armazenar a idade do usurio.
1 2 3 4 5 6 7 @ManagedBean public class UsuarioBean { private String nome ; private int idade ; // GETTERS E SETTERS }
Cdigo Java 6.5: UsuarioBean.java

3 Crie um arquivo XHTML no diretrio WebContent chamado usuario.xhtml. Nesse arquivo, crie um formulrio para o usurio digitar e enviar o seu nome e a sua idade.

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Nome : " for = " campo - nome " / >

90

www.k19.com.br

91
13 14 15 16 17 18 19 2 21 <h : inputText value = " #{ usuarioBean . nome } " id = " campo - nome " / > <h : outputLabel value = " Idade : " for = " campo - idade " / > <h : inputText value = " #{ usuarioBean . idade } " id = " campo - idade " / > <h : commandButton value = " Enviar " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 6.33: usuario.xhtml

C OMPONENTES V ISUAIS

Adicione a aplicao ao servidor e inicialize-o. Acesse a aplicao em http://localhost:8 8 /

K19-Componentes-Visuais/usuario.xhtml.
5

No arquivo usuario.xhtml, acrescente um trecho de cdigo para exibir os dados do usurio.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ usuarioBean . nome } " id = " campo - nome " / > <h : outputLabel value = " Idade : " for = " campo - idade " / > <h : inputText value = " #{ usuarioBean . idade } " id = " campo - idade " / > <h : commandButton value = " Enviar " / > </ h : form > O nome do usurio <b > #{ usuarioBean . nome } </ b > e sua idade <b > #{ usuarioBean . idade } </ b >. </ h : body > </ html >
Cdigo XHTML 6.34: usuario.xhtml

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

6 Agora, crie um conversor monetrio. Esse conversor deve receber trs dados de entrada: as moedas de origem e destino, e o valor a ser convertido. Primeiramente, crie uma classe chamada ConversorMonetarioBean para implementar esse conversor.

1 2 3 4 5 6 7 8

@ManagedBean public class ConversorMonetarioBean { private String de ; private String para ; private Double valor ; // GETTERS E SETTERS }
Cdigo Java 6.6: ConversorMonetarioBean.java

Adicione um mtodo para realizar a converso e um atributo para armazenar o resultado.


@ManagedBean public class ConversorMonetarioBean {

1 2

www.k19.com.br

91

C OMPONENTES V ISUAIS
3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 private String de ; private String para ; private Double valor ; private Double resultado ; private Map < String , Double > taxas = new LinkedHashMap < String , Double >() ; public ConversorMonetarioBean () { this . taxas . put ( " Real " , 1. ) ; this . taxas . put ( " Euro " , 2.33) ; this . taxas . put ( " Peso argentino " , .42) ; this . taxas . put ( " Dlar americano " , 1.84) ; } public void converte () { this . resultado = this . valor * this . taxas . get ( this . de ) / this . taxas . get ( this . para ) ; } // GETTERS E SETTERS }
Cdigo Java 6.7: ConversorMonetarioBean.java

92

No diretrio WebContent, crie um arquivo chamado conversor-monetario.xhtml. Nesse arquivo, implemente um formulrio para o usurio digitar os dados de entrada e ver o resultado da converso.
8

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : commandButton value = " Converter " action = " #{ conversorMonetarioBean . converte } " / > <h : inputText value = " #{ conversorMonetarioBean . valor } " / > <h : outputLabel value = " de " for = " de " / > <h : selectOneMenu value = " #{ conversorMonetarioBean . de } " id = " de " > <f : selectItems value = " #{ conversorMonetarioBean . taxas . keySet () } " var = " moeda " itemValue = " #{ moeda } " itemLabel = " #{ moeda } " / > </ h : selectOneMenu > <h : outputLabel value = " para " for = " para " / > <h : selectOneMenu value = " #{ conversorMonetarioBean . para } " id = " para " > <f : selectItems value = " #{ conversorMonetarioBean . taxas . keySet () } " var = " moeda " itemValue = " #{ moeda } " itemLabel = " #{ moeda } " / > </ h : selectOneMenu > </ h : form > Resultado : #{ conversorMonetarioBean . resultado } </ h : body >

92

www.k19.com.br

93
41 </ html >
Cdigo XHTML 6.35: conversor-monetario.xhtml

C OMPONENTES V ISUAIS

Acesse a aplicao em http://localhost:8 8 /K19-Componentes-Visuais/conversor-monetario.

xhtml

Exerccios Complementares
Considere o servio de atendimento ao consumidor de uma loja virtual. Voc deve criar um formulrio para que o consumidor possa se comunicar com a loja. Esse formulrio deve ter campos para o usurio informar o seu nome, e-mail, telefone, sexo e nmero do pedido. Alm disso, deve existir um campo para o usurio selecionar um assunto e outro para ele escrever o seu comentrio.
1

Textos e Imagens
Para inserir textos em uma pgina, podemos usar os componentes <h:outputText> e <h:outputFormat>. O texto exibido por tais componentes denido pelo atributo value. Em particular, o <h:outputFormat> permite diversos tipos de formatao do texto que ser exibido.
1 2 3 4 <h : outputFormat value = " Preo do produto { }: R$ {1} " > <f : param value = " #{ lojaBean . produto . nome } " / > <f : param value = " #{ lojaBean . produto . preco } " / > </ h : outputFormat >
Cdigo XHTML 6.37: Exemplo de utilizao do <h:outputFormat>

O componente <h:graphicImage> usado para inserir imagens. Podemos indicar o caminho da imagem atravs dos atributos value ou url. Esses dois atributos so exatamente iguais.
1 <h : graphicImage value = " / imagens / k19 - treinamentos . png " / >
Cdigo XHTML 6.38: Exemplo de insero de imagem

Para padronizar a organizao dos recursos da sua aplicao, o JSF 2 permite a criao de bibliotecas de imagens. Para criar uma biblioteca, basta adicionar um diretrio na pasta /resources (na raiz da aplicao). Por exemplo, se criarmos o diretrio /resources/imagens-k19/ e adicionarmos a imagem k19-treinamentos.png nesse diretrio, podemos inseri-la em uma pgina da seguinte forma:
1 <h : graphicImage library = " imagens - k19 " name = " k19 - treinamentos . png " / >
Cdigo XHTML 6.39: Exemplo de insero de imagem usando o atributo library

Mais Sobre
Todos os componentes do JSF possuem um atributo booleano chamado rendered. Esse atributo indica se o componente deve ser renderizado durante a etapa Render

www.k19.com.br

93

C OMPONENTES V ISUAIS

94

Response do processamento de uma requisio. O valor padro desse atributo true, o que
indica que o componente deve ser exibido. O preo de alguns produtos vendidos pela Amazon.com, por exemplo, no so exibidos na pgina de apresentao do produto. Para um produto desse tipo, o usurio precisa adicion-lo ao carrinho de compras para ento poder ver o seu preo. Como exemplo, suponha que um objeto do tipo Produto possua uma propriedade booleana chamada mostraPreco. Ela indica se o preo daquele produto deve ser exibido ou no. Assim, podemos associar o atributo rendered do componente responsvel pela exibio do preo do produto a essa propriedade. Isso pode ser feito usando expression language, como no exemplo abaixo.
1 2 3 4 5 <h : outputFormat value = " Preo do produto { }: R$ {1} " rendered = " #{ lojaBean . produto . mostraPreco } " > <f : param value = " #{ lojaBean . produto . nome } " / > <f : param value = " #{ lojaBean . produto . preco } " / > </ h : outputFormat >
Cdigo XHTML 6.40: O preo do produto exibido somente se o valor da propriedade mostraPreco for true

Exemplos
1. XHTML:
1 <h : outputText value = " Curso : #{ curso . sigla } - #{ curso . descricao } " / >

HTML gerado:
1 Curso : K12 - Desenvolvimento Web com JSF2 e JPA2

2. XHTML:
1 2 3 4 5 6 7 8 9 1 11 12 13 <h : outputFormat value = " { } amava {1} que amava {2} que amava {3} que amava {4} que amava {5} que no amava ningum . { } foi para os Estados Unidos , {1} para o convento , {2} morreu de desastre , {3} ficou para tia , {4} suicidou - se e {5} casou com J . Pinto Fernandes que no tinha entrado na histria . " > <f : param value = " Joo " / > <f : param value = " Teresa " / > <f : param value = " Raimundo " / > <f : param value = " Maria " / > <f : param value = " Joaquim " / > <f : param value = " Lili " / > </ h : outputFormat >

HTML gerado:
1 2 3 4 Joo amava Teresa que amava Raimundo que amava Maria que amava Joaquim que amava Lili que no amava ningum . Joo foi para os Estados Unidos , Teresa para o convento , Raimundo morreu de desastre , Maria ficou para tia , Joaquim suicidou - se e Lili casou com J . Pinto Fernandes que no tinha entrado na histria .

3. XHTML:
94
www.k19.com.br

95
1 <h : graphicImage value = " / imagens / k19 - treinamentos . png " / >

C OMPONENTES V ISUAIS

HTML gerado:
1 < img src = " / K19 - Componentes - Visuais / imagens / k19 - treinamentos . png " / >

Resultado:

Exerccios de Fixao
No arquivo conversor-monetario.xhtml do projeto K19-Componentes-Visuais, use a tag <h:outputFormat> para exibir o resultado do conversor monetrio.
10

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : commandButton value = " Converter " action = " #{ conversorMonetarioBean . converte } " / > <h : inputText value = " #{ conversorMonetarioBean . valor } " / > <h : outputLabel value = " de " for = " de " / > <h : selectOneMenu value = " #{ conversorMonetarioBean . de } " id = " de " > <f : selectItems value = " #{ conversorMonetarioBean . taxas . keySet () } " var = " moeda " itemValue = " #{ moeda } " itemLabel = " #{ moeda } " / > </ h : selectOneMenu > <h : outputLabel value = " para " for = " para " / > <h : selectOneMenu value = " #{ conversorMonetarioBean . para } " id = " para " > <f : selectItems value = " #{ conversorMonetarioBean . taxas . keySet () } " var = " moeda " itemValue = " #{ moeda } " itemLabel = " #{ moeda } " / > </ h : selectOneMenu > </ h : form > <h : outputFormat value = " { } em {1} equivale a {2} em {3} " rendered = " #{ conversorMonetarioBean . resultado != null } " > <f : param value = " #{ conversorMonetarioBean . valor } " / > <f : param value = " #{ conversorMonetarioBean . de } " / > <f : param value = " #{ conversorMonetarioBean . resultado } " / > <f : param value = " #{ conversorMonetarioBean . para } " / >

www.k19.com.br

95

C OMPONENTES V ISUAIS
44 45 46 47 </ h : outputFormat > </ h : body > </ html >
Cdigo XHTML 6.44: conversor-monetario.xhtml

96

Componentes de Organizao
O JSF dene dois componentes que nos ajudam a organizar visualmente os elementos de uma pgina JSF. <h:panelGrid> Organiza os elementos em uma grade. <h:panelGroup> Permite que diversos componentes sejam tratados como um nico componente. O <h:panelGrid> usado para organizar componentes em forma de uma grade. O uso de um <h:panelGrid> bastante simples. Basicamente, devemos congurar a quantidade de colunas que desejamos. Para isso, utilizamos o atributo columns.
1 2 3 4 5 6 7 8 9 1 11 12 <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome do curso : " for = " nome " / > <h : inputText value = " #{ cursosBean . curso . nome } " id = " nome " / > <h : outputLabel value = " Descrio : " for = " descricao " / > <h : inputTextarea value = " #{ cursosBean . curso . descricao } " id = " descricao " / > <h : outputLabel value = " Carga horria : " for = " carga - horaria " / > <h : inputText value = " #{ cursosBean . curso . cargaHoraria } " id = " carga - horaria " / > <h : commandButton action = " #{ cursosBean . cadastraCurso } " value = " Cadastrar " / > </ h : panelGrid >
Cdigo XHTML 6.45: Organizao de um formulrio com o <h:panelGrid>

Os componentes so inseridos na grade de acordo com a ordem em que esto apresentados no cdigo. O primeiro elemento inserido na primeira coluna da primeira linha. O segundo elemento inserido na segunda coluna da primeira linha. Uma vez que uma linha foi completamente preenchida, o prximo componente inserido na primeira coluna da prxima linha, e o processo se repete at o ltimo componente. Suponha que seja necessrio inserir mais de um componente em uma mesma clula de um

<h:panelGrid>. No exemplo acima, podemos adicionar um cone de um relgio ao lado do rtulo


Carga horria:. No entanto, queremos que a imagem e o rtulo sejam colocados na mesma clula. Para isso, podemos agrup-los usando um <h:panelGroup>.
1 2 3 4 <h : panelGroup > <h : outputLabel value = " Carga horria : " for = " carga - horaria " / > <h : graphicImage library = " imagens " name = " relogio . png " / > </ h : panelGroup >
Cdigo XHTML 6.46: Agrupando componentes com o <h:panelGroup>

96

www.k19.com.br

97

C OMPONENTES V ISUAIS

Exemplos
1. XHTML:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome do curso : " for = " nome " / > <h : inputText value = " #{ cursosBean . curso . nome } " id = " nome " / > <h : outputLabel value = " Descrio : " for = " descricao " / > <h : inputTextarea value = " #{ cursosBean . curso . descricao } " id = " descricao " / > <h : panelGroup > <h : outputLabel value = " Carga horria : " for = " carga - horaria " / > <h : graphicImage library = " imagens " name = " relogio . png " / > </ h : panelGroup > <h : inputText value = " #{ cursosBean . curso . cargaHoraria } " id = " carga - horaria " / > <h : commandButton action = " #{ cursosBean . cadastraCurso } " value = " Cadastrar " / > </ h : panelGrid >

HTML gerado:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 < table > < tbody > < tr > < td > < label for = " nome " > Nome do curso : </ label > </ td > < td > < input id = " nome " type = " text " name = " nome " / > </ td > </ tr > < tr > < td > < label for = " descricao " > Descrio : </ label > </ td > < td > < textarea id = " descricao " name = " descricao " > </ textarea > </ td > </ tr > < tr > < td > < label for = " carga - horaria " > Carga horria : </ label > < img src = " / K19 - Componentes - Visuais / javax . faces . resource / relogio . png . xhtml ? ln = imagens " /> </ td > < td > < input id = " carga - horaria " type = " text " name = " carga - horaria " / > </ td > </ tr > < tr > < td > < input type = " submit " name = " j_idt98 " value = " Cadastrar " / > </ td > </ tr > </ tbody > </ table >

Resultado:
Nome do curso: Descrio:

Carga horria: Cadastrar

Tabelas
www.k19.com.br

97

C OMPONENTES V ISUAIS

98

O JSF fornece o componente <h:dataTable> para a criao de tabelas. Podemos associar uma lista de elementos a um <h:dataTable> atravs do atributo value. Automaticamente, esse componente gera uma linha para cada item da lista. Os itens da lista podem ser acessados atravs de uma varivel denida pelo atributo var. As colunas da tabela so denidas pelo componente <h:column>. Podemos acrescentar cabealhos e rodaps tabela e a cada coluna usando o componente <f:facet>. Veja um exemplo a seguir.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 <h : dataTable value = " #{ cursosBean . cursos } " var = " curso " > <f : facet name = " header " > Lista de cursos </ f : facet > <h : column > <f : facet name = " header " > Sigla </ f : facet > #{ curso . sigla } </ h : column > <h : column > <f : facet name = " header " > Nome </ f : facet > #{ curso . nome } </ h : column > <h : column > <f : facet name = " header " > Descrio </ f : facet > #{ curso . descricao } </ h : column > <h : column > <f : facet name = " header " > Adicionar turma </ f : facet > <h : commandLink value = " Adicionar turma " action = " #{ cursosBean . adicionarTurma ( curso ) } " / > </ h : column > </ h : dataTable >
Cdigo XHTML 6.48: Exemplo de criao de tabela com o componente <h:dataTable>

Observe, no exemplo acima, que a tabela est associada propriedade cursos do managed bean cursosBean. A varivel curso utilizada para acessar cada um dos elementos da propriedade cursos. O cabealho Lista de cursos da tabela est denido com o componente <f:facet> assim como o cabealho de cada coluna (Sigla, Nome, Descrio e Adicionar turma). O HTML gerado pelo JSF a partir do cdigo acima seria mais ou menos assim:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 < table > < thead > < tr > < th colspan = " 4 " scope = " colgroup " > Lista de cursos </ th > </ tr > < tr > < th scope = " col " > Sigla </ th > < th scope = " col " > Nome </ th > < th scope = " col " > Descrio </ th > < th scope = " col " > Adicionar turma </ th > </ tr > </ thead > < tbody > < tr > < td > K11 </ td >

98

www.k19.com.br

99
16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 < td > Orientao a Objetos em Java </ td > < td > Com este curso voc vai obter uma base slida de conhecimentos de Java e de Orientao a Objetos </ td > < td > < input type = " submit " name = " j_idt1 : j_idt1 1 : : j_idt114 " value = " Adicionar turma " / > </ td > </ tr > < tr > < td > K12 </ td > < td > Desenvolvimento Web com JSF2 e JPA2 </ td > < td > Depois deste curso , voc estar apto a desenvolver aplicaes Web com os padres da plataforma Java </ td > < td > < input type = " submit " name = " j_idt1 : j_idt1 1 :1: j_idt114 " value = " Adicionar turma " / > </ td > </ tr > < tr > < td > K21 </ td > < td > Persistncia com JPA2 e Hibernate </ td > < td > Neste curso de Java Avanado , abordamos de maneira profunda os recursos de persistncia do JPA2 e do Hibernate </ td > < td > < input type = " submit " name = " j_idt1 : j_idt1 1 :2: j_idt114 " value = " Adicionar turma " / > </ td > </ tr > </ tbody > </ table >
Cdigo HTML 6.24: Cdigo HTML gerado pelo JSF

C OMPONENTES V ISUAIS

A gura abaixo mostra como essa tabela apresentada no navegador.

Lista de cursos Sigla Nome Orientao a Objetos em Java Desenvolvimento Web com JSF2 e JPA2 Persistncia com JPA2 e Hibernate Descrio Com este curso voc vai obter uma base slida de conhecimentos de Java e de Orientao a Objetos. Depois deste curso, voc estar apto a desenvolver aplicaes Web com os padres da plataforma Java Neste curso de Java Avanado, abordamos de maneira profunda os recursos de persistncia do JPA2 e do Hibernate Adicionar Turma
Adiciona turma

K11

K12

Adiciona turma

K21

Adiciona turma

Figura 6.1: Representao do HTML no navegador

www.k19.com.br

99

C OMPONENTES V ISUAIS

100

Exerccios de Fixao
No projeto K19-Componentes-Visuais, crie uma pgina que contenha um formulrio para adicionar cursos e que exiba os cursos j adicionados. Primeiramente, crie uma classe chamada Curso para representar um curso. Essa classe deve ter dois atributos do tipo String: um para armazenar o nome e outro para armazenar a sigla do curso.
11

1 2 3 4 5 6

public class Curso { private String nome ; private String sigla ; // GETTERS E SETTERS }
Cdigo Java 6.9: Curso.java

Crie uma classe chamada CursosBean para armazenar uma lista de cursos. Para que os cursos adicionados sejam mantidos nessa varivel entre uma requisio e outra, marque a classe com a anotao @SessionScoped. No Captulo 9 discutiremos sobre escopos de managed beans.
12

1 2 3 4 5 6 7

@ManagedBean @SessionScoped public class CursosBean { private List < Curso > cursos = new ArrayList < Curso >() ; // GETTER E SETTER }
Cdigo Java 6.10: CursosBean.java

13 Na classe CursosBean, adicione dois atributos do tipo String para armazenar o nome e a sigla de um curso e crie um mtodo para adicionar um curso com esse nome e essa sigla.

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

@ManagedBean @SessionScoped public class CursosBean { private List < Curso > cursos = new ArrayList < Curso >() ; private Curso curso = new Curso () ; public void adicionaCurso () { this . cursos . add ( this . curso ) ; this . curso = new Curso () ; } // GETTERS E SETTERS }
Cdigo Java 6.11: CursosBean.java

Crie um arquivo chamado cursos.xhtml no diretrio WebContent e implemente um formulrio para adicionar cursos lista de cursos do managed bean cursosBean. Use a tag <h:panelGrid> para organizar o formulrio.
14

1 2 3 4 5

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 "

100

www.k19.com.br

101
6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 xmlns : f = " http :// java . sun . com / jsf / core " >

C OMPONENTES V ISUAIS

<h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ cursosBean . curso . nome } " id = " campo - nome " / > <h : outputLabel value = " Sigla : " for = " campo - sigla " / > <h : inputText value = " #{ cursosBean . curso . sigla } " id = " campo - sigla " / > <h : commandButton value = " Adicionar " action = " #{ cursosBean . adicionaCurso } " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML 6.49: cursos.xhtml

No arquivo cursos.xhtml, insira um trecho de cdigo para exibir os cursos j adicionados. Use a tag <h:dataTable> para apresentar os cursos. Voc pode usar o atributo rendered desse componente para exibir a tabela apenas quando a lista de cursos no est vazia.
15

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Sigla : " for = " campo - sigla " / > <h : inputText value = " #{ cursosBean . curso . sigla } " id = " campo - sigla " / > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ cursosBean . curso . nome } " id = " campo - nome " / > <h : commandButton value = " Adicionar " action = " #{ cursosBean . adicionaCurso } " / > </ h : panelGrid > </ h : form > <h : dataTable value = " #{ cursosBean . cursos } " var = " curso " rendered = " #{ not empty cursosBean . cursos } " > <f : facet name = " header " > Lista de Cursos </ f : facet > <h : column > <f : facet name = " header " > Sigla </ f : facet > #{ curso . sigla } </ h : column > <h : column > <f : facet name = " header " > Nome </ f : facet > #{ curso . nome } </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 6.50: cursos.xhtml

www.k19.com.br

101

C OMPONENTES V ISUAIS

102

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Componentes-Visuais/cursos.xhtml

Exerccios Complementares
2 Usando o componente <h:dataTable>, liste os produtos de uma loja virtual. A tabela deve mostrar o nome e o preo de cada produto. No diretrio src, crie uma classe chamada Produto. Essa classe deve ter um atributo do tipo String para armazenar o nome do produto e um atributo do tipo Double para guardar o preo do produto. Crie uma classe chamada ProdutosBean para guardar uma lista de produtos. Implemente a listagem de produtos em um arquivo chamado lista-de-produtos.xhtml no diretrio WebContent.

Na classe Produto, acrescente uma propriedade do tipo Boolean para indicar se o preo do produto deve ser exibido. Modique a tabela de listagem dos produtos para considerar essa nova restrio. Se o preo de um produto no puder ser exibido, ento o texto Adicione o produto ao carrinho para ver o preo deve aparecer no lugar do preo do produto.
3

Mensagens
Durante o processamento de uma requisio, podemos adicionar mensagens que podem ser exibidas na pgina de resposta. Uma mensagem pode ser adicionada, por exemplo, da seguinte forma:
1 2 FacesMessage mensagem = new FacesMessage ( " Turma adicionada " ) ; FacesContext . getCurrentInstance () . addMessage ( null , mensagem ) ;
Cdigo Java 6.16: Adicionando uma mensagem

O primeiro parmetro do mtodo addMessage() dene qual componente ser associado mensagem adicionada. Quando o valor null passado nesse parmetro, a mensagem considerada global, ou seja, ela no ser associada a nenhum componente especco. Na tela, podemos exibir todas as mensagens geradas no processamento da requisio atravs do componente <h:messages>. Se desejarmos exibir apenas as mensagens globais, devemos utilizar o atributo globalOnly da seguinte forma:
1 <h : messages globalOnly = " true " / >
Cdigo XHTML 6.53: Exibindo as mensagens globais

As mensagens so comumente utilizadas para indicar erros de converso e validao. Veremos mais detalhes sobre isso no Captulo 10.

Adicionando JavaScript e CSS


Podemos adicionar recursos como scripts e arquivos de estilos (CSS) usando diretamente as tags <script> e <link> do HTML. Contudo, o JSF dene outra maneira de inserir esses recursos nas pginas da aplicao. Tais recursos podem ser inseridos com as tags <h:outputScript> e <h:out102
www.k19.com.br

103

C OMPONENTES V ISUAIS

putStylesheet>. A utilizao dessas tags facilita a criao de componentes visuais personalizados


ou o gerenciamento de recursos que dependem de regionalidade.
1 2 <h : outputScript name = " k19 . js " library = " javascript " target = " head " / > <h : outputStylesheet name = " k19 . css " library = " css " / >
Cdigo XHTML 6.54: Exemplo de adio de cdigo JavaScript e arquivo CSS na pgina da aplicao

Outros Componentes

<ui:remove>
Para comentar (ou excluir) partes de cdigo XHTML de uma aplicao, o JSF prov a tag <ui:remove>. Qualquer trecho de cdigo dentro dessa tag removido durante o processamento de uma pgina JSF. No exemplo abaixo, a caixa para inserir o sobrenome do usurio no ser processada e, portanto, no ser exibida na pgina gerada.
1 2 3 4 <h : outputText value = " Nome : #{ testeBean . nome } " / > < ui : remove > <h : outputText value = " Sobrenome : #{ testeBean . sobrenome } " / > </ ui : remove >
Cdigo XHTML 6.55: Excluindo parte do cdigo de uma pgina JSF

O trecho de cdigo HTML correspondente, gerado pelo JSF, o seguinte:


1 Nome : Jonas
Cdigo HTML 6.25: Trecho de cdigo HTML gerado pelo JSF

Alternativamente, podemos usar os delimitadores <!-- e --> do XML para comentar o cdigo. Nesse caso, contudo, o trecho de cdigo comentado ser processado pelo JSF. Por exemplo, a partir do cdigo
1 2 3 4 <h : outputText value = " Nome : #{ testeBean . nome } " / > <! -<h : outputText value = " Sobrenome : #{ testeBean . sobrenome } " / > -- >
Cdigo XHTML 6.56: Uso de delimitadores do XML para comentar cdigo

o JSF produzir o seguinte cdigo HTML:


1 2 3 4 Nome : Jonas <! -<h : outputText value = " Sobrenome : Hirata " / > -- >
Cdigo HTML 6.26: Trecho de cdigo HTML gerado pelo JSF

Note que o cdigo dentro do comentrio foi processado pelo JSF. A string "Hirata" foi obtida da propriedade sobrenome do managed bean testeBean.
www.k19.com.br

103

C OMPONENTES V ISUAIS

104

<ui:repeat>
A tag <ui:repeat> usada para iterar sobre colees. Ela possui dois atributos obrigatrios: value e var. O atributo value deve ser associado a uma coleo de objetos e o atributo var deve denir o nome da varivel. Essa varivel ser usada para referenciar cada um dos elementos da coleo. No exemplo abaixo, temos um cdigo para gerar uma lista HTML no ordenada a partir de uma coleo de cursos.
1 2 3 4 5 6 7 8 <h : outputText value = " Alguns cursos da K19 : " / > < ul > < ui : repeat value = " #{ testeBean . cursos } " var = " curso " > < li > <h : outputText value = " #{ curso . sigla }: #{ curso . nome } " / > </ li > </ ui : repeat > </ ul >
Cdigo XHTML 6.57: Iterando sobre uma lista de cursos

A partir desse cdigo, o JSF gera o seguinte cdigo HTML:


1 2 3 4 5 6 7 Alguns cursos da K19 : < ul > < li > K11 : Orientao a Objetos em Java </ li > < li > K12 : Desenvolvimento Web com JSF2 e JPA2 </ li > < li > K21 : Persistncia com JPA2 e Hibernate </ li > < li > K51 : Design Patterns em Java </ li > </ ul >
Cdigo HTML 6.27: Cdigo HTML gerado pelo JSF

Exerccios de Fixao
No projeto K19-Componentes-Visuais, crie um arquivo CSS para formatar a pgina que lista os cursos. No diretrio WebContent, crie um diretrio chamado resources. Dentro de resources, crie um diretrio chamado css. Crie um arquivo chamado k19.css contendo o estilo desejado e adicione-o ao diretrio WebContent/resources/css.
16

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

body { font - family : arial , helvetica , sans - serif ; font - size : 14 px ; } h1 { color : # 6699; font - size : 18 px ; } ul { list - style - type : square ; } input { background - color : # E6E6FA ; border : solid 1 px # ; }
Cdigo CSS 6.1: k19.css

104

www.k19.com.br

105
17

C OMPONENTES V ISUAIS

Use a tag <h:outputStylesheet> para incluir o arquivo de estilos na pgina denida por cursos.xhtml. Use a tag <ui:repeat> para exibir os cursos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : outputStylesheet name = " k19 . css " library = " css " / > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Sigla : " for = " campo - sigla " / > <h : inputText value = " #{ cursosBean . sigla } " id = " campo - sigla " / > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ cursosBean . nome } " id = " campo - nome " / > <h : commandButton value = " Adicionar " action = " #{ cursosBean . adicionaCurso } " / > </ h : panelGrid > </ h : form > < h1 > Alguns cursos da K19 : </ h1 > < ul > < ui : repeat value = " #{ cursosBean . cursos } " var = " curso " > < li > <h : outputText value = " #{ curso . sigla }: #{ curso . nome } " / > </ li > </ ui : repeat > </ ul > </ h : body > </ html >
Cdigo XHTML 6.58: cursos.xhtml

Exerccios Complementares
Considere novamente a pgina de adio e listagem de cursos. Modique sua aplicao de forma que uma mensagem de conrmao seja exibida na tela aps o usurio adicionar um novo curso.
4

www.k19.com.br

105

C OMPONENTES V ISUAIS

106

106

www.k19.com.br

CAPTULO

T EMPLATES E M ODULARIZAO

Certamente, voc j ouviu algum falar da importncia da reutilizao de cdigo no desenvolvimento de software. Os objetivos principais dessa reutilizao so diminuir o tempo e o custo do desenvolvimento e da manuteno das aplicaes. Com essa ideia em mente, um projeto chamado Facelets foi desenvolvido com o objetivo principal de facilitar todo o processo de desenvolvimento e manuteno das telas de uma aplicao JSF. O Facelets j faz parte do JSF 2 e a engine padro para o gerenciamento das telas de aplicaes web JSF 2.

Templates
A reutilizao do cdigo das telas realizada principalmente pelo uso de templates. A ideia identicar um padro em um determinado conjunto de telas e deni-lo atravs de um esqueleto (template). Esse esqueleto formado por trechos estticos e dinmicos. O posicionamento desses trechos sempre xo. Contudo, ao contrrio do contedo de um trecho esttico, o contedo de um trecho dinmico pode diferir de tela para tela. Por exemplo, considere uma aplicao na qual todas as telas so divididas em trs partes: cabealho, corpo e rodap. Essas partes esto sempre posicionadas da mesma forma. O cabealho posicionado no topo da pgina, o rodap, no nal e o corpo, entre os dois anteriores. O contedo do cabealho e do rodap sempre o mesmo em todas as telas da aplicao. Por outro lado, o contedo do corpo varia de tela para tela.
www.k19.com.br

107

T EMPLATES E M ODULARIZAO
Pgina 2
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

108

Pgina 2

Pgina 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

Pgina 3
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

Pgina 1

Template

Pgina 3

Pgina 4
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

Pgina 4
Figura 7.1: Template utilizado por diversas pginas

Criando um template
A criao de um template simples. Basta criar um arquivo XHTML e denir o posicionamento dos trechos estticos e dinmicos. O contedo dos trechos estticos tambm deve ser denido da forma usual dentro do template. Por outro lado, o contedo dos trechos dinmicos s ser denido nas telas. Para indicar o posicionamento dos trechos dinmicos, devemos utilizar a tag <ui:insert>.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 >

108

www.k19.com.br

109
17 18 19 2 21 22 23 24 25

T EMPLATES E M ODULARIZAO

< ui : insert name = " corpo - da - pagina " > Espao para o contedo da tela </ ui : insert > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 1 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 7.1: template.xhtml

O componente <ui:insert> utilizado para posicionar os trechos dinmicos. O atributo name desse componente utilizado para nomear os trechos dinmicos. Normalmente, a declarao <!DOCTYPE> no varia de tela para tela dentro de uma aplicao. Dessa forma, podemos adicion-la de forma esttica no template, conforme o exemplo acima. Vimos no Captulo 6 que fundamental a utilizao dos componentes <h:head> e <h:body>. No exemplo acima, esses componentes foram denidos estaticamente no template. Assim, todas as telas que utilizam esse template no correm mais o risco de carem sem esses componentes.

Utilizando templates
Para criar uma tela que usa um determinado template, devemos criar um arquivo XHTML e adicionar a tag <ui:composition> a esse arquivo. O arquivo do template desejado deve ser indicado atravs do atributo template da tag <ui:composition>.
1 2 3 4 < ui : composition template = " / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " > </ ui : composition >
Cdigo XHTML 7.2: tela.xhtml

Todo contedo no contido na tag <ui:composition> ser descartado pelo JSF no processo de construo da tela. O contedo de um trecho dinmico pode ser denido atravs do componente <ui:define>. Esse componente possui o atributo name que utilizado para indicar qual trecho dinmico do template queremos denir. No exemplo acima, podemos denir o contedo do trecho dinmico corpo-da-pagina da seguinte forma:
1 2 3 4 5 6 7 8 9 1 11 < ui : composition template = " / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " corpo - da - pagina " > < h1 > Lista de treinamentos </ h1 > < h2 > K11 - Orientao a Objetos em Java </ h2 > < h2 > K12 - Desenvolvimento Web com JSF2 e JPA2 </ h2 > </ ui : define > </ ui : composition >
Cdigo XHTML 7.3: tela.xhtml

www.k19.com.br

109

T EMPLATES E M ODULARIZAO

110

Se o contedo de um trecho dinmico no for denido, o JSF utilizar o contedo existente no corpo da tag <ui:insert> denido no template. No exemplo acima, caso o contedo do trecho dinmico corpo-da-pagina no fosse denido no arquivo tela.xhtml, o JSF utilizaria o texto Espao para o contedo da tela, que foi denido no arquivo template.xhtml como contedo padro para esse trecho.

Pare para pensar...


Em geral, os templates no denem uma tela concreta da aplicao. Eles funcionam como uma base para a criao de telas concretas. Dessa forma, no seria interessante que os navegadores acessassem diretamente a tela correspondente a um template, pois, provavelmente, essa tela estaria incompleta. Para evitar esse comportamento indesejado, podemos colocar todos os templates dentro do diretrio /WEB-INF.

Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Templates-e-Modularizacao seguindo os passos vistos no exerccio do Captulo 5.
1

Crie um diretrio chamado templates na pasta WEB-INF. Crie um template chamado template.xhtml na pasta WEB-INF/templates. Copie o arquivo k19-logo.png da pasta K19-Arquivos/imagens, que est na rea de Trabalho, para a pasta WebContent do projeto K19-Templates-e-Modularizacao.
2

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 7.4: template.xhtml

Monte uma tela que use o template criado no exerccio anterior. O nome do arquivo deve ser

formulario.xhtml.
1 2 3 4 5 < ui : composition template = " / WEB - INF / templates / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " >

110

www.k19.com.br

111
6 7 8 9 1 11 12 13 < 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 >
Cdigo XHTML 7.5: formulario.xhtml

T EMPLATES E M ODULARIZAO

Verique o resultado acessando a url:

http://localhost:8 8 /K19-Templates-e-Modularizacao/formulario.xhtml

Modularizao
Os trechos estticos ou dinmicos denidos em um template possuem posio xa. Em determinadas situaes, necessrio tornar exvel o posicionamento de um determinado trecho. Por exemplo, considere uma aplicao com 50 pginas diferentes. Os usurios dessa aplicao podem enviar mensagens para o administrador do sistema quando identicarem algum problema. Essas mensagens so enviadas atravs de um formulrio HTML. Esse formulrio de contato deve ser exibido em todas as telas da aplicao. Nesse caso, poderamos pensar em criar um template e denir o formulrio de contato como um trecho esttico desse template. Contudo, h uma restrio importante que descarta essa abordagem. O formulrio de contato deve ser exibido em posies diferentes nas telas da aplicao. Por exemplo, em algumas telas o formulrio aparecer no topo e em outras ele aparecer no centro.
Suspendisse tristique dolor sit amet felis vehicula rutrum. Phasellus fringilla mauris eu turpis sodales congue. Etiam ultricies nisl in

Mdulo / Partial

Lorem ipsum
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra Suspendisse tristique dolor sit amet felis vehicula rutrum. Phasellus fringilla mauris eu turpis sodales congue.

Lorem ipsum
Suspendisse tristique dolor sit amet felis vehicula rutrum. Phasellus fringilla mauris eu turpis sodales congue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

Lorem ipsum
Suspendisse tristique dolor sit amet felis vehicula rutrum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Suspendisse tristique dolor sit amet felis vehicula rutrum.

Pgina 1

Pgina 2

Pgina 3

Figura 7.2: Mdulo reaproveitado em diversas pginas

Nessa situao, a melhor abordagem denir o formulrio de contato, separadamente, em um arquivo XHTML. O cdigo XHTML que dene o formulrio de contato deve ser inserido no corpo da tag <ui:composition>. Observe o cdigo abaixo.
www.k19.com.br

111

T EMPLATES E M ODULARIZAO
1 2 3 4 5 6 7 8 9 1 11 12 13 < ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : form > <h : panelGrid > <h : outputLabel value = " Mensagem : " for = " mensagem " / > <h : inputTextarea id = " mensagem " value = " #{ mensagensBean . mensagem } " / > <h : commandButton value = " Enviar " action = " #{ mensagensBean . envia } " / > </ h : panelGrid > </ h : form > </ ui : composition >
Cdigo XHTML 7.6: formulario-de-contato.xhtml

112

Com o formulrio de contato denido em um arquivo separado, podemos utilizar a tag <ui:in-

clude> para adicion-lo onde for necessrio.


1 2 3 ... < ui : include src = " / formulario - de - contato . xhtml " / > ...
Cdigo XHTML 7.7: Inserindo o formulrio de contato

Parmetros
Em algumas situaes necessrio passar parmetros de um arquivo XHTML para outro. Por exemplo, considere a aplicao de uma livraria. Na primeira pgina dessa aplicao, uma lista com livros mais vendidos exibida no canto direito. Em outra pgina, uma lista com os livros mais caros exibida no canto esquerdo. Podemos criar um arquivo XHTML e atribuir a ele a tarefa de exibir uma lista qualquer de livros independentemente de posicionamento.
1 2 3 4 5 6 7 8 9 < ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : dataTable value = " #{ livros } " var = " livro " > ... </ h : dataTable > </ ui : composition >
Cdigo XHTML 7.8: lista-livros.xhtml

Observe, no cdigo acima, que o componente <h:dataTable> foi vinculado a uma varivel chamada livros. Essa varivel um parmetro do arquivo lista-livros.xhtml. Na primeira pgina da aplicao da livraria, podemos adicionar o arquivo lista-livros.xhtml com a tag <ui:include>, passando como parmetro a lista dos livros mais vendidos. Para isso, devemos utilizar o componente <ui:param>.
1 2 3 ... < ui : include src = " / lista - livros . xhtml " > < ui : param name = " livros " value = " #{ livrosBean . listaDosLivrosMaisVendidos } " / >

112

www.k19.com.br

113
4 5 </ ui : include > ...

T EMPLATES E M ODULARIZAO

Cdigo XHTML 7.9: Inserindo a lista dos livros mais vendidos

Em outra pgina da aplicao da livraria, podemos adicionar o arquivo lista-livros.xhtml passando como parmetro a lista dos livros mais caros.
1 2 3 4 5 ... < ui : include src = " / lista - livros . xhtml " > < ui : param name = " livros " value = " #{ livrosBean . listaDosLivrosMaisCaros } " / > </ ui : include > ...
Cdigo XHTML 7.10: Inserindo a lista dos livros mais caros

Exerccios de Fixao
4 Vamos implementar uma listagem de instrutores no nosso projeto K19-Templates-e-Modularizacao. O primeiro passo criar uma classe para modelar os instrutores. Crie um pacote chamado model no projeto K19-Templates-e-Modularizacao e adicione nele uma classe chamada Instrutor

com seguinte cdigo:


1 2 3 4 5 6 7 8 package model ; public class Instrutor { private String nome ; private String dataDeNascimento ; // GETTERS E SETTERS }
Cdigo Java 7.1: Instrutor.java

Faa um managed bean que fornea uma lista de instrutores para uma tela de listagem de instrutores. Crie um pacote chamado managedbeans no projeto K19-Templates-e-Modularizacao e adicione nele uma classe chamada InstrutorBean com seguinte cdigo:
5

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

package managedbeans ; import import import import java . util . ArrayList ; java . util . List ; model . Instrutor ; javax . faces . bean . ManagedBean ;

@ManagedBean public class InstrutorBean { private List < Instrutor > instrutores = new ArrayList < Instrutor >() ; public InstrutorBean () { Instrutor rafael = new Instrutor () ; rafael . setNome ( " Rafael Cosentino " ) ; rafael . setDataDeNascimento ( " 3 /1 /1984 " ) ; Instrutor marcelo = new Instrutor () ; marcelo . setNome ( " Marcelo Martins " ) ; marcelo . setDataDeNascimento ( " 2/ 4/1985 " ) ;

www.k19.com.br

113

T EMPLATES E M ODULARIZAO
22 23 24 25 26 27 28 29 3 31 32 33 this . instrutores . add ( rafael ) ; this . instrutores . add ( marcelo ) ; } public List < Instrutor > getInstrutores () { return instrutores ; } public void setInstrutores ( List < Instrutor > instrutores ) { this . instrutores = instrutores ; } }
Cdigo Java 7.2: InstrutorBean.java

114

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 K19-Templates-e-Modularizacao e se chamar instrutor-info.xhtml.
6

1 2 3 4 5 6 7 8 9 1 11

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

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

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

< ui : composition template = " / WEB - INF / templates / template . xhtml " 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 : 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 >
Cdigo XHTML 7.12: listagem-de-instrutores.xhtml

Veja o resultado acessando a url:

http://localhost:8 8 /K19-Templates-e-Modularizacao/listagem-de-instrutores.xhtml

Exerccios Complementares
114
www.k19.com.br

115

T EMPLATES E M ODULARIZAO

Usando templates, voc deve criar uma pgina para exibir os detalhes dos produtos de uma loja virtual. A pgina de apresentao dos produtos deve ter o seguinte formato. Uma imagem do produto deve ser apresentada do lado esquerdo da pgina. O nome e o preo do produto devem ser exibidos do lado direito da imagem. Uma descrio do produto deve aparecer abaixo de tudo. Alm disso, o logotipo da loja deve aparecer no topo da pgina e, logo abaixo, deve haver uma caixa de seleo para escolher o produto cujos detalhes sero exibidos.
1

www.k19.com.br

115

T EMPLATES E M ODULARIZAO

116

116

www.k19.com.br

CAPTULO
www.k19.com.br/artigo

N AVEGAO

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.

www.k19.com.br Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean rutrum accumsan lorem, non euismod ligula aliquet in. Proin vitae ultricies sapien. Donec volutpat lacus eleifend sapien vestibulum eu dapibus mi pharetra. Nunc at quam erat. Sed vel dui a tortor ultricies fringilla eget et ipsum. Maecenas at sem at nunc pharetra consectetur. Nulla enim nisi, tristique ac rhoncus vel, rhoncus a dolor. Ut dignissim, nisi vitae varius dictum,

LEIA MAIS

COMPRAR

www.k19.com.br/loja

Donec vel feugiat ligula. Mauris bibendum suscipit purus, eu aliquam dui venenatis sit amet. Praesent tortor nisl, egestas ut laoreet non, hendrerit at sapien.

Figura 8.1: Navegao entre pginas

Navegao Implcita
Na navegao implcita, quando o usurio clica em algum boto ou link, um sinal (outcome) enviado para o JSF. Esse sinal uma string que ser utilizada pelo tratador de navegao do JSF para denir a prxima tela que ser apresentada ao usurio. Considere, por exemplo, um link ou boto de uma tela (denida pelo arquivo pagina1.xhtml) que envia o outcome pagina2. Quando um usurio clicar nesse link ou boto, ele ser redirecionado para a tela denida pelo arquivo pagina2.xhtml. Esse arquivo deve estar no mesmo diretrio do arquivo pagina1.xhtml. Nesse caso, o outcome igual ao nome do arquivo de resposta sem o suxo .xhtml.
www.k19.com.br

117

N AVEGAO

118

Quando utilizamos os componentes <h:commandButton> e <h:commandLink> para criar botes e links, devemos denir os outcomes atravs do atributo action. Por outro lado, quando utilizamos os componentes <h:button> e <h:link>, devemos denir os outcomes atravs do atributo outcome. Veja como seria o cdigo da pagina1.xhtml e pagina2.xhtml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > K19 Pgina 1 </ h1 > <h : form > <h : commandButton value = " Pgina 2 " action = " pagina2 " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 8.1: pagina1.xhtml

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > K19 Pgina 2 </ h1 > <h : link outcome = " pagina1 " > <h : outputText value = " Pgina 1 " / > </ h : link > </ h : body > </ html >
Cdigo XHTML 8.2: pagina2.xhtml

Alm do nome, os outcomes tambm podem determinar o caminho do arquivo de resposta. Se o outcome comear com caractere /, esse caminho ser denido a partir do diretrio raiz da aplicao web . Caso contrrio, ser denido a partir do diretrio atual. Considere, por exemplo, um arquivo chamado pagina1.xhtml no diretrio /diretorio1 e um arquivo chamado pagina2.xhtml no diretrio /diretorio1/diretorio2. No arquivo pagina1.xhtml, podemos adicionar um boto para navegar para o arquivo pagina2.xhtml da seguintes formas:
1 2 3 ... <h : commandButton value = " Pgina 2 " action = " / diretorio1 / diretorio2 / pagina2 " / > ...
Cdigo XHTML 8.3: pagina1.xhtml

1 2 3

... <h : commandButton value = " Pgina 2 " action = " diretorio2 / pagina2 " / > ...
Cdigo XHTML 8.4: pagina1.xhtml

118

www.k19.com.br

119

N AVEGAO

Note que, no primeiro cdigo, o caminho denido a partir do diretrio raiz da aplicao web. J no segundo cdigo, o caminho denido relativamente ao diretrio atual.

Navegao Explcita
Na navegao explcita, podemos associar um outcome a um arquivo de resposta independentemente do nome ou do caminho desse arquivo. Essa associao deve ser registrada no arquivo de congurao do JSF, o faces-config.xml. Para registrar uma navegao explcita, podemos adicionar trs informaes no arquivo de congurao do JSF: O caminho do arquivo que dene a tela de origem. O outcome. O caminho do arquivo que dene a tela de resposta. Veja o exemplo abaixo.
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 >
Cdigo XML 8.1: Registrando uma navegao explcita

Aps o registro da navegao acima, podemos adicionar um boto ou link no arquivo pagina1.xhtml com o outcome proxima para navegar para o arquivo pagina2.xhtml.
1 2 3 ... <h : commandButton value = " Prxima tela " action = " proxima " / > ...
Cdigo XHTML 8.5: pagina1.xhtml

Importante
O JSF utiliza a seguinte lgica para determinar a pgina de resposta. Primeiro, ele verica se o outcome compatvel com alguma regra de navegao registrada no arquivo faces-config.xml. Caso seja, o JSF realizar uma navegao explcita processando essa regra. Caso contrrio, o JSF tentar realizar uma navegao implcita, procurando um arquivo compatvel com o outcome. Se esse arquivo no existir, a tela atual ser reapresentada.

Mais Sobre
Podemos registrar uma regra de navegao para diversos arquivos utilizando wildcards. Considere o exemplo abaixo.

www.k19.com.br

119

N AVEGAO

120

1 2 3 4 5 6 7 8

< navigation - rule > < from - view - id >/ K19 /* </ from - view - id > < navigation - case > < from - outcome > home </ from - outcome > <to - view - id >/ home . xhtml </ to - view - id > </ navigation - case > </ navigation - rule >
Cdigo XML 8.2: Registrando uma navegao explcita

O caractere * na tag <from-view-id> indica que essa regra de navegao ser aplicada para todo arquivo do diretrio /K19.

Mais Sobre
Podemos criar navegaes condicionais. Considere, por exemplo, uma aplicao em que os usurios podem escolher a verso da interface que desejam utilizar. As regras de navegao podem ento considerar a preferncia do usurio. Para isso, podemos adicionar a tag <if> na denio de uma regra de navegao. Veja o exemplo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 < navigation - rule > < from - view - id >/ login . xhtml </ from - view - id > < navigation - case > < from - outcome > sucesso </ from - outcome > < if > #{ usuarioBean . preferencias [ versao - da - interface ] == simples } </ if > <to - view - id >/ home - simples . xhtml </ to - view - id > </ navigation - case > < navigation - case > < from - outcome > sucesso </ from - outcome > < if > #{ usuarioBean . preferencias [ versao - da - interface ] == avancada } </ if > <to - view - id >/ home - avancada . xhtml </ to - view - id > </ navigation - case > </ navigation - rule >
Cdigo XML 8.3: Registrando uma navegao explcita condicional

Exerccios de Fixao
1 Crie um projeto do tipo Dynamic Web Project chamado K19-Navegacao seguindo os passos vistos nos exerccios de xao do Captulo 5.

Na pasta WebContent do projeto K19-Navegacao, crie trs arquivos XHTML: componentes-visuais.xhtml, templates-e-modularizacao.xhtml e navegacao.xhtml. A partir de qualquer um deles, deve ser possvel navegar para qualquer outro. Podemos criar uma espcie de menu para navegar entre as pginas:
2

...

120

www.k19.com.br

121
2 3 4 5

N AVEGAO
<h : link value = " Componentes Visuais " outcome = " componentes - visuais " / > <h : link value = " Templates e Modularizao " outcome = " templates -e - modularizacao " / > <h : link value = " Navegao " outcome = " navegacao " / > ...
Cdigo XHTML 8.6: Menu para navegar entre as pginas.

Para facilitar, podemos denir um template para criar essas trs pginas. Crie um arquivo chamado template.xhtml no diretrio /WEB-INF/templates/.
3

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " style = " text - align : center " > < h1 > K19 - Desenvolvimento Web com JSF2 e JPA2 </ h1 > </ div > <h : link value = " Componentes Visuais " outcome = " componentes - visuais " / > <h : link value = " Templates e Modularizao " outcome = " templates -e - modularizacao " / > <h : link value = " Navegao " outcome = " navegacao " / > < ui : insert name = " corpo - da - pagina " > Espao para o contedo da tela </ ui : insert > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 1 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 8.7: template.xhtml

Agora, use esse template para criar as pginas componentes-visuais.xhtml, templates-e-modularizacao.xhtml e navegacao.xhtml
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 < ui : composition template = " / WEB - INF / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " corpo - da - pagina " > < h1 > Componentes Visuais </ h1 > No JSF 2 , as telas so definidas em arquivos xhtml . Os componentes visuais que constituem as telas so adicionados por meio de tags . A especificao do JSF define uma grande quantidade de tags e as classifica em bibliotecas . As principais bibliotecas de tags do JSF so : < ul > < li > Core ( http :// java . sun . com / jsf / core ) </ li > < li > HTML ( http :// java . sun . com / jsf / html ) </ li > < li > Facelets ( http :// java . sun . com / jsf / facelets ) </ li > </ ul > </ ui : define > </ ui : composition >
Cdigo XHTML 8.8: componentes-visuais.xhtml

www.k19.com.br

121

N AVEGAO
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 < ui : composition template = " / WEB - INF / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " corpo - da - pagina " > < h1 > Templates e Modularizao </ h1 > A criao de um template simples . Basta criar um arquivo XHTML e definir o posicionamento dos trechos estticos e dinmicos . O contedo dos trechos estticos tambm deve ser definido da forma usual dentro do template . Por outro lado , o contedo dos trechos dinmicos s ser definido nas telas . Para indicar o posicionamento dos trechos dinmicos , devemos utilizar a tag ui : insert . </ ui : define > </ ui : composition >
Cdigo XHTML 8.9: templates-e-modularizacao.xhtml

122

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

< ui : composition template = " / WEB - INF / template . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " corpo - da - pagina " > < h1 > Navegao </ h1 > Navegar entre as telas de uma aplicao web preciso . O mecanismo de navegao do JSF bem sofisticado 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 . </ ui : define > </ ui : composition >
Cdigo XHTML 8.10: navegacao.xhtml

Navegue atravs dos links (ou botes) da url:

http://localhost:8 8 /K19-Navegacao/componentes-visuais.xhtml
5 Suponha que a sequncia dos tpicos seja Componentes Visuais, Templates e Modularizao e Navegao. Queremos adicionar dois botes s pginas: um para avanar para o prximo tpico e outro para voltar para o tpico anterior. Para isso, congure uma navegao explcita no arquivo faces-config.xml.

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

... < navigation - rule > < from - view - id > componentes - visuais . xhtml </ from - view - id > < navigation - case > < from - outcome > proximo </ from - outcome > <to - view - id > templates -e - modularizacao . xhtml </ to - view - id > </ navigation - case > </ navigation - rule > < navigation - rule > < from - view - id > templates -e - modularizacao . xhtml </ from - view - id > < navigation - case > < from - outcome > proximo </ from - outcome > <to - view - id > navegacao . xhtml </ to - view - id > </ navigation - case > < navigation - case > < from - outcome > anterior </ from - outcome > <to - view - id > componentes - visuais . xhtml </ to - view - id >

122

www.k19.com.br

123
22 23 24 25 26 27 28 29 3 31 32 33 </ navigation - case > </ navigation - rule > < navigation - rule > < from - view - id > navegacao . xhtml </ from - view - id > < navigation - case > < from - outcome > anterior </ from - outcome > <to - view - id > templates -e - modularizacao . xhtml </ to - view - id > </ navigation - case > </ navigation - rule > ...
Cdigo XML 8.4: faces-cong.xml

N AVEGAO

No arquivo /WEB-INF/template.xhtml, adicione dois botes. O primeiro deve ser usado para navegar para o tpico anterior (logo, deve emitir o sinal anterior). O segundo boto deve ser usado para navegar para o prximo tpico (portanto, deve emitir o sinal proximo).
6

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " style = " text - align : center " > < h1 > K19 - Desenvolvimento Web com JSF2 e JPA2 </ h1 > </ div > <h : form > <h : commandButton value = " Anterior " action = " anterior " / > <h : commandButton value = " Prximo " action = " proximo " / > </ h : form > <h : link value = " Componentes Visuais " outcome = " componentes - visuais " / > <h : link value = " Templates e Modularizao " outcome = " templates -e - modularizacao " / > <h : link value = " Navegao " outcome = " navegacao " / > < ui : insert name = " corpo - da - pagina " > Espao para o contedo da tela </ ui : insert > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 1 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 8.11: template.xhtml

Navegue atravs dos links e botes da url:

http://localhost:8 8 /K19-Navegacao/componentes-visuais.xhtml

Navegaes Esttica e Dinmica


www.k19.com.br

123

N AVEGAO

124

At agora, utilizamos apenas navegaes estticas, pois os outcomes foram denidos nos botes e links. Dessa forma, toda vez que um boto ou link clicado, ele emite sempre o mesmo outcome. Por exemplo, o boto abaixo sempre emite o outcome k19.
1 <h : commandButton value = " K19 " action = " k19 " / >
Cdigo XHTML 8.12: Boto com navegao esttica

Podemos tornar esse comportamento dinmico, fazendo com que os outcomes sejam diferentes a cada clique. Para isso, os botes e links devem ser associados a mtodos de ao de managed beans atravs de expression language. Veja o exemplo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > K19 Cara ou Coroa </ h1 > <h : form > <h : commandButton value = " Lanar Moeda " action = " #{ caraOuCoroaBean . lanca } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 8.13: cara-ou-coroa.xhtml

1 2 3 4 5 6 7 8 9 1

@ManagedBean public class CaraOuCoroaBean { public String lanca () { if ( Math . random () < .5) { return " cara " ; } else { return " coroa " ; } } }
Cdigo Java 8.1: CaraOuCoroaBean.java

Toda vez que o boto Lanar Moeda for clicado, o mtodo lanca() do managed bean caraOuCoroaBean ser chamado. A string devolvida por esse mtodo ser considerada o outcome a ser utilizado na navegao.

Mais Sobre
Vimos que a pgina de resposta depende tanto da pgina de origem quanto do outcome. No caso da navegao dinmica, a pgina de resposta tambm pode depender do mtodo de ao que produziu o outcome. Para isso, basta acrescentar a tag <from-action> na denio da regra de navegao. Veja o exemplo abaixo.
1 2 3 4 < navigation - rule > < from - view - id >/ index . xhtml </ from - view - id > < navigation - case >

124

www.k19.com.br

125

N AVEGAO

5 6 7 8 9 1 11 12 13 14 15

< from - outcome > lista </ from - outcome > < from - action > #{ cursosBean . lista } </ from - action > <to - view - id >/ lista - cursos . xhtml </ to - view - id > </ navigation - case > < navigation - case > < from - outcome > lista </ from - outcome > < from - action > #{ alunosBean . lista } </ from - action > <to - view - id >/ lista - alunos . xhtml </ to - view - id > </ navigation - case > </ navigation - rule >
Cdigo XML 8.5: faces-cong.xml

1 2 3 4

... <h : commandLink value = " Lista cursos " action = " #{ cursosBean . lista } " / > <h : commandLink value = " Lista alunos " action = " #{ alunosBean . lista } " / > ...
Cdigo XHTML 8.14: index.xhtml

Se o link Lista cursos for clicado, o mtodo lista() do managed bean cursosBean ser acionado. Suponha que esse mtodo devolva lista. De acordo com a regra de navegao denida no faces-config.xml, o usurio ser direcionado pgina denida pelo arquivo /lista-cursos.xhtml. Por outro lado, se o usurio clicar no link Lista alunos, o mtodo lista() do managed bean alunosBean ser invocado. Se esse mtodo devolver lista, o usurio ser direcionado pgina denida pelo arquivo /lista-alunos.xhtml, conforme a regra de navegao denida no faces-config.xml.

Exerccios de Fixao
Implemente um managed bean que, de forma aleatria, escolha entre dois outcomes. Crie um pacote chamado managedbeans no projeto K19-Navegacao e adicione uma classe chamada CaraOuCoroaBean.
8

1 2 3 4 5 6 7 8 9 1

@ManagedBean public class CaraOuCoroaBean { public String proxima () { if ( Math . random () < .5) { return " cara " ; } else { return " coroa " ; } } }
Cdigo Java 8.2: CaraOuCoroaBean.java

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 K19-Navegacao.
9

www.k19.com.br

125

N AVEGAO
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > K19 Cara ou Coroa </ h1 > <h : form > <h : commandButton value = " Lanar Moeda " action = " #{ caraOuCoroaBean . proxima } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 8.15: cara-ou-coroa.xhtml

126

10

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

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > Deu Cara ! </ h1 > <h : form > <h : commandButton value = " voltar " action = " cara - ou - coroa " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 8.16: cara.xhtml

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

11

Navegue atravs dos links e botes da url:


www.k19.com.br

126

127

N AVEGAO

http://localhost:8 8 /Navegacao/cara-ou-coroa.xhtml

Exerccios Complementares
Considere uma aplicao em que o usurio pode escolher entre acessar uma verso simples ou avanada da aplicao. O usurio pode alterar essa preferncia em uma pgina especca da aplicao. Crie uma aplicao web que tenha trs pginas. Uma das pginas deve permitir que o usurio altere suas preferncias. As outras duas devem ser a pgina principal da aplicao, sendo uma para a verso simples e outra para a verso avanada. Cada uma das pginas deve ter um menu para que o usurio possa navegar entre a pgina principal e a pgina de conguraes. O link para a pgina principal deve levar em considerao a preferncia do usurio. Use navegao implcita.
1

Dica: Para armazenar a preferncia do usurio, voc pode usar um managed bean. Anote a classe que implementar esse managed bean com @SessionScoped para que a preferncia do usurio seja mantida entre uma requisio e outra da aplicao.
2

Repita o exerccio anterior usando navegao explcita.

www.k19.com.br

127

N AVEGAO

128

128

www.k19.com.br

CAPTULO
Cdigo Java 9.1: TesteBean.java Cdigo XML 9.1: faces-cong.xml

E SCOPOS

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. Eis alguns dos escopos do JSF 2: Request. View. Session. Application.

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. Assim, os dados no so mantidos de uma requisio para outra. A partir do JSF 2, os managed beans podem ser registrados atravs da anotao @ManagedBean. O JSF utiliza o escopo request como padro quando managed beans so registrados usando essa anotao. Mesmo sendo o padro, podemos deixar explcito a escolha do escopo request atravs da anotao @RequestScoped.
1 2 3 4 5 6 7 package br . com . k19 ; @ManagedBean @RequestScoped class TesteBean { ... }

Por outro lado, se o managed bean for registrado da maneira tradicional, no arquivo faces-config.xml, a escolha de um escopo obrigatria e realizada atravs da tag managed-bean-scope.
1 2 3 4 5 6 7 ... < managed - bean > < managed - bean - name > testeBean </ managed - bean - name > < managed - bean - class > br . com . k19 . TesteBean </ managed - bean - class > < managed - bean - scope > request </ managed - bean - scope > </ managed - bean > ...

www.k19.com.br

129

E SCOPOS

130

Navegador

Aplicao Cria Mata

Requisio HTTP Resposta HTTP

MB MB

JSF

Figura 9.1: Escopo de request

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 br . com . k19 ; @ManagedBean @ViewScoped class TesteBean { ... }

Cdigo Java 9.2: TesteBean.java

1 2 3 4 5 6 7

... < managed - bean > < managed - bean - name > testeBean </ managed - bean - name > < managed - bean - class > br . com . k19 . TesteBean </ managed - bean - class > < managed - bean - scope > view </ managed - bean - scope > </ managed - bean > ...

Cdigo XML 9.2: faces-cong.xml

130

www.k19.com.br

131

E SCOPOS

Navegador
index.xhtml

Aplicao

Requisio HTTP Resposta HTTP


index.xhtml

MB

ia Cr

Requisio HTTP Resposta HTTP


produtos.xhtml

JSF
M
MB

Requisio HTTP Resposta HTTP

a at

Figura 9.2: Escopo de view

Session
Certas informaes devem ser mantidas entre as requisies de um determinado usurio em um determinado navegador. Por exemplo, considere uma aplicao que utiliza carrinho de compras. Um usurio faz diversas requisies para escolher os produtos e coloc-los no seu carrinho. Durante todo esse tempo, a aplicao deve manter a informao de quais produtos j foram escolhidos por esse usurio. Da surge o escopo session. Cada usurio possui um espao na memria do servidor que chamado de session. Tecnicamente, possvel existir duas ou mais sessions de um mesmo usurio, por exemplo, se ele estiver utilizando dois ou mais 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, quando o usurio faz logout) ou o servidor decide apagar a session de um usurio quando esse usurio no faz requisies por um determinado perodo de tempo. Esse tempo pode ser congurado com o Web Container. Para escolher o escopo session, devemos utilizar a anotao @SessionScoped ou a tag mana-

ged-bean-scope.
1 2 3 4 5 package br . com . k19 ; @ManagedBean @SessionScoped class TesteBean {

www.k19.com.br

131

E SCOPOS
6 7 ... }
Cdigo Java 9.3: TesteBean.java

132

1 2 3 4 5 6 7

... < managed - bean > < managed - bean - name > testeBean </ managed - bean - name > < managed - bean - class > br . com . k19 . TesteBean </ managed - bean - class > < managed - bean - scope > session </ managed - bean - scope > </ managed - bean > ...
Cdigo XML 9.3: faces-cong.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 request mais apropriado.
Navegador
index.xhtml

Aplicao

Requisio HTTP Resposta HTTP


produtos.xhtml

MB

a Cri

Requisio HTTP Resposta HTTP


usuario.xhtml

Requisio HTTP Resposta HTTP

JSF

30 minutos depois

MB

Figura 9.3: Escopo de session

132

at a

www.k19.com.br

133

E SCOPOS

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. Ao contrrio do que ocorre com escopos discutidos anteriormente, as instncias dos managed beans registrados com escopo application so compartilhadas por todos os usurios da aplicao. O JSF cria apenas uma instncia de cada managed bean em escopo de application. 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 br . com . k19 ; @ManagedBean @ApplicationScoped class TesteBean { ... }
Cdigo Java 9.4: TesteBean.java

1 2 3 4 5 6 7

... < managed - bean > < managed - bean - name > testeBean </ managed - bean - name > < managed - bean - class > br . com . k19 . TesteBean </ managed - bean - class > < managed - bean - scope > application </ managed - bean - scope > </ managed - bean > ...
Cdigo XML 9.4: faces-cong.xml

Mais Sobre
Por padro, a instncia de um managed bean em escopo application criada no momento em que ela usada pela primeira vez. Podemos alterar esse comportamento, fazendo com que essa instncia seja criada quando a aplicao inicializada. Para isso, basta acrescentar a propriedade eager com o valor true na anotao @ManagedBean. Veja o exemplo abaixo.
1 2 3 4 5 6 7 package br . com . k19 ; @ManagedBean ( eager = true ) @ApplicationScoped class TesteBean { ... }
Cdigo Java 9.5: TesteBean.java

Exerccios de Fixao
www.k19.com.br

133

E SCOPOS

134

Crie um projeto do tipo Dynamic Web Project chamado K19-Escopos seguindo os passos vistos no exerccio do Captulo 5.
1

Vamos criar uma pgina para adicionar carros e visualiz-los. Na pasta src, faa um pacote chamado model.
2

No pacote model, crie uma classe chamada Carro para modelar os carros. Essa classe deve ter dois atributos do tipo String: um para armazenar a marca e outro para guardar o modelo do carro.
3

1 2 3 4 5 6 7 8

package model ; public class Carro { private String marca ; private String modelo ; // GETTERS E SETTERS }
Cdigo Java 9.6: Carro.java

Na pasta src, faa um pacote chamado managedbeans.

5 No pacote managedbeans, crie uma classe chamada CarrosBean para armazenar uma lista de carros.

1 2 3 4 5 6 7 8

package managedbeans ; @ManagedBean public class CarrosBean { private List < Carro > carros = new ArrayList < Carro >() ; // GETTER E SETTER }
Cdigo Java 9.7: CarrosBean.java

Na classe CarrosBean, acrescente um atributo do tipo Carro para armazenar o carro a ser adicionado. Implemente tambm um mtodo chamado adicionaCarro() para inserir um novo carro na lista.
6

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

package managedbeans ; @ManagedBean public class CarrosBean { private List < Carro > carros = new ArrayList < Carro >() ; private Carro carro = new Carro () ; public void adicionaCarro () { this . carros . add ( this . carro ) ; this . carro = new Carro () ; } // GETTERS E SETTERS }
Cdigo Java 9.8: CarrosBean.java

134

www.k19.com.br

135
7

E SCOPOS

Dena o escopo do managed bean carrosBean como sendo request. Para isso, use a anotao @RequestScoped.
1 2 3 4 5 6 7 package managedbeans ; @ManagedBean @RequestScoped public class CarrosBean { ... }
Cdigo Java 9.9: CarrosBean.java

8 No diretrio WebContent, crie um arquivo XHTML chamado carros.xhtml. Implemente um formulrio para adicionar um novo carro.

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Marca : " for = " campo - marca " / > <h : inputText value = " #{ carrosBean . carro . marca } " id = " campo - marca " / > <h : outputLabel value = " Modelo : " for = " campo - modelo " / > <h : inputText value = " #{ carrosBean . carro . modelo } " id = " campo - modelo " / > <h : commandButton value = " Adicionar " action = " #{ carrosBean . adicionaCarro } " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML 9.1: carro.xhtml

No arquivo carros.xhtml, adicione um trecho de cdigo para exibir os carros adicionados.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Marca : " for = " campo - marca " / > <h : inputText value = " #{ carrosBean . carro . marca } " id = " campo - marca " / > <h : outputLabel value = " Modelo : " for = " campo - modelo " / > <h : inputText value = " #{ carrosBean . carro . modelo } " id = " campo - modelo " / >

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

www.k19.com.br

135

E SCOPOS
21 22 23 24 25 26 27 28 29 3 31 32 33 34 <h : commandButton value = " Adicionar " action = " #{ carrosBean . adicionaCarro } " / > </ h : panelGrid > </ h : form > <h : panelGroup rendered = " #{ not empty carrosBean . carros } " > < h1 > Lista de carros : </ h1 > < ul > < ui : repeat value = " #{ carrosBean . carros } " var = " carro " > < li > <h : outputText value = " #{ carro . marca } #{ carro . modelo } " / > </ li > </ ui : repeat > </ ul > </ h : panelGroup > </ h : body > </ html >
Cdigo XHTML 9.2: carros.xhtml

136

10

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Escopos/carros.xhtml
Adicione alguns carros e observe a lista de carros. O que acontece? Mude o escopo do managed bean carrosBean de request para view. Para isso, use a anotao @ViewScoped.
11

1 2 3 4 5 6 7

package managedbeans ; @ManagedBean @ViewScoped public class CarrosBean { ... }


Cdigo Java 9.10: CarrosBean.java

12

Novamente, acesse a aplicao no endereo:

http://localhost:8 8 /K19-Escopos/carros.xhtml
Adicione alguns carros e observe a lista de carros. O que acontece? No diretrio WebContent, crie um arquivo chamado menu.xhtml. Esse arquivo deve denir uma pgina que possua um link para a pgina denida por carros.xhtml.
13

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > <h : link value = " Adicionar carros " outcome = " carros " / > </ h : body > </ html >
Cdigo XHTML 9.3: menu.xhtml

14

No arquivo carros.xhtml, adicione um link para a pgina denida por menu.xhtml.


www.k19.com.br

136

137
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : link value = " Menu " outcome = " menu " / > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Marca : " for = " campo - marca " / > <h : inputText value = " #{ carrosBean . carro . marca } " id = " campo - marca " / > <h : outputLabel value = " Modelo : " for = " campo - modelo " / > <h : inputText value = " #{ carrosBean . carro . modelo } " id = " campo - modelo " / > <h : commandButton value = " Adicionar " action = " #{ carrosBean . adicionaCarro } " / > </ h : panelGrid > </ h : form > <h : panelGroup rendered = " #{ not empty carrosBean . carros } " > < h1 > Lista de carros : </ h1 > < ul > < ui : repeat value = " #{ carrosBean . carros } " var = " carro " > < li > <h : outputText value = " #{ carro . marca } #{ carro . modelo } " / > </ li > </ ui : repeat > </ ul > </ h : panelGroup > </ h : body > </ html >
Cdigo XHTML 9.4: carros.xhtml

E SCOPOS

15

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Escopos/carros.xhtml
Certique-se de que o escopo do managed bean carrosBean seja view. Mais uma vez, adicione alguns carros e observe a lista de carros. Use os links criados para navegar entre as pginas denidas por carros.xhtml e menu.xhtml. O que acontece? Mude o escopo do managed bean carrosBean de view para session. Para isso, use a anotao @SessionScoped.
16

1 2 3 4 5 6 7

package managedbeans ; @ManagedBean @SessionScoped public class CarrosBean { ... }


Cdigo Java 9.11: CarrosBean.java

17

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Escopos/carros.xhtml
www.k19.com.br

137

E SCOPOS

138

Novamente, adicione alguns carros e observe a lista de carros. Use os links que voc criou para navegar entre as pginas denidas por carros.xhtml e menu.xhtml. O que acontece? Agora, acesse a aplicao a partir de navegadores diferentes. Adicione alguns carros a partir dos diferentes navegadores. O que voc observa?
18

Mude o escopo do managed bean carrosBean de session para application. Para isso, use a anotao @ApplicationScoped.
19

1 2 3 4 5 6 7

package managedbeans ; @ManagedBean @ApplicationScoped public class CarrosBean { ... }


Cdigo Java 9.12: CarrosBean.java

20

Novamente, usando navegadores diferentes, adicione alguns carros. O que voc pode observar?

138

www.k19.com.br

CAPTULO

C ONVERSO E VALIDAO

10

Converso
Quando um usurio preenche um formulrio, os valores preenchidos 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, considere 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 so enviados para a aplicao 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 aos usurios. Novamente, os dados devem ser convertidos antes de serem enviados para os navegadores. Felizmente, o JSF oferece um mecanismo automatizado de converso de dados. Veremos a seguir o funcionamento desse mecanismo.

Conversores Padro
Para facilitar o trabalho de desenvolvimento de uma aplicao, o JSF dene um conjunto de conversores padro. Alguns desses conversores so aplicados automaticamente. Outros conversores so aplicados apenas se forem explicitamente indicados. O JSF aplica automaticamente conversores padro para os seguintes tipos fundamentais do Java: BigDecimal BigInteger Boolean e boolean Byte e byte Character e char Double e double
www.k19.com.br

139

C ONVERSO E VALIDAO

140

Float e oat Integer e int Long e long Short e short No exemplo abaixo, o contedo digitado na caixa de texto ser convertido para o tipo double automaticamente, pois a propriedade numero do tipo double.
1 2 3 4 5 6 7 @ManagedBean public class TesteBean { private double numero ; // GETTERS E SETTERS }
Cdigo Java 10.1: TesteBean.java

1 2

<! -- O valor digitado nesse campo ser convertido para double -- > <h : inputText value = " #{ testeBean . numero } " / >
Cdigo XHTML 10.1: Caixa de texto vinculada propriedade numero

Personalizando Conversores Padro


Alguns conversores padro podem ou precisam usar informaes adicionais para realizar a converso de dados. As tags <f:convertNumber> e <f:convertDateTime> so usadas para transmitir informaes aos conversores de nmeros (java.lang.Number) e datas (java.util.Date e java.sql.Date), respectivamente.

<f:convertNumber> A tag <f:convertNumber> permite que converses mais sosticadas sejam feitas em valores numricos. Para estipular que um valor numrico seja exibido com um nmero mximo de casas decimais, podemos usar o atributo maxFractionDigits da tag <f:convertNumber>. No exemplo abaixo, a propriedade numero do managed bean testeBean exibida com no mximo duas casas decimais.
1 2 3 <h : outputText value = " #{ testeBean . numero } " > <f : convertNumber maxFractionDigits = " 2 " / > </ h : outputText >

Analogamente, podemos denir o nmero mnimo de casas decimais com o atributo minFractionDigits. Podemos tambm denir a formatao de um nmero por meio de uma espcie de expresso regular. Isso pode ser feito usando o atributo pattern, como no exemplo abaixo.
1 2 <h : outputText value = " #{ testeBean . numero } " > <f : convertNumber pattern = " # . " />

140

www.k19.com.br

141
3 </ h : outputText >

C ONVERSO E VALIDAO

Para apresentar dados na forma de porcentagem, podemos usar o atributo type e deni-lo com o valor percent.
1 2 3 <h : outputText value = " #{ testeBean . numero } " > <f : convertNumber type = " percent " / > </ h : outputText >

Para personalizar a exibio de valores monetrios, a tag <f:convertNumber> prov o atributo currencySymbol e locale. No cdigo abaixo, exemplicamos o uso desses dois atributos.
1 2 3 4 5 6 7 <h : outputText value = " #{ testeBean . numero } " > <f : convertNumber currencySymbol = " R$ " type = " currency " / > </ h : outputText > <h : outputText value = " #{ testeBean . numero } " > <f : convertNumber locale = " pt_BR " 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 e java.sql.Date. Essa tag possui o atributo pattern, que permite a denio do formato da data que desejamos utilizar.
1 2 3 <h : outputText value = " #{ testeBean . data } " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : outputText >

Para mais detalhes sobre o uso do atributo pattern, consulte a pgina http://docs.oracle. com/javase/7/docs/api/java/text/SimpleDateFormat.html. Uma outra maneira de escolher o formato de data a ser utilizado por meio do atributo locale. No exemplo abaixo, ao denir o valor do atributo locale como pt_BR, o padro de data utilizado ser dd/MM/yyyy.
1 2 3 <h : outputText value = " #{ testeBean . data } " > <f : convertDateTime locale = " pt_BR " / > </ h : outputText >

Exerccios de Fixao
1 Crie um projeto do tipo Dynamic Web Project chamado K19-Conversao-e-Validacao seguindo os passos vistos no exerccio do Captulo 5. 2 3

No diretrio src, crie um pacote chamado model. Crie uma classe chamada Funcionario para modelar funcionrios e adicione-a ao pacote model.

www.k19.com.br

141

C ONVERSO E VALIDAO
1 2 3 4 5 6 7 8 9 package model ; public class Funcionario { private Double salario ; private Integer codigo ; private Date aniversario ; // GETTERS E SETTERS }
Cdigo Java 10.2: Funcionario.java

142

Acrescente um pacote na pasta src chamado managedbeans e adicione a seguinte classe a esse pacote:
4

1 2 3 4 5 6 7 8

package managedbeans ; @ManagedBean public class FuncionarioBean { private Funcionario funcionario = new Funcionario () ; // GETTER E SETTER }
Cdigo Java 10.3: FuncionarioBean.java

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

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ 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 . funcionario . salario } " > <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 . funcionario . codigo } " / > <h : message for = " campo - codigo " / > <h : outputLabel value = " Data : ( dd / MM / yyyy ) " for = " campo - aniversario " / > <h : inputText id = " campo - aniversario " value = " #{ funcionarioBean . funcionario . 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 >

142

www.k19.com.br

143
37 </ html >
Cdigo XHTML 10.8: cadastro.xhtml

C ONVERSO E VALIDAO

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/cadastro.xhtml
Preencha o formulrio com valores inadequados diversas vezes e observe as mensagens de erros.

Exerccios Complementares
Crie um formulrio para registrar a cotao do dlar. Esse formulrio deve ter trs campos obrigatrios. No primeiro, o usurio deve digitar o valor do dlar em reais. Esse campo deve estar associado a um conversor de nmeros cujo tipo seja a moeda brasileira (use os atributos locale e type da tag <f:convertNumber>). O segundo campo deve guardar a variao do dlar, em porcentagem, com no mximo cinco dgitos na parte fracionria. No terceiro campo, o usurio deve colocar o horrio e a data da cotao, cujo formato deve ser HH:mm dd-MM-yyyy.
1 2

Exiba na tela os valores que foram submetidos pelo formulrio e convertidos.

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

<h:message>
Para exibir erros relacionados a um determinado campo, podemos utilizar o componente <h:message>. Esse componente deve ser associado ao campo correspondente aos erros que desejamos exibir. Para estabelecer essa ligao, devemos denir o valor do atributo for do componente <h:message> igual ao valor do atributo id do campo em questo.
1 2 3 4 5 6 7 @ManagedBean public class TesteBean { private Double numero ; // GETTERS E SETTERS }
Cdigo Java 10.6: TesteBean.java

1 2

<h : inputText value = " #{ testeBean . numero } " id = " campo - numero " / > <h : message for = " campo - numero " / >
Cdigo XHTML 10.11: Exibindo mensagens de erro relacionadas a um campo de texto

www.k19.com.br

143

C ONVERSO E VALIDAO

144

As imagens abaixo exibem o campo de texto com o valor digitado pelo usurio e aps o processamento da requisio.
K19 Treinamentos Enviar

Figura 10.1: Campo de texto associado a uma propriedade numrica de um managed bean

K19 Treinamentos

form:campo-numero: K19 Treinamentos must be a number between 4.9E-324 and 1.7976931348623157E308 Example: 1999999
Enviar

Figura 10.2: Mensagem de erro de converso

Mais Sobre
Os textos padro das mensagens de erro so denidos no resource bundle javax.faces.Messages.

Mais Sobre
Cada mensagem de erro possui duas verses: uma detalhada e outra resumida. Por padro, apenas a mensagem detalhada exibida quando a tag <h:message> aplicada. Para modicar esse comportamento, podemos alterar os valores dos atributos showSummary e showDetail. O primeiro atributo indica se a mensagem resumida deve ser apresentada, enquanto o segundo indica se a mensagem detalhada deve ser exibida. Esses atributos devem assumir valores true ou false. Veja o exemplo abaixo.
1 2 <h : inputText value = " #{ testeBean . numero } " id = " campo - numero " / > <h : message for = " campo - numero " showSummary = " true " showDetail = " false " / >
Cdigo XHTML 10.12: Denindo o tipo de mensagem de erro a ser apresentada

Note que as mensagens detalhada e resumida podem ser exibidas ao mesmo tempo. Para isso, basta que esses dois atributos possuam o valor true.

<h:messages>
Como vimos, a tag <h:message> permite que os erros relacionados a um determinado campo sejam exibidos. Para exibir os erros de todos os campos, podemos incluir uma tag <h:message> para cada campo. Entretanto, podemos fazer o mesmo de uma forma mais prtica. A tag <h:messages> exibe todas as mensagens.
1 <h : messages / >
Cdigo XHTML 10.13: Exibindo todas as mensagens

144

www.k19.com.br

145

C ONVERSO E VALIDAO

Ao contrrio da tag <h:message>, os valores padro dos atributos showSummary e showDetail da tag <h:messages> so true e false, respectivamente.

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. Normalmente, queremos personalizar essas mensagens. Para isso, so necessrios dois passos:

1. Criar um arquivo de mensagens. 2. Registrar esse arquivo no faces-config.xml.

Criando um Arquivo de Mensagens Um arquivo de mensagens um conjunto de chaves e valores. As chaves so utilizadas para recuperar as mensagens, enquanto os valores denem os textos que sero exibidos. 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} : { } must be true or false .
Cdigo XML 10.1: Exemplo de arquivo de mensagens

Os nomes dos arquivos de mensagens devem possuir o suxo .properties.

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

Note que o suxo .properties omitido no faces-config.xml.

Mais Sobre
Suponha que uma aplicao tenha um arquivo de mensagens registrado no

www.k19.com.br

145

C ONVERSO E VALIDAO

146

faces-config.xml. Para obter uma mensagem de erro, o JSF buscar primeiramente nesse arquivo. Caso no a encontre, ele utilizar a mensagem padro.

Mais Sobre
Podemos denir, de maneira especca, a mensagem que deve ser utilizada quando um erro de converso ocorrer em um determinado campo. Para isso, basta utilizar o atributo converterMessage. Observe o seguinte exemplo.
1 2 3 <h : inputText value = " #{ testeBean . numero } " id = " campo - numero " converterMessage = " Por favor , digite um nmero " / > <h : message for = " campo - numero " / >
Cdigo XHTML 10.14: Denindo uma mensagem para um erro de converso

No exemplo acima, se o usurio submeter o formulrio com um valor no numrico no campo campo-numero, ento a mensagem de erro Por favor, digite um nmero ser exibida na tela de resposta.

Exerccios de Fixao
No projeto K19-Conversao-e-Validacao, faa um pacote chamado resources na pasta src. Adicione a esse pacote um arquivo de mensagens chamado Messages.properties com o seguinte contedo.
7

1 2 3 4 5 6

javax . faces . converter . NumberConverter . NUMBER = O valor { } no adequado . javax . faces . converter . NumberConverter . NUMBER_detail ={ } no nmero ou inadequado . javax . faces . converter . IntegerConverter . INTEGER = O valor { } no adequado . javax . faces . converter . IntegerConverter . INTEGER_detail ={ } no um nmero inteiro . javax . faces . converter . DateTimeConverter . DATE = A data { } no est correta . javax . faces . converter . DateTimeConverter . DATE_detail = { } no parece uma data .
Cdigo XML 10.3: Messages.properties

Adicione a congurao necessria no faces-config.xml para utilizar o arquivo de mensagens criado no exerccio anterior.
8

1 2 3 4 5

... < application > < message - bundle > resources . Messages </ message - bundle > </ application > ...
Cdigo XML 10.4: faces-cong.xml

Observao: a tag <application> deve ser colocada dentro de da tag <faces-config>.


9

Preencha o formulrio vrias vezes com valores inadequados e observe as novas mensagens.

Validao
146
www.k19.com.br

147

C ONVERSO E VALIDAO

Como vimos, um dado enviado atravs de uma requisio HTTP chega na aplicao no formato de texto. O processo de converso consiste em transformar esse texto em algum tipo especco do Java. Aps a converso, podemos vericar se os valores obtidos respeitam determinadas restries impostas pelas regras da aplicao. Por exemplo, considere um campo para o usurio digitar sua idade. Como discutido anteriormente, o valor digitado ser tratado como texto at chegar na aplicao. Em seguida, esse dado ser convertido para um tipo numrico do Java (como int ou long por exemplo). Obviamente, a idade de um usurio deve ser um valor no-negativo. Contudo, essa condio no vericada na etapa de converso. Dessa forma, depois da converso dos dados, mais uma etapa necessria para que essa vericao seja realizada. Essa etapa conhecida como validao.

Validadores Padro
Novamente, para facilitar o trabalho de desenvolvimento de uma aplicao, o JSF dene um conjunto de validadores padro. A seguir, veremos alguns detalhes sobre esses validadores.

Campo Obrigatrio (Required)


A validao mais comum de todas a de vericar se um determinado campo foi preenchido. Podemos aplicar essa validao utilizando o atributo required.
1 2 <h : inputText value = " #{ testeBean . nome } " id = " campo - nome " required = " true " / > <h : message for = " campo - nome " / >
Cdigo XHTML 10.15: Campo de texto obrigatrio

Uma outra forma de registrar um validador desse tipo por meio da tag <f:validateRequired>, conforme o exemplo abaixo.
1 2 3 4 <h : inputText value = " #{ testeBean . nome } " id = " campo - nome " > <f : validateRequired / > </ h : inputText > <h : message for = " campo - nome " / >
Cdigo XHTML 10.16: Outra forma de exigir que um campo seja obrigatrio

<f:validateLongRange>
O validador <f:validateLongRange> utilizado para vericar se um valor numrico inteiro pertence a um determinado intervalo de nmeros. No exemplo abaixo, o validador ir vericar se o valor da propriedade idade est entre 10 e 130.
1 2 3 4 <h : inputText value = " #{ testeBean . idade } " id = " campo - idade " > <f : validateLongRange minimum = " 1 " maximum = " 13 " / > </ h : inputText > <h : message for = " campo - idade " / >

www.k19.com.br

147

C ONVERSO E VALIDAO

148

Cdigo XHTML 10.17: A propriedade idade deve receber um nmero entre 10 e 130

<f:validateDoubleRange>
O validador <f:validateDoubleRange> funciona de forma anloga ao <f:validateLongRange>. Ele utilizado para vericar se um valor numrico real pertence a um determinado intervalo de nmeros. No exemplo abaixo, o validador vericar se o valor da propriedade preco do managed bean testeBean est entre 20.57 e 200.56.
1 2 3 4 <h : inputText value = " #{ testeBean . preco } " id = " campo - preco " > <f : validateDoubleRange minimum = " 2 .57 " maximum = " 2 .56 " / > </ h : inputText > <h : message for = " campo - preco " / >
Cdigo XHTML 10.18: A propriedade preco deve receber um nmero entre 20.57 e 200.56

<f:validateLength>
O validador <f:validateLength> verica se uma string possui uma quantidade mnima ou mxima de caracteres. Veja o exemplo abaixo.
1 2 3 4 <h : inputText value = " #{ testeBean . nome } " id = " campo - nome " > <f : validateLength minimum = " 6 " maximum = " 2 " / > </ h : inputText > <h : message for = " campo - nome " / >
Cdigo XHTML 10.19: Restrio no nmero de caracteres da propriedade nome

Nesse exemplo, a restrio imposta a de que a propriedade nome do managed bean testeBean seja uma string com pelo menos 6 e no mximo 20 caracteres.

<f:validateRegex>
O validador <f:validateRegex> usado para vericar se um texto respeita uma determinada expresso regular. No exemplo abaixo, o validador vericar se a propriedade codigo tem pelo menos 6 e no mximo 20 caracteres, alm de ser formada apenas por letras.
1 2 3 4 <h : inputText value = " #{ testeBean . codigo } " id = " campo - codigo " > <f : validateRegex pattern = " [a - zA - Z ]{6 ,2 } " / > </ h : inputText > <h : message for = " campo - codigo " / >
Cdigo XHTML 10.20: Expresso regular para restringir o dado de entrada de um campo de texto

Exerccios de Fixao
148
www.k19.com.br

149

C ONVERSO E VALIDAO

Vamos acrescentar alguns validadores para os campos do formulrio de cadastro de funcionrios do projeto K19-Conversao-e-Validacao. Com base nas restries abaixo, acrescente validadores apropriados.
10

O salrio de um funcionrio deve ser no-negativo. O cdigo de um funcionrio deve ser um nmero inteiro maior ou igual a 5 e estritamente menor do que 20. Todos os campos so obrigatrios.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ 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 . funcionario . salario } " required = " true " > <f : convertNumber locale = " pt_BR " / > <f : validateDoubleRange minimum = " " / > </ h : inputText > <h : message for = " campo - salario " / > <h : outputLabel value = " Cdigo : " for = " campo - codigo " / > <h : inputText id = " campo - codigo " value = " #{ funcionarioBean . funcionario . codigo } " required = " true " > <f : validateLongRange minimum = " 5 " maximum = " 19 " / > </ h : inputText > <h : message for = " campo - codigo " / > <h : outputLabel value = " Data : ( dd / MM / yyyy ) " for = " campo - aniversario " / > <h : inputText id = " campo - aniversario " value = " #{ funcionarioBean . funcionario . aniversario } " required = " true " > <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 >
Cdigo XHTML 10.21: cadastro.xhtml

11

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/cadastro.xhtml
Teste o formulrio com diversos valores e observe o que acontece.
www.k19.com.br

149

C ONVERSO E VALIDAO

150

Exerccios Complementares
Crie um formulrio para o cadastro de produtos. Um produto tem quatro atributos: nome, cdigo, tamanho e volume. O nome deve ser formado apenas por letras e espaos. O cdigo deve ter pelo menos quatro e no mximo dez caracteres. O primeiro caractere desse cdigo deve ser uma letra maiscula e os demais devem ser nmeros. O tamanho deve ser um nmero inteiro entre 1 e 32. O volume deve ser um nmero real maior ou igual a 0.1. Todos os campos do formulrio devem ser obrigatrios.
3

Bean Validation
Uma nova abordagem para denir validaes foi adicionada no JSF 2. A ideia declarar as regras de validao nas classes do modelo ao invs de inseri-las nos arquivos XHTML que denem as telas. A grande vantagem das validaes denidas nas classes do 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=3 3. Para denir as validaes com bean validation, basta adicionar anotaes nas classes do modelo. No cdigo abaixo, o atributo nome foi marcado com a anotao @NotNull. Com essa anotao, o JSF vericar se o valor do atributo nome no nulo.
1 2 3 4 5 public class Funcionario { @NotNull private String nome ; ... }
Cdigo Java 10.9: Funcionario.java

Mais Sobre
Considere uma caixa de texto vinculada a uma propriedade do tipo String. Por padro, quando essa caixa no preenchida, o JSF considera o seu contedo como sendo a string vazia () e no como o valor null. Assim, a anotao @NotNull no pode ser utilizada para obrigar que o usurio preencha essa caixa de texto. Podemos alterar o comportamento padro do JSF fazendo com que ele considere o contedo de uma caixa de texto no preenchida como null. Para isso, devemos acrescentar o seguinte trecho no arquivo de congurao da aplicao web (web.xml).
1 2 3 4 5 6 7 8 ... < context - param > < param - name > javax . faces . INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL </ param - name > < param - value > true </ param - value > </ context - param > ...
Cdigo XML 10.5: web.xml

150

www.k19.com.br

151

C ONVERSO E VALIDAO

Veja abaixo as anotaes disponveis e suas respectivas funes. @AssertFalse Verica se uma propriedade booleana possui valor false. @AssertTrue Verica se uma propriedade booleana possui valor true. @DecimalMax Dene o valor real mximo que uma propriedade pode armazenar. @DecimalMin Dene o valor real mnimo que uma propriedade pode assumir. @Digits Dene a quantidade mxima de dgitos da parte inteira (atravs do atributo integer) ou da parte fracionria (atravs do atributo fraction) de um nmero. @Future Verica se uma data posterior ao instante atual. @Max Dene o valor inteiro mximo que uma propriedade pode assumir. @Min Dene o valor inteiro mnimo que uma propriedade pode armazenar. @NotNull Verica se o valor de uma propriedade no null. @Null Verica se o valor de uma propriedade null. @Past Verica se uma data anterior ao instante atual. @Pattern Verica se o valor de uma propriedade respeita uma expresso regular. @Size Dene os tamanhos mnimo (atravs do atributo min) e mximo (atravs do atributo max) para uma Collection, array ou String. As validaes denidas atravs das anotaes da especicao bean validation so aplicadas automaticamente pelo JSF. As mensagens de erro referentes a essas validaes so automaticamente acrescentadas no contexto do processamento da requisio correspondente.

Mais Sobre
Para desabilitar bean validations em um componente particular de um formulrio, podemos usar a tag <f:validateBean>. Isso pode ser feito atribuindo o valor true ao atributo disabled dessa tag. Considere o seguinte managed bean.
1 2 3 4 5 6 public class FuncionarioBean { private Funcionario funcionario = new Funcionario () ; // GETTER E SETTER }

www.k19.com.br

151

C ONVERSO E VALIDAO

152

Cdigo Java 10.10: FuncionarioBean.java

No exemplo abaixo, a validao introduzida pela anotao @NotNull do atributo nome da classe

Funcionario desabilitada.
1 2 3 <h : inputText value = " #{ funcionarioBean . funcionario . nome } " > <f : validateBean disabled = " true " / > </ h : inputText >
Cdigo XHTML 10.23: Desabilitando validaes introduzidas por anotaes

Personalizando as mensagens de erro Podemos personalizar as mensagens de erro atravs do atributo message das anotaes do bean validation. Veja o seguinte cdigo.
1 2 3 4 5 public class Funcionario { @NotNull ( message = " O nome no pode ser nulo " ) private String nome ; ... }
Cdigo Java 10.11: Funcionario.java

No exemplo acima, a mensagem de erro de validao est denida de maneira xa. Pode ser mais apropriado deni-la em um arquivo de mensagens. Nesse caso, devemos criar um arquivo chamado ValidationMessages.properties no classpath da aplicao. No exemplo abaixo, a mensagem O nome do funcionrio no pode ser nulo est associada chave br.com.k19.Funcionario.nome.
1 br . com . k19 . Funcionario . nome = O nome do funcionrio no pode ser nulo
Arquivo de Propriedades 10.1: ValidationMessages.properties

Finalmente, devemos denir o valor do atributo message com a chave associada mensagem que desejamos exibir. O identicador da mensagem deve estar entre chaves, como mostrado a seguir.
1 2 3 4 5 public class Funcionario { @NotNull ( message = " { br . com . k19 . Funcionario . nome } " ) private String nome ; ... }
Cdigo Java 10.12: Funcionario.java

A mensagem O nome do funcionrio no pode ser nulo especca para o caso acima. Agora, suponha que desejamos criar uma mensagem comum associada ao validador @NotNull. Como o valor padro da propriedade message desse validador "{javax.validation.constraints.NotNull.message}", basta denir uma mensagem com essa chave no arquivo ValidationMessages.properties.
1 javax . validation . constraints . NotNull . message = O valor no pode ser nulo

152

www.k19.com.br

153

C ONVERSO E VALIDAO

Arquivo de Propriedades 10.2: ValidationMessages.properties

Podemos tambm alterar as mensagens dos demais validadores do bean validation. As chaves das mensagens associadas a esses validadores so listadas abaixo: @AssertFalse: "{javax.validation.constraints.AssertFalse.message}" @AssertTrue: "{javax.validation.constraints.AssertTrue.message}" @DecimalMax: "{javax.validation.constraints.DecimalMax.message}" @DecimalMin: "{javax.validation.constraints.DecimalMin.message}" @Digits: "{javax.validation.constraints.Digits.message}" @Future: "{javax.validation.constraints.Future.message}" @Max: "{javax.validation.constraints.Max.message}" @Min: "{javax.validation.constraints.Min.message}" @Null: "{javax.validation.constraints.Null.message}" @Past: "{javax.validation.constraints.Past.message}" @Pattern: "{javax.validation.constraints.Pattern.message}" @Size: "{javax.validation.constraints.Size.message}"

Exerccios de Fixao
12

Remova os validadores do arquivo cadastro.xhtml que voc adicionou no exerccio anterior.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ 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 . funcionario . salario } " > <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 . funcionario . codigo } " / > <h : message for = " campo - codigo " / > <h : outputLabel value = " Data : ( dd / MM / yyyy ) " for = " campo - aniversario " / > <h : inputText id = " campo - aniversario " value = " #{ funcionarioBean . funcionario . aniversario } " / > <h : message for = " campo - aniversario " / > <h : commandButton value = " Cadastrar " / >

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

www.k19.com.br

153

C ONVERSO E VALIDAO
31 32 33 34 35 </ h : panelGrid > <h : messages / > </ h : form > </ h : body > </ html >
Cdigo XHTML 10.24: cadastro.xhtml

154

13 Usando bean validation, modique a classe Funcionario para considerar as restries do exerccio anterior, isto :

O salrio de um funcionrio deve ser no-negativo. O cdigo de um funcionrio deve ser um nmero inteiro maior ou igual a 5 e estritamente menor do que 20. Todos os campos so obrigatrios.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 package model ; public class Funcionario { @NotNull @Min ( value = ) private Double salario ; @NotNull @Min ( value = 5) @Max ( value = 19) private Integer codigo ; @NotNull private Date aniversario ; // GETTERS E SETTERS }
Cdigo Java 10.13: Funcionario.java

14

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/cadastro.xhtml
Teste o formulrio com diversos valores e observe o que acontece.

Criando o seu Prprio Conversor


Se os conversores padro no forem sucientes para atender as necessidades de uma aplicao, podemos criar os nossos prprios conversores. Considere uma aplicao que armazena nmeros de telefones internacionais. Esses nmeros sero modelados pela seguinte classe.
1 2 3 4 5 6 7 public class Telefone { private String codigoDoPais ; private String codigoDeArea ; private String numeroLocal ; // GETTERS E SETTERS }
Cdigo Java 10.14: Telefone.java

154

www.k19.com.br

155

C ONVERSO E VALIDAO

Um nmero de telefone divido em trs partes: o cdigo do pas, o cdigo da rea e o nmero local. A interface da nossa aplicao utilizar o seguinte formato para apresentar ou receber nmeros de telefone:

CodigoDoPais

CodigoDeArea

NumeroLocal

As trs partes so separadas por espaos. Tanto o cdigo do pas quanto o cdigo de rea so formados apenas por dgitos. O nmero local, por outro lado, formado por dgitos e, opcionalmente, por hifens. No exemplo abaixo, o nmero de telefone da K19 mostrado nesse formato. Veja abaixo alguns exemplos de como o nmero de telefone da K19 poderia ser apresentado seguindo esse formato. 55 11 2387-3791 55 11 23873791 55 11 23-87-37-91 Para automatizar o processo de transformao das strings digitadas pelos usurios em objetos da classe Telefone e vice-e-versa, podemos implementar um conversor JSF. O primeiro passo para implementar um conversor JSF criar uma classe que implementa a interface javax.faces.convert.Converter. Nessa classe, devemos adicionar a anotao @FacesConverter para indicar a classe associada a esse conversor, como no cdigo abaixo.
1 2 3 4 @FacesConverter ( forClass = Telefone . class ) public class ConversorDeTelefone implements Converter { ... }
Cdigo Java 10.15: ConversorDeTelefone.java

A interface Converter exige a implementao de dois mtodos: getAsObject() e getAsString(). O primeiro mtodo deve transformar um objeto do tipo String em um objeto Java (em nosso caso, um objeto do tipo Telefone). J o mtodo getAsString() deve converter um objeto Java em um objeto do tipo String (em nosso caso, criar uma String a partir de um Telefone). Uma possvel implementao para o conversor de nmeros de telefone apresentada a seguir.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 package br . com . k19 ; @FacesConverter ( forClass = Telefone . class ) public class ConversorDeTelefone implements Converter { @Override public Object getAsObject ( FacesContext context , UIComponent component , String value ) { value = value . trim () ; if (! Pattern . matches ( " [ -9]+\\ s +[ -9]+\\ s +[ -9 -]+ " , value ) ) { FacesMessage mensagem = new FacesMessage ( " Nmero de telefone invlido " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ConverterException ( mensagem ) ; } String campos [] = value . split ( " \\ s + " ) ;

www.k19.com.br

155

C ONVERSO E VALIDAO
19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36

156

String codigoDoPais = campos [ ]; String codigoDeArea = campos [1]; String numeroLocal = campos [2]. replaceAll ( " -" , " " ) ; Telefone telefone = new Telefone ( codigoDoPais , codigoDeArea , numeroLocal ) ; return telefone ; } @Override public String getAsString ( FacesContext context , UIComponent component , Object value ) { Telefone telefone = ( Telefone ) value ; return telefone . getCodigoDoPais () + " " + telefone . getCodigoDeArea () + " " + telefone . getNumeroLocal () ; } }
Cdigo Java 10.16: ConversorDeTelefone.java

Se a string recebida pelo mtodo getAsObject() no respeita o formato de nmeros de telefone denido acima, uma mensagem de erro criada e uma exceo do tipo javax.faces.convert.ConverterException guardando essa mensagem lanada.

Exerccios de Fixao
Considere um formulrio que possua uma caixa de texto para receber um nmero de CPF (Cadastro de Pessoas Fsicas). Um nmero de CPF dividido em duas partes. A primeira parte do nmero formada por nove dgitos. Chamaremos essa parte de nmero de identicao. A segunda parte formada por dois dgitos, que so chamados de dgitos vericadores. Esses dois ltimos dgitos so usados para vericar o nmero de identicao e prevenir erros. Um nmero de CPF apresentado com a primeira parte separada da segunda por um hfen.
15

Implemente um conversor de nmeros de CPF. Primeiramente, crie um pacote chamado model na pasta src. Crie uma classe chamada CPF para representar um nmero de CPF. Essa classe deve ter trs atributos do tipo int: um para armazenar o nmero de identicao e outros dois para guardar os dgitos vericadores.
16

1 2 3 4 5 6 7 8 9

package model ; public class CPF { private int numeroDeIdentificacao ; private int primeiroDigitoVerificador ; private int segundoDigitoVerificador ; // GETTERS E SETTERS }
Cdigo Java 10.17: CPF.java

17 18

No diretrio src, crie um pacote chamado converters.

Agora, dentro do pacote converters, crie uma classe chamada ConversorDeCPF para implementar o conversor de nmeros de CPF. Um nmero de CPF deve respeitar o seguinte formato:
156
www.k19.com.br

157

C ONVERSO E VALIDAO

XXXXXXXXX-XX. Lembre que essa classe deve ser anotada com @FacesConverter e implementar a interface javax.faces.convert.Converter.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 package converters ; @FacesConverter ( forClass = CPF . class ) public class ConversorDeCPF implements Converter { @Override public Object getAsObject ( FacesContext context , UIComponent component , String value ) { value = value . trim () ; if (! Pattern . matches ( " [ -9]{9} -[ -9]{2} " , value ) ) { FacesMessage mensagem = new FacesMessage ( " Nmero de CPF invlido " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ConverterException ( mensagem ) ; } String partesDoCPF [] = value . split ( " -" ) ; int numeroDeIdentificacao = Integer . parseInt ( partesDoCPF [ ]) ; int primeiroDigitoVerificador = Integer . parseInt ( partesDoCPF [1]. substring ( , 1) ) ; int segundoDigitoVerificador = Integer . parseInt ( partesDoCPF [1]. substring (1 , 2) ) ; CPF cpf = new CPF () ; cpf . setNumeroDeIdentificacao ( numeroDeIdentificacao ) ; cpf . setPrimeiroDigitoVerificador ( primeiroDigitoVerificador ) ; cpf . setSegundoDigitoVerificador ( segundoDigitoVerificador ) ; return cpf ; } @Override public String getAsString ( FacesContext context , UIComponent component , Object value ) { CPF cpf = ( CPF ) value ; return cpf . getNumeroDeIdentificacao () + " + " + cpf . getPrimeiroDigitoVerificador () + cpf . getSegundoDigitoVerificador () ; } }
Cdigo Java 10.18: ConversorDeCPF.java

19 20

No diretrio src, crie um pacote chamado managedbeans.

No pacote managedbeans, crie uma classe chamada CPFBean para implementar o managed bean que dar suporte ao formulrio.
1 2 3 4 5 6 7 8 package managedbeans ; @ManagedBean public class CPFBean { private CPF cpf ; // GETTER E SETTER }
Cdigo Java 10.19: CPFBean.java

Finalmente, crie um arquivo chamado formulario.xhtml e implemente um formulrio para receber um nmero de CPF.
21

1 2

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >

www.k19.com.br

157

C ONVERSO E VALIDAO
3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2

158

< html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Formulrio </ h1 > <h : form > <h : outputLabel value = " CPF : " for = " cpf " / > <h : inputText id = " cpf " value = " #{ cPFBean . cpf } " / > <h : commandButton value = " Enviar " / > </ h : form > <h : message for = " cpf " style = " color : red " / > </ h : body > </ html >
Cdigo XHTML 10.25: formulario.xhtml

22

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/formulario.xhtml
Teste o formulrio com diversos valores para campo de CPF. Observe as mensagens de erro de converso para valores invlidos.

Exerccios Complementares
Em 2010, foi lanado um novo de documento de identicao no Brasil, o Registro de Identidade Civil (RIC). Esse documento tem um nmero que identica unicamente cada cidado. O nmero RIC tem duas partes. A primeira parte formada por dez dgitos e a segunda, o dgito vericador, formada por um nico dgito. A primeira parte opcionalmente separada da segunda por um hfen. Primeiro, voc deve criar uma classe para modelar esse documento. Em seguida, voc deve implementar um conversor para esse tipo de objeto. Por m, voc deve implementar um formulrio para testar o seu conversor.
4

Criando o seu Prprio Validador


A criao de um validador anloga criao de um conversor. Precisamos criar uma classe que implemente a interface javax.faces.validator.Validator. Essa interface dene um nico mtodo, o validate(). Alm disso, a classe tambm precisa ser anotada com @FacesValidator. Considere um formulrio HTML que possui uma caixa de texto para o usurio digitar um nmero primo. Um nmero primo um nmero natural maior do que 1 cujos nicos divisores positivos so 1 e ele mesmo. Essa caixa de texto est associada a uma propriedade do tipo long em um managed bean. Aps o usurio submeter esse formulrio e uma vez que a etapa de converso foi concluda, precisamos validar os dados do formulrio. Em particular, precisamos vericar se o nmero digitado pelo usurio primo. Criaremos uma classe chamada ValidadorDeNumerosPrimos para implementar um validador que execute essa tarefa.
158
www.k19.com.br

159
1 2 3 4 5 6 package br . com . k19 ; @FacesValidator ( " br . com . k19 . ValidadorDeNumerosPrimos " ) public class ValidadorDeNumerosPrimos implements Validator { ... }
Cdigo Java 10.23: ValidadorDeNumerosPrimos.java

C ONVERSO E VALIDAO

Uma forma simples de vericar se determinado nmero primo testar se ele divisvel por algum nmero maior do que 1 e menor ou igual raiz quadrada desse nmero. Se ele for divisvel por algum desses nmeros, ento ele no primo. Caso contrrio, ele um nmero primo. No cdigo abaixo, apresentamos uma implementao para esse validador.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 package br . com . k19 ; @FacesValidator ( " br . com . k19 . ValidadorDeNumerosPrimos " ) public class ValidadorDeNumerosPrimos implements Validator { @Override public void validate ( FacesContext context , UIComponent component , Object value ) { long numero = ( Long ) value ; boolean isPrimo = false ; if ( numero > 1) { double raizQuadrada = Math . sqrt (( double ) numero ) ; isPrimo = true ; for ( long i = 2; i <= raizQuadrada ; i ++) { if ( numero % i == ) { isPrimo = false ; break ; } } } if (! isPrimo ) { FacesMessage mensagem = new FacesMessage ( " O nmero " + numero + " no primo " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ValidatorException ( mensagem ) ; } } }
Cdigo Java 10.24: ValidadorDeNumerosPrimos.java

Se o nmero que estamos validando no for primo ento precisamos lanar uma exceo do tipo javax.faces.validator.ValidatorException. Analogamente ao que zemos na elaborao de um conversor, lanamos uma exceo contendo uma FacesMessage com uma mensagem de erro. Para associar um validador a um determinado campo de um formulrio, podemos usar a tag <f:validator>. Essa tag possui um atributo chamado validatorId cujo valor deve ser igual ao valor registrado na anotao @FacesValidator. Em nosso caso particular, esse valor "br.com.k19.ValidadorDeNumerosPrimos". O cdigo XHTML abaixo dene um formulrio com uma caixa de texto e vincula essa caixa ao validador de nmeros primos.
1 2 3 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >

www.k19.com.br

159

C ONVERSO E VALIDAO
4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 < 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Digite um nmero primo : " for = " numero - primo " / > <h : inputText value = " #{ testeBean . numeroPrimo } " id = " numero - primo " > <f : validator validatorId = " br . com . k19 . ValidadorDeNumerosPrimos " / > </ h : inputText > <h : commandButton value = " Enviar " / > < br / > <h : message for = " numero - primo " style = " color : red " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 10.27: Associando um validador a uma propriedade

160

Passando Parmetros para o Validador


Para realizar a validao de um determinado dado, informaes adicionais podem ser necessrias. Por exemplo, considere o caso em que precisamos vericar se uma data escolhida por um usurio pertence a um determinado intervalo. Nesse caso, precisamos de duas informaes adicionais: as datas de incio e m do intervalo. Da mesma forma que criamos um validador de nmeros primos, podemos criar um validador para realizar essa vericao. A diferena que agora precisamos das datas que determinam o intervalo. Por exemplo, se tivermos uma caixa de texto para receber a data escolhida pelo usurio, ento as datas de incio e m do intervalo podem ser denidas como atributos dessa caixa. Para denir um atributo de um componente visual, podemos usar a tag <f:attribute>. Essa tag possui dois parmetros (name e value), que so usados para denir o nome e o valor desse atributo. Em nosso exemplo, criaremos dois atributos, que chamaremos de "inicio" e "fim", para denir as datas que delimitam o intervalo a ser considerado. No cdigo abaixo, criamos esses atributos com valores " 1/ 5/2 14" e "3 / 8/2 14", respectivamente.
1 2 3 4 <h : inputText value = " #{ testeBean . data } " id = " campo - data " > <f : attribute name = " inicio " value = " 1/ 5/2 14 " / > <f : attribute name = " fim " value = " 3 / 8/2 14 " / > </ h : inputText >
Cdigo XHTML 10.28: Adicionando atributos a um componente visual

Esses atributos podem ser recuperados no mtodo validade() do validador da seguinte forma:
1 2 3 4 5 6 7 @Override public void validate ( FacesContext context , UIComponent component , Object value ) { String inicio = ( String ) component . getAttributes () . get ( " inicio " ) ; String fim = ( String ) component . getAttributes () . get ( " fim " ) ; ... }
Cdigo Java 10.25: Recuperando atributos de um componente visual

160

www.k19.com.br

161

C ONVERSO E VALIDAO

Exerccios de Fixao
Agora, crie um validador de nmeros de CPF. Como dissemos no exerccio anterior, os dois ltimos dgitos do CPF (dgitos vericadores) so usados para validar os demais dgitos (nmero de identicao). Os dgitos vericadores so gerados por um algoritmo chamado Mdulo 11 a partir do nmero de identicao.
23

O primeiro dgito vericador obtido da seguinte forma. Suponha que o nmero de identicao seja x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 , onde x i representa o i -simo dgito da direita para a esquerda do nmero de identicao. Seja y o valor dado por y = 2x 1 + 3x 2 + 4x 3 + 5x 4 + 6x 5 + 7x 6 + 8x 7 + 9x 8 + 10x 9 . Se o valor do resto da diviso de y por 11 (y%11 em Java) for menor do que 2, ento o primeiro dgito vericador d 1 = 0. Caso contrrio, o primeiro dgito vericador d 1 igual a 11 menos o resto da diviso de y por 11. O segundo dgito vericador obtido de forma anloga, mas aplicando o algoritmo acima ao nmero x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 d 1 . Nesse caso, o novo valor de y ser y = 2d 1 + 3x 1 + 4x 2 + 5x 3 + 6x 4 + 7x 5 + 8x 6 + 9x 7 + 10x 8 + 11x 9 . Crie um pacote chamado validators no diretrio src.
24 No pacote validators, crie uma classe chamada ValidadorDeCPF. Lembre que essa classe deve ser anotada com @FacesValidator e implementar a interface javax.faces.validator.Validator.

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

package validators ; @FacesValidator ( value = " br . com . k19 . validators . ValidadorDeCPF " ) public class ValidadorDeCPF implements Validator { @Override public void validate ( FacesContext context , UIComponent component , Object value ) throws ValidatorException { CPF int int int cpf = ( CPF ) value ; numeroDeIdentificacao = cpf . getNumeroDeIdentificacao () ; primeiroDigitoVerificador = cpf . getPrimeiroDigitoVerificador () ; segundoDigitoVerificador = cpf . getSegundoDigitoVerificador () ;

if (! this . validaCPF ( numeroDeIdentificacao , primeiroDigitoVerificador , segundoDigitoVerificador ) ) { String numero = numeroDeIdentificacao + " -" + primeiroDigitoVerificador + segundoDigitoVerificador ; FacesMessage mensagem = new FacesMessage ( " O nmero " + numero + " no um CPF vlido " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ValidatorException ( mensagem ) ; } } private boolean validaCPF ( int numeroDeIdentificacao , int primeiroDigitoVerificador , int segundoDigitoVerificador ) { long primeiroDigito = this . modulo11 (( long ) numeroDeIdentificacao ) ;

www.k19.com.br

161

C ONVERSO E VALIDAO
32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 long segundoDigito = this . modulo11 (( long ) numeroDeIdentificacao * 1 + primeiroDigito ) ; return primeiroDigitoVerificador == primeiroDigito && segundoDigitoVerificador == segundoDigito ; } private long modulo11 ( long numero ) { long soma = ; long multiplicador = 2; while ( numero > ) { long digito = numero % 1 ; soma += multiplicador * digito ; numero /= 1 ; multiplicador ++; } long resto = soma % 11; if ( resto < 2) return ; else return 11 - resto ; } }
Cdigo Java 10.26: ValidadorDeCPF.java

162

25

No arquivo formulario.xhtml, associe a caixa de texto ao validador de nmeros de CPF criado.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 Treinamentos </ title > </ h : head > <h : body > < h1 > Formulrio </ h1 > <h : form > <h : outputLabel value = " CPF : " for = " cpf " / > <h : inputText id = " cpf " value = " #{ cPFBean . cpf } " > <f : validator validatorId = " br . com . k19 . validators . ValidadorDeCPF " / > </ h : inputText > <h : commandButton value = " Enviar " / > </ h : form > <h : message for = " cpf " style = " color : red " / > </ h : body > </ html >
Cdigo XHTML 10.29: formulario.xhtml

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

26

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/formulario.xhtml
Submeta o formulrio com valores invlidos para o nmero de CPF e observe as mensagens de erro de validao.

Exerccios Complementares
Considere um formulrio que possua um campo de texto para o usurio digitar uma data. Essa data deve pertencer a um determinado intervalo. Implemente um validador que considere essa res5

162

www.k19.com.br

163

C ONVERSO E VALIDAO

trio. As datas que denem o intervalo devem ser passadas como parmetro para o validador com o uso da tag <f:attribute>.

Criando o seu Prprio Bean Validator


Vimos que os bean validators podem ser registrados atravs de anotaes. Agora, mostraremos como criar o seu prprio bean validator e uma anotao para aplic-lo. Para exemplicar, considere a validao de nmeros primos. No exemplo abaixo, denimos a anotao @Primo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 package br . com . k19 ; import import import import static static static static java . lang . annotation . ElementType . ANNOTATION_TYPE ; java . lang . annotation . ElementType . FIELD ; java . lang . annotation . ElementType . METHOD ; java . lang . annotation . RetentionPolicy . RUNTIME ;

import java . lang . annotation . Retention ; import java . lang . annotation . Target ; import javax . validation . Constraint ; import javax . validation . Payload ; @Target ({ METHOD , FIELD , ANNOTATION_TYPE }) @Retention ( RUNTIME ) @Constraint ( validatedBy = ValidadorDePrimo . class ) public @interface Primo { String message () default " { br . com . k19 . Primo . message } " ; Class <? >[] groups () default {}; Class <? extends Payload >[] payload () default {}; }
Cdigo Java 10.29: Primo.java

Note que a anotao @Primo vinculada ao validador denido pela classe ValidadorDePrimo. Esse vnculo estabelecido atravs da propriedade validatedBy da anotao @Constraint. Observe tambm que, de acordo com o cdigo acima, a mensagem denida pela chave br.com.k19.Primo.message ser utilizada por padro quando um erro for identicado na validao. A classe que dene o validador de nmeros primos deve implementar a interface javax.validation.ConstraintValidator. Essa interface possui dois mtodos: initialize() e isValid(). O primeiro utilizado para extrair, se necessrio, os valores dos atributos da anotao. O segundo deve implementar a validao propriamente dita.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 public class ValidadorDePrimo implements ConstraintValidator < Primo , Long > { @Override public void initialize ( Primo constraintAnnotation ) { } @Override public boolean isValid ( Long value , ConstraintValidatorContext context ) { if ( value <= 1) { return false ; } double raizQuadrada = Math . sqrt (( double ) value ) ; for ( long i = 2; i <= raizQuadrada ; i ++) { if ( value % i == ) {

www.k19.com.br

163

C ONVERSO E VALIDAO
17 18 19 2 21 22 return false ; } } return true ; } }
Cdigo Java 10.30: ValidadorDePrimo.java

164

Por m, devemos denir o valor da mensagem associada chave br.com.k19.Primo.message no arquivo ValidationMessages.properties.
1 br . com . k19 . Primo . message = O nmero no primo
Arquivo de Propriedades 10.3: ValidationMessages.properties

Exerccios de Fixao
Seguindo o exerccio anterior, crie um bean validator para validar nmeros de CPF. Primeiro, crie um pacote chamado beanvalidators no diretrio src.
27 28

No pacote beanvalidators, dena a anotao @CPF como no cdigo abaixo.


package beanvalidators ; import import import import static static static static java . lang . annotation . ElementType . ANNOTATION_TYPE ; java . lang . annotation . ElementType . FIELD ; java . lang . annotation . ElementType . METHOD ; java . lang . annotation . RetentionPolicy . RUNTIME ;

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

import java . lang . annotation . Retention ; import java . lang . annotation . Target ; import javax . validation . Constraint ; import javax . validation . Payload ; @Target ({ METHOD , FIELD , ANNOTATION_TYPE }) @Retention ( RUNTIME ) @Constraint ( validatedBy = beanvalidators . CPFBeanValidator . class ) public @interface CPF { String message () default " O nmero de CPF no vlido " ; Class <? >[] groups () default {}; Class <? extends Payload >[] payload () default {}; }
Cdigo Java 10.31: CPF.java

No pacote beanvalidators, crie uma classe chamada CPFBeanValidator para implementar o validador associado anotao @CPF. Essa classe deve implementar a interface javax.validation.ConstraintValidator.
29

1 2 3 4 5 6 7 8 9

package beanvalidators ; import javax . validation . ConstraintValidator ; import javax . validation . ConstraintValidatorContext ; public class CPFBeanValidator implements ConstraintValidator < beanvalidators . CPF , model . CPF > { @Override

164

www.k19.com.br

165
1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 public void initialize ( beanvalidators . CPF constraintAnnotation ) { }

C ONVERSO E VALIDAO

@Override public boolean isValid ( model . CPF value , ConstraintValidatorContext context ) { model . CPF cpf = ( model . CPF ) value ; int numeroDeIdentificacao = cpf . getNumeroDeIdentificacao () ; int primeiroDigitoVerificador = cpf . getPrimeiroDigitoVerificador () ; int segundoDigitoVerificador = cpf . getSegundoDigitoVerificador () ; return this . validaCPF ( numeroDeIdentificacao , primeiroDigitoVerificador , segundoDigitoVerificador ) ; } private boolean validaCPF ( int numeroDeIdentificacao , int primeiroDigitoVerificador , int segundoDigitoVerificador ) { long primeiroDigito = this . modulo11 (( long ) numeroDeIdentificacao ) ; long segundoDigito = this . modulo11 (( long ) numeroDeIdentificacao * 1 + primeiroDigito ) ; return primeiroDigitoVerificador == primeiroDigito && segundoDigitoVerificador == segundoDigito ; } private long modulo11 ( long numero ) { long soma = ; long multiplicador = 2; while ( numero > ) { long digito = numero % 1 ; soma += multiplicador * digito ; numero /= 1 ; multiplicador ++; } long resto = soma % 11; if ( resto < 2) return ; else return 11 - resto ; } }
Cdigo Java 10.32: CPFBeanValidator.java

Na classe CPFBean, adicione a anotao @CPF ao atributo cpf para usar o validador que voc acabou de criar.
30

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

package managedbeans ; import javax . faces . bean . ManagedBean ; import model . CPF ; @ManagedBean public class CPFBean { @beanvalidators . CPF private CPF cpf ; // GETTER E SETTER }
Cdigo Java 10.33: CPFBean.java

31

Crie um formulrio com uma caixa de texto para digitar um nmero de CPF.
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " >

1 2

www.k19.com.br

165

C ONVERSO E VALIDAO
3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2

166

< 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Formulrio </ h1 > <h : form > <h : outputLabel value = " CPF : " for = " cpf " / > <h : inputText id = " cpf " value = " #{ cPFBean . cpf } " / > <h : commandButton value = " Enviar " / > </ h : form > <h : message for = " cpf " style = " color : red " / > </ h : body > </ html >
Cdigo XHTML 10.32: formulario.xhtml

32

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/formulario.xhtml

166

www.k19.com.br

CAPTULO

E VENTOS

11

Aplicaes JSF so fortemente baseadas em eventos. Esses eventos podem ser gerados pelos usurios da aplicao ou pelo prprio JSF. Veja abaixo alguns exemplos de eventos gerados pelos usurios. Um clique em um boto ou link. A troca do valor preenchido em uma caixa de texto. A troca da opo escolhida em uma caixa de seleo. Veja abaixo alguns exemplos de eventos gerados pelo JSF. Inicializao da aplicao. Finalizao da aplicao. Erro no processamento de uma requisio. Um evento pode ser associado a procedimentos que sero executados quando esse evento ocorrer. No JSF, os eventos so divididos em trs categorias: FacesEvent, PhaseEvent e SystemEvent.

FacesEvent
H dois tipos de FacesEvents: ActionEvent e ValueChangeEvent. Apresentaremos a seguir o funcionamento desses tipos de eventos.

ActionEvent
Um ActionEvent gerado quando um boto ou link pressionado pelo usurio. Mtodos de um managed bean podem ser associados a esses eventos. Toda vez que um evento ocorrer os mtodos associados a ele sero executados. Para associar mtodos de um managed bean a um ActionEvent, podemos utilizar os atributos action ou actionListener dos componentes <h:commandButton> e

<h:commandLink>
O atributo action deve ser associado a um mtodo pblico do tipo void ou String de um managed bean. Se esse mtodo devolver uma String, ela ser utilizada para determinar a navegao das pginas (veja Captulo 8). Conceitualmente, o atributo action deve ser associado a mtodos que representam alguma regra de negcio da aplicao. No exemplo abaixo, o boto Salva est associado ao mtodo salva() do managed bean produtoBean atravs do atributo action da tag <h:commandButton>. Esse mtodo implementa a lgica de negcio para cadastrar produtos. A String lista-produtos devolvida pelo mtodo salva() ser utilizada para determinar a navegao das pginas.
www.k19.com.br

167

E VENTOS
1 <h : commandButton value = " Salva " action = " #{ produtoBean . salva } " / >
Cdigo XHTML 11.1: Boto associado ao mtodo salva() do managed bean produtoBean

168

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

@ManagedBean public class ProdutoBean { private Produto produto = new Produto () ; private List < Produto > produtos = new ArrayList < Produto >() ; public String salva () { this . produtos . add ( this . produto ) ; this . produto = new Produto () ; return " lista - produtos " ; } // GETTERS E SETTERS }
Cdigo Java 11.1: ProdutoBean.java

O atributo actionListener, por sua vez, deve ser associado a um mtodo pblico do tipo void que receba um ActionEvent como parmetro. Conceitualmente, o atributo actionListener deve ser associado a mtodos que implementam alguma lgica associada interface do usurio. No exemplo abaixo, o boto Clique Aqui est associado ao mtodo mudaTexto() do managed bean cliqueBean atravs do atributo actionListener da tag <h:commandButton>. Esse mtodo altera o texto do boto para Clicado.
1 <h : commandButton value = " Clique Aqui " actionListener = " #{ cliqueBean . mudaTexto } " / >
Cdigo XHTML 11.2: Boto associado ao mtodo mudaTexto() do managed bean cliqueBean

1 2 3 4 5 6 7

@ManagedBean public class CliqueBean { public void mudaTexto ( ActionEvent e ) { UICommand c = ( UICommand ) e . getComponent () ; c . setValue ( " Clicado " ) ; } }
Cdigo Java 11.2: CliqueBean.java

Os atributos action e actionListener permitem que no mximo dois mtodos sejam associados a um evento de ao. Para associar mais do que dois mtodos a um evento de ao, podemos usar a tag <f:actionListener>. O valor do atributo type dessa tag deve ser o nome de uma classe que implemente a interface javax.faces.event.ActionListener. Essa interface exige a criao de um mtodo chamado processAction(). Veja o exemplo abaixo.
1 2 3 <h : commandLink value = " Enviar " action = " ... " actionListener = " ... " > <f : actionListener type = " br . com . k19 . MudaCorDaFonte " / > </ h : commandLink >
Cdigo XHTML 11.3: Link associado ao mtodo processAction() da classe MudaCorDaFonte

1 2 3 4 5

package br . com . k19 ; public class MudaCorDaFonte implements ActionListener { @Override public void processAction ( ActionEvent e ) {

168

www.k19.com.br

169
6 7 8 9 UICommand c = ( UICommand ) e . getComponent () ; c . getAttributes () . put ( " style " , " color : red ; " ) ; } }
Cdigo Java 11.3: MudaCorDaFonte.java

E VENTOS

Nesse exemplo, usamos a tag <f:actionListener> para associar o link ao mtodo processAction() da classe br.com.k19.MudaCorDaFonte.

Importante
Os mtodos associados a um evento de ao so executados na seguinte ordem: 1. O mtodo associado com o atributo actionListener. 2. Mtodos associados com tag <f:actionListener> de acordo com a ordem em que elas aparecem no arquivo XHTML. 3. O mtodo indicado pelo atributo action.

Importante
Por padro, os mtodos associados a eventos de ao so executados na fase Invoke Application do processamento de uma requisio (veja o Captulo 5 para mais informaes).

ValueChangeEvent
Um ValueChangeEvent produzido quando o valor de uma caixa de texto ou a opo de uma caixa de seleo so alterados. Podemos associar mtodos de um managed bean a esses eventos. Tais mtodos devem receber um parmetro do tipo ValueChangeEvent e serem pblicos. Para estabelecer essa associao, podemos utilizar o atributo valueChangeListener das caixas de texto ou de seleo ou a tag <f:valueChangeListener>. Considere um formulrio usado para editar as informaes dos produtos de uma loja. No exemplo abaixo, associamos uma caixa de texto ao mtodo mudaPreco() do managed bean produtoBean atravs do atributo valueChangeListener da tag <h:inputText>. Esse mtodo registra a mudana do preo de um produto.
1 2 <h : outputLabel value = " Preo : " for = " preco " / > <h : inputText valueChangeListener = " #{ produtoBean . mudaPreco } " id = " preco " / >
Cdigo XHTML 11.4: Caixa de texto associada ao mtodo mudaPreco() do managed bean produtoBean

1 2 3 4 5 6

@ManagedBean public class ProdutoBean { public void mudaPreco ( ValueChangeEvent e ) { System . out . println ( " Preo antigo : " + e . getOldValue () ) ; System . out . println ( " Preo novo : " + e . getNewValue () ) ; }

www.k19.com.br

169

E VENTOS
7 }
Cdigo Java 11.4: ProdutoBean.java

170

O mesmo pode ser feito com o uso da tag <f:valueChangeListener>. No exemplo abaixo, criamos uma classe chamada RegistraAlteracao, que implementa a interface ValueChangeListener, e associamos a caixa de texto ao mtodo processValueChange() dessa classe.
1 2 3 4 <h : outputLabel value = " Preo : " for = " preco " / > <h : inputText id = " preco " > <f : valueChangeListener type = " br . com . k19 . RegistraAlteracao " / > </ h : inputText >
Cdigo XHTML 11.5: Caixa de texto associada ao mtodo processValueChange() da classe RegistraAlteracao

1 2 3 4 5 6 7 8 9

package br . com . k19 ; public class RegistraAlteracao implements ValueChangeListener { @Override public void processValueChange ( ValueChangeEvent e ) { System . out . println ( " Preo antigo : " + e . getOldValue () ) ; System . out . println ( " Preo novo : " + e . getNewValue () ) ; } }
Cdigo Java 11.5: RegistraAlteracao.java

Importante
Os mtodos associados a um evento de mudana de valor so executados na seguinte ordem: 1. O mtodo associado com o atributo valueChangeListener. 2. Mtodos associados com tag <f:valueChangeListener> na ordem em que elas aparecem no arquivo XHTML.

Importante
Os mtodos associados a eventos de mudana de valor so executados na fase Process Validations do processamento de uma requisio. Veja o Captulo 5 para mais informaes sobre o processamento de uma requisio.

Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Eventos seguindo os passos vistos no exerccio do Captulo 5.
1

Criaremos uma pgina com trs botes. Um dos botes estar habilitado e os outros dois desabilitados. Quando o usurio pressionar o boto habilitado, a aplicao deve escolher aleatoriamente qual dos trs botes estar habilitado da prxima vez e desabilitar os outros dois.
2

170

www.k19.com.br

171

E VENTOS

Adicione na pasta WebContent o seguinte arquivo XHTML:


1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 - Eventos </ title > </ h : head > <h : body > <h : form > <h : commandButton id = " botao - jonas " value = " Jonas " disabled = " false " actionListener = " #{ botaoBean . sorteiaBotao } " / > <h : commandButton id = " botao - marcelo " value = " Marcelo " disabled = " true " actionListener = " #{ botaoBean . sorteiaBotao } " / > <h : commandButton id = " botao - rafael " value = " Rafael " disabled = " true " actionListener = " #{ botaoBean . sorteiaBotao } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 11.6: botoes.xhtml

Crie um managed bean para implementar o tratamento dos botes. Adicione em um pacote chamado managedbeans a seguinte classe:
3

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

@ManagedBean public class BotaoBean { public void sorteiaBotao ( ActionEvent event ) { UIComponent formulario = event . getComponent () . getParent () ; UIComponent botaoJonas = formulario . findComponent ( " botao - jonas " ) ; UIComponent botaoMarcelo = formulario . findComponent ( " botao - marcelo " ) ; UIComponent botaoRafael = formulario . findComponent ( " botao - rafael " ) ; botaoJonas . getAttributes () . put ( " disabled " , true ) ; botaoMarcelo . getAttributes () . put ( " disabled " , true ) ; botaoRafael . getAttributes () . put ( " disabled " , true ) ; double numero = Math . random () ; if ( numero < 1. /3. ) { botaoJonas . getAttributes () . put ( " disabled " , false ) ; } else if ( numero < 2. /3. ) { botaoMarcelo . getAttributes () . put ( " disabled " , false ) ; } else { botaoRafael . getAttributes () . put ( " disabled " , false ) ; } } }
Cdigo Java 11.6: BotaoBean.java

www.k19.com.br

171

E VENTOS
4

172

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Eventos/botoes.xhtml

PhaseEvent
Os PhaseEvents so eventos disparados automaticamente pelo JSF antes e depois de cada uma das fases do processamento de uma requisio. Esses eventos so teis basicamente para monitorar a execuo dessas fases. Para tratar um PhaseEvent, podemos criar uma classe que implemente a interface javax.faces.event.PhaseListener. Alm disso, precisamos registrar essa classe no arquivo faces-config.xml. A interface PhaseListener obriga a implementao de trs mtodos: afterPhase(), beforePhase() e getPhaseId(). O mtodo getPhaseId() deve devolver a referncia de um objeto do tipo javax.faces.event.PhaseId, que indica em quais fases do processamento de uma requisio estamos interessados. Se estivermos interessados nos eventos da fase Apply Request Values, por exemplo, podemos fazer esse mtodo devolver PhaseId.APPLY_REQUEST_VALUES. Os valores que podem ser utilizados so: PhaseId.RESTORE_VIEW PhaseId.APPLY_REQUEST_VALUES PhaseId.INVOKE_APPLICATION PhaseId.PROCESS_VALIDATIONS PhaseId.UPDATE_MODEL_VALUES PhaseId.RENDER_RESPONSE PhaseId.ANY_PHASE O mtodo beforePhase() recebe a referncia de um PhaseEvent como parmetro e executado antes das fases especicadas pelo mtodo getPhaseId(). O mtodo afterPhase() anlogo ao beforePhase() e executado aps as fases especicadas pelo mtodo getPhaseId(). No exemplo abaixo, criamos a classe MonitorPhaseListener que implementa a interface PhaseListener. No mtodo getPhaseId(), devolvemos PhaseId.ANY_PHASE, que indica que estamos interessados nos eventos relacionados a todas as fases.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 package br . com . k19 ; public class MonitorPhaseListener implements PhaseListener { @Override public void afterPhase ( PhaseEvent event ) { System . out . println ( " MonitorPhaseListener . afterPhase () " ) ; System . out . println ( event . getPhaseId () ) ; } @Override public void beforePhase ( PhaseEvent event ) { System . out . println ( " MonitorPhaseListener . beforePhase () " ) ; System . out . println ( event . getPhaseId () ) ; }

172

www.k19.com.br

173
17 18 19 2 21 @Override public PhaseId getPhaseId () { return PhaseId . ANY_PHASE ; } }
Cdigo Java 11.7: MonitorPhaseListener.java

E VENTOS

No arquivo faces-config.xml, registramos essa classe da seguinte forma:


1 2 3 4 5 ... < lifecycle > < phase - listener > br . com . k19 . MonitorPhaseListener </ phase - listener > </ lifecycle > ...
Cdigo XML 11.1: faces-cong.xml

Exerccios de Fixao
5

Crie uma classe em um pacote chamado phaselisteners com o seguinte contedo:


package phaselisteners ; public class MonitorPhaseListener implements PhaseListener { @Override public void afterPhase ( PhaseEvent event ) { System . out . println ( " MonitorPhaseListener . afterPhase () - " + event . getPhaseId () ) ; } @Override public void beforePhase ( PhaseEvent event ) { System . out . println ( " MonitorPhaseListener . beforePhase () - " + event . getPhaseId () ) ; } @Override public PhaseId getPhaseId () { return PhaseId . ANY_PHASE ; } }
Cdigo Java 11.8: MonitorPhaseListener.java

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

Registre a classe MonitorPhaseListener no arquivo faces-config.xml.


... < lifecycle > < phase - listener > phaselisteners . MonitorPhaseListener </ phase - listener > </ lifecycle > ...
Cdigo XML 11.2: faces-cong.xml

1 2 3 4 5

Acesse a pgina botoes.xhtml, clique nos botes e verique as mensagens impressas no con-

sole.

SystemEvent
www.k19.com.br

173

E VENTOS

174

SystemEvents so similares aos PhaseEvents no sentido de que ambos esto relacionados a pontos especcos de execuo de uma aplicao JSF. Contudo, os eventos de sistema so gerados em diversos pontos no cobertos pelos eventos de fase. Todas as classes que denem eventos de sistema so subclasses de javax.faces.event.SystemEvent. Apresentamos abaixo algumas dessas classes.
PostConstructApplicationEvent gerado imediatamente aps o incio da aplicao, depois que todas as conguraes so processadas. PreDestroyApplicationEvent Esse tipo de evento gerado imediatamente antes da aplicao ser nalizada. ExceptionQueuedEvent Esse evento gerado assim que uma exceo no esperada lanada durante o processamento de uma requisio. Alguns exemplos de excees esperadas durante o processamento de uma requisio so aquelas relacionadas converso e validao dos dados. PreValidateEvent e PostValidateEvent Esses eventos so gerados imediatamente antes e logo aps um componente ser validado, respectivamente. As trs primeiras classes listadas acima so subclasses diretas de SystemEvent, enquanto que as duas ltimas so subclasses de javax.faces.event.ComponentSystemEvent. Uma das formas para se registrar um interessado em eventos de sistema usando a tag <f:event>. Essa tag possui dois atributos: type e listener. O atributo type usado para indicar o tipo de evento. Alguns dos possveis valores para esse atributo so preValidate e postValidate. O atributo listener deve indicar um mtodo que ser chamado quando o evento for processado. Esse mtodo deve ser pblico, do tipo void, e receber como parmetro uma referncia para um objeto do tipo javax.faces.event.ComponentSystemEvent. O evento PostValidateEvent pode ser til na validao de mltiplos campos, por exemplo. Considere uma aplicao bancria que permite gerar extratos da conta corrente. Os dados de entrada so duas datas e o resultado o extrato referente ao perodo determinado por essas datas. Uma restrio que devemos impor que a data nal no pode vir antes da data inicial. No formulrio do cdigo abaixo, usamos a tag <f:event> para indicar que o mtodo validaDatas() do managed bean extratoBean deve ser chamado assim que o evento postValidate for processado.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 <h : form > <f : event type = " postValidate " listener = " #{ extratoBean . validaDatas } " / > <h : messages / > <h : outputLabel value = " Data inicial : " for = " data - inicial " / > <h : inputText value = " #{ extratoBean . dataInicial } " id = " data - inicial " required = " true " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : inputText > <h : outputLabel value = " Data final : " for = " data - final " / > <h : inputText value = " #{ extratoBean . dataFinal } " id = " data - final " required = " true " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : inputText > <h : commandButton value = " Ver extrato " action = " #{ extratoBean . geraExtrato } " / >

174

www.k19.com.br

175
16 </ h : form >

E VENTOS

Cdigo XHTML 11.7:

O mtodo validaDatas() do managed bean extratoBean registrado para receber eventos do tipo

PostValidateEvent

Na classe ExtratoBean, denimos o mtodo validaDatas() que recebe uma referncia para um ComponentSystemEvent como parmetro. Aps vericar se as datas inicial e nal so validas (tarefa executada pelo validador de datas padro de cada um dos componentes), prosseguimos com a vericao da nossa restrio adicional, isto , a data inicial deve vir antes da data nal. Se essa restrio no for respeitada, no devemos exibir extrato algum. Dessa forma, adicionamos uma mensagem no contexto do processamento da requisio e redirecionamos o uxo para a ltima fase do processamento, isto , para a fase Render Response.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 package managedbeans ; @ManagedBean public class ExtratoBean { private Date dataInicial ; private Date dataFinal ; public void validaDatas ( ComponentSystemEvent event ) { UIComponent source = event . getComponent () ; UIInput dataInicialInput = ( UIInput ) source . findComponent ( " data - inicial " ) ; UIInput dataFinalInput = ( UIInput ) source . findComponent ( " data - final " ) ; if ( dataInicialInput . isValid () && dataFinalInput . isValid () ) { Date dataInicialEscolhida = ( Date ) dataInicialInput . getLocalValue () ; Date dataFinalEscolhida = ( Date ) dataFinalInput . getLocalValue () ; if ( dataFinalEscolhida . before ( dataInicialEscolhida ) ) { FacesMessage message = new FacesMessage ( " A data final no pode vir antes da data inicial " ) ; message . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; FacesContext context = FacesContext . getCurrentInstance () ; context . addMessage ( source . getClientId () , message ) ; context . renderResponse () ; } } } public void geraExtrato () { FacesMessage message = new FacesMessage ( " extrato gerado com sucesso " ) ; message . setSeverity ( FacesMessage . SEVERITY_INFO ) ; FacesContext context = FacesContext . getCurrentInstance () ; context . addMessage ( null , message ) ; } // GETTERS E SETTERS }
Cdigo Java 11.9: ExtratoBean.java

Exerccios de Fixao
8

Na pasta WebContent adicione um arquivo XHTML com o seguinte contedo:


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN "

www.k19.com.br

175

E VENTOS
2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 - Eventos </ title > </ h : head > <h : body > <h : form > <f : event type = " postValidate " listener = " #{ extratoBean . validaDatas } " / > <h : outputLabel value = " Data inicial : " for = " data - inicial " / > <h : inputText value = " #{ extratoBean . dataInicial } " id = " data - inicial " required = " true " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : inputText > <h : outputLabel value = " Data final : " for = " data - final " / > <h : inputText value = " #{ extratoBean . dataFinal } " id = " data - final " required = " true " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : inputText > <h : commandButton value = " Ver extrato " action = " #{ extratoBean . geraExtrato } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 11.8: extrato.xhtml

176

Adicione a classe ExtratoBean em um pacote chamado managedbeans com o seguinte contedo:


package managedbeans ; @ManagedBean public class ExtratoBean { private Date dataInicial ; private Date dataFinal ; public void validaDatas ( ComponentSystemEvent event ) { UIComponent source = event . getComponent () ; UIInput dataInicialInput = ( UIInput ) source . findComponent ( " data - inicial " ) ; UIInput dataFinalInput = ( UIInput ) source . findComponent ( " data - final " ) ; if ( dataInicialInput . isValid () && dataFinalInput . isValid () ) { Date dataInicialEscolhida = ( Date ) dataInicialInput . getLocalValue () ; Date dataFinalEscolhida = ( Date ) dataFinalInput . getLocalValue () ; if ( dataFinalEscolhida . before ( dataInicialEscolhida ) ) { FacesMessage message = new FacesMessage ( " A data final no pode vir antes da data inicial " ) ; message . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; FacesContext context = FacesContext . getCurrentInstance () ; context . addMessage ( source . getClientId () , message ) ; context . renderResponse () ; } } }

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

176

www.k19.com.br

177
3 31 32 33 34 35 36 37 38 39

E VENTOS

public void geraExtrato () { FacesMessage message = new FacesMessage ( " extrato gerado com sucesso " ) ; message . setSeverity ( FacesMessage . SEVERITY_INFO ) ; FacesContext context = FacesContext . getCurrentInstance () ; context . addMessage ( null , message ) ; } // GETTERS E SETTERS }
Cdigo Java 11.10: ExtratoBean.java

10

Acesse a pgina extrato.xhtml e teste a validao das datas.

Immediate
Por padro, a converso e a validao dos dados de um componente de entrada (<h:inputText>, por exemplo) so realizadas na fase Process Validation. Alm disso, os eventos de mudana de valor (ValueChangeEvent) tambm ocorrem nessa fase. Tambm por padro, os eventos de ao (ActionEvent) associados aos componentes <h:commandButton> ou <h:commandLink> so disparados no nal da fase Invoke Application do processamento de uma requisio. Porm, esse comportamento pode ser alterado atravs do atributo immediate desses componentes. Se o valor do atributo immediate de um componente de entrada for true, ento a converso e validao dos dados desse componente iro ocorrer durante a fase Apply Request Values, onde tambm iro ser disparados possveis eventos de mudana de valor. No caso dos links e botes, os eventos de ao sero disparados no nal da fase Apply Request Values.

Exerccios de Fixao
Crie um formulrio para o cadastro de pessoas. Esse formulrio deve possuir trs campos obrigatrios. O primeiro deve ser uma caixa de texto para receber o nome de uma pessoa. O segundo deve ser uma caixa de seleo para o usurio escolher um estado. O terceiro campo tambm deve ser uma caixa de seleo, que permitir ao usurio escolher uma cidade. A caixa de seleo de cidade deve exibir apenas as cidades do estado escolhido. Ou seja, quando o usurio selecionar determinado estado, a lista de cidades deve ser atualizada de acordo.
11

Na pasta src do projeto K19-Eventos, crie um pacote chamado managedbeans e outro chamado

model.
No pacote model, crie uma classe chamada Estado para modelar um estado. Essa classe deve ter como atributos o nome e a sigla do estado, bem como uma lista de cidades.
12

1 2 3 4 5 6

package model ; public class Estado { private String nome ; private String sigla ; private List < String > cidades = new ArrayList < String >() ;

www.k19.com.br

177

E VENTOS
7 8 9

178

// GETTERS E SETTERS }
Cdigo Java 11.11: Estado.java

No pacote managedbeans, crie uma classe chamada CadastroBean, que dar suporte ao formulrio de cadastro. Essa classe tambm deve armazenar uma lista de estados que podero ser escolhidos no formulrio. Anote essa classe com @SessionScoped para que os dados do formulrio sejam mantidos entre uma requisio e outra.
13

1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49

package managedbeans ; @ManagedBean @SessionScoped public class CadastroBean { private String nome ; private String cidade ; private String siglaDoEstadoEscolhido ; private Estado estadoSelecionado = new Estado () ; private List < Estado > estados = new ArrayList < Estado >() ; public CadastroBean () { 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 " ) ; Estado rn = new Estado () ; rn . setSigla ( " RN " ) ; rn . setNome ( " Rio Grande do Norte " ) ; rn . getCidades () . add ( " Natal " ) ; rn . getCidades () . add ( " Mossor " ) ; this . estados . add ( sp ) ; this . estados . add ( rj ) ; this . estados . add ( rn ) ; } public void mudaEstado ( ValueChangeEvent event ) { this . siglaDoEstadoEscolhido = event . getNewValue () . toString () ; for ( Estado e : this . estados ) { if ( e . getSigla () . equals ( this . siglaDoEstadoEscolhido ) ) { this . estadoSelecionado = e ; break ; } } } // GETTERS E SETTERS }
Cdigo Java 11.12: CadastroBean.java

Na pasta WebContent, crie um arquivo chamado cadastro.xhtml e implemente o formulrio desejado.


14

178

www.k19.com.br

179
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Cadastro </ h1 > <h : form > <h : panelGrid columns = " 3 " > <h : outputLabel value = " Nome : " for = " nome " / > <h : inputText value = " #{ cadastroBean . nome } " required = " true " id = " nome " / > <h : message for = " nome " / > <h : outputLabel value = " Estado : " for = " estado " / > <h : selectOneMenu id = " estado " value = " #{ cadastroBean . siglaDoEstadoEscolhido } " valueChangeListener = " #{ cadastroBean . mudaEstado } " onchange = " this . form . submit () ; " required = " true " > <f : selectItem itemLabel = " Escolha um estado " noSelectionOption = " true " / > <f : selectItems value = " #{ cadastroBean . estados } " var = " estado " itemLabel = " #{ estado . nome } " itemValue = " #{ estado . sigla } " / > </ h : selectOneMenu > <h : message for = " estado " / > <h : outputLabel value = " Cidade : " for = " cidade " / > <h : selectOneMenu id = " cidade " value = " #{ cadastroBean . cidade } " required = " true " > <f : selectItem itemLabel = " Escolha uma cidade " noSelectionOption = " true " / > <f : selectItems value = " #{ cadastroBean . estadoSelecionado . cidades } " / > </ h : selectOneMenu > <h : message for = " cidade " / > </ h : panelGrid > <h : commandButton value = " Cadastrar " / > </ h : form > </ h : body > </ html >
Cdigo XHTML 11.9: cadastro.xhtml

E VENTOS

Para que a lista de cidades seja atualizada assim que o usurio selecionar um novo estado, usamos os atributos onchange e valueChangeListener do componente <h:selectOneMenu>. Denimos o valor do atributo onchange como sendo "this.form.submit();", o que signica que o formulrio ser submetido toda vez que um novo estado for selecionado. Alm disso, o atributo valueChangeListener est associado ao mtodo mudaEstado(), o que signica que esse mtodo ser chamado quando o evento de mudana de valor for gerado no processamento da requisio. Nesse mtodo, alteramos o valor da propriedade estadoSelecionado para reetir a escolha atual do usurio, o que implica que a caixa de seleo de cidade exibir as cidades desse estado. Veja as linhas em destaque no cdigo acima.
15

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Eventos/cadastro.xhtml
www.k19.com.br

179

E VENTOS

180

Note que, quando selecionamos um estado, o formulrio submetido automaticamente e os dados de todos os campos so convertidos e validados. Para atualizar a lista de cidades, precisamos que o dado presente na caixa de seleo de estado passe pelas etapas de converso e validao. Por outro lado, queremos evitar que os demais campos sejam convertidos e validados, bem como evitar que o cadastro seja efetivado sem que o usurio tenha submetido o formulrio.
16

Assim, precisamos (i) antecipar a converso e validao dessa caixa de seleo e, logo em seguida, (ii) desviar o uxo do processamento da requisio para a fase Render Response. A primeira tarefa pode ser feita denindo como true o valor do atributo immediate do componente <h:selectOneMenu>. O uxo do processamento da requisio pode ser desviado para a fase Render Response se chamarmos o mtodo renderResponse() da instncia da classe FacesContext logo aps atualizarmos o valor do atributo estadoSelecionado do managed bean cadastroBean.
1 2 3 4 5 6 7 8 9 1 11 12 13 ... <h : selectOneMenu id = " estado " value = " #{ cadastroBean . siglaDoEstadoEscolhido } " required = " true " valueChangeListener = " #{ cadastroBean . mudaEstado } " onchange = " this . form . submit () ; " immediate = " true " > <f : selectItem itemLabel = " Escolha um estado " noSelectionOption = " true " / > <f : selectItems value = " #{ cadastroBean . estados } " var = " estado " itemLabel = " #{ estado . nome } " itemValue = " #{ estado . sigla } " / > </ h : selectOneMenu > ...
Cdigo XHTML 11.10: cadastro.xhtml

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

... public void mudaEstado ( ValueChangeEvent event ) { this . siglaDoEstadoEscolhido = event . getNewValue () . toString () ; for ( Estado e : this . estados ) { if ( e . getSigla () . equals ( this . siglaDoEstadoEscolhido ) ) { this . estadoSelecionado = e ; break ; } } FacesContext . getCurrentInstance () . renderResponse () ; } ...
Cdigo Java 11.13: CadastroBean.java

180

www.k19.com.br

CAPTULO
Cdigo XHTML 12.1: Aplicando a tag <f:ajax>

A JAX

12

Quando as aplicaes possuem telas complexas, com grande quantidade de contedo, no interessante recarregar uma pgina inteira s para modicar uma pequena parte da tela. Com o intuito de melhorar a interatividade entre as aplicaes e os usurios, podemos aplicar o conceito do AJAX (Asynchronous Javascript And XML). Aplicando esse conceito, obtemos duas capacidades muito uteis. A primeira a possibilidade de atualizar trechos de uma pgina ao invs da pgina inteira. A segunda poder realizar requisies sem interromper a navegao dos usurios. Por exemplo, considere uma aplicao web para a visualizao de fotos. As fotos so exibidas individualmente em uma tela que tambm apresenta outros contedos. Os usurios podem, atravs do link Prxima, avanar para a prxima foto, ou voltar para a foto anterior atravs do link Anterior. Quando o usurio decide visualizar a prxima foto ou a anterior, no necessrio recarregar a pgina inteira, j que o nico contedo alterado da pgina a foto. Outro exemplo, considere uma aplicao de mensagens instantneas (GTalk, MSN, . . . ). A listagem de contatos de um usurio pode ser atualizada frequentemente sem que ele tenha que pressionar qualquer boto ou link, sem que a pgina tenha de ser recarregada e sem interromper a navegao do usurio. A verso 2 do JSF, diferentemente das anteriores, oferece suporte nativo a AJAX. Neste captulo, veremos como utilizar esse suporte.

Fazendo requisies AJAX


As requisies AJAX so realizadas quando determinados eventos ocorrem. Esses eventos esto fortemente relacionados aos componentes visuais adicionados s pginas. Devemos indicar para o JSF quais componentes e eventos devem realizar requisies AJAX. Para fazer isso, utilizamos a tag <f:ajax>.
1 2 3 <h : inputText > <f : ajax / > </ h : inputText >

No exemplo acima, uma requisio AJAX ser realizada toda vez que o valor da caixa de texto for modicado, j que o evento padro associado ao componente <h:inputText> o onchange. Por outro lado, podemos explicitar o evento que deve disparar as requisies AJAX atravs do atributo event da tag <f:ajax>. Devemos tomar cuidado pois nem todos os eventos so aceitos por todos os componentes.
1 <h : inputText >

www.k19.com.br

181

A JAX
2 3 <f : ajax event = " keyup " / > </ h : inputText >
Cdigo XHTML 12.2: Denindo o tipo de evento que deve disparar requisies AJAX

182

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 >
Cdigo XHTML 12.3: Aplicando a tag <f:ajax> a vrios componentes

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

Processando uma parte especca da tela


Quando uma requisio AJAX feita, podemos determinar quais componentes da tela devem ser avaliados pelo JSF. Por exemplo, quando enviamos um formulrio, talvez seja necessrio avaliar apenas os componentes que esto no prprio formulrio. Podemos denir quais componentes devem ser avaliados no servidor atravs do atributo execute da tag <f:ajax>. O valor desse atributo deve ser uma lista contendo os identicadores dos componentes que precisam ser avaliados no servidor. Quando um componente avaliado, todos os componentes denidos em seu corpo tambm sero avaliados.
1 2 3 4 5 6 7 8 9 <h : form id = " formulario - login " > <h : inputText / > <h : inputSecret / > <h : commandButton value = " Enviar " > <f : ajax event = " click " execute = " formulario - login " / > </ h : commandButton > </ h : form >
Cdigo XHTML 12.5: Denindo quais componentes sero avaliados

No exemplo acima, quando o boto Enviar for pressionado, uma requisio AJAX ser realizada. No servidor, o formulrio e todos os componentes denidos dentro dele sero avaliados.
182
www.k19.com.br

183

A JAX

Recarregando parte da tela


Podemos denir quais componentes devem ser atualizados quando a resposta de uma requisio AJAX chega no navegador. Para isso, devemos utilizar o atributo render da tag <f:ajax>. O valor desse atributo deve ser uma lista contendo os identicadores dos componentes que precisam ser atualizados quando a resposta de uma requisio AJAX chegar no navegador.
1 2 3 4 <h : commandButton value = " Gera Nmero " > <f : ajax event = " click " render = " numero " / > </ h : commandButton > <h : outputText id = " numero " value = " #{ geradorDeNumeroBean . numero } " / >
Cdigo XHTML 12.6: Denindo quais componentes sero atualizados

No exemplo acima, uma requisio AJAX realizada quando o boto Gera Nmero pressionado. Quando a resposta dessa requisio chega no navegador, apenas o componente <h:outputText> com o identicador numero ser atualizado. J no cdigo abaixo, dois componentes <h:outputText> so atualizados. Mais especicamente, os componentes com os identicadores numero1 e numero2 so atualizados.
1 2 3 4 5 <h : commandButton value = " Gera Nmeros " > <f : ajax event = " click " render = " numero1 numero2 " / > </ h : commandButton > <h : outputText id = " numero1 " value = " #{ geradorDeNumeroBean . numero } " / > <h : outputText id = " numero2 " value = " #{ geradorDeNumeroBean . numero } " / >
Cdigo XHTML 12.7: Denindo dois componentes para serem atualizados

Associando um procedimento a uma requisio AJAX


Podemos associar um mtodo a uma requisio AJAX. Esse mtodo ser executado durante o processamento dessa requisio no servidor. Mais especicamente, ele ser executado na fase Invoke Application. Essa associao realizada atravs do atributo listener da tag <f:ajax>.
1 2 3 4 5 6 7 <h : commandButton value = " Salva " > <f : ajax event = " click " execute = " formulario " render = " formulario " listener = " #{ produtoBean . salva } " / > </ h : commandButton >
Cdigo XHTML 12.8: Denindo quais componentes sero atualizados

No exemplo acima, as requisies AJAX realizadas atravs do boto Salva foram associadas ao mtodo salva() do managed bean produtoBean.

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 componentes.
www.k19.com.br

183

A JAX

184

@all refere-se a todos os componentes da tela. @none 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 identicador do formulrio.
1 2 3 4 5 6 7 8 9 <h : form id = " formulario - login " > <h : inputText / > <h : inputSecret / > <h : commandButton value = " Enviar " > <f : ajax event = " click " execute = " @form " / > </ h : commandButton > </ h : form >
Cdigo XHTML 12.9: Utilizando a palavra especial @form

Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Ajax seguindo os passos vistos no exerccio do Captulo 5.
1

Criaremos um formulrio com a validao dos campos realizadas com AJAX. Na pasta WebContent, adicione um arquivo XHTML com o seguinte contedo:
2

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 - Ajax </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : inputText id = " caixa " > <f : ajax event = " keyup " execute = " caixa " render = " mensagem " / > <f : validateLength minimum = " 5 " maximum = " 1 " / > </ h : inputText > <h : message id = " mensagem " for = " caixa " style = " color : red " / > <h : commandButton value = " Enviar " / > </ h : panelGrid > </ h : form > </ h : body > </ html >

184

www.k19.com.br

185

A JAX

Cdigo XHTML 12.10: formulario.xhtml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Ajax/formulario.xhtml

www.k19.com.br

185

A JAX

186

186

www.k19.com.br

CAPTULO

I NTEGRAO JSF E JPA

13

Como vimos nos primeiros captulos, os SGDBs so utilizados para armazenar os dados manipulados pelas aplicaes. At agora, os dados manipulados pelas aplicaes JSF desenvolvidas nos exerccios no foram armazenados em um SGDB. Adicionaremos essa capacidade s aplicaes JSF neste captulo. Para isso, mostraremos uma maneira de integrar os recursos do JSF e do JPA.

Bibliotecas
Para utilizar os recursos do JPA em uma aplicao JSF, os jars do provedor JPA e do driver JDBC que sero utilizados devem estar no classpath da aplicao. Nos captulos anteriores, as aplicaes JSF desenvolvidas nos exerccios foram implantadas no Glasssh 3.0.1 que um servidor de aplicao Java EE 6. Por padro, a verso 3.0.1 do Glasssh possui os jars do provedor JPA EclipseLink. Dessa forma, as aplicaes JSF implantadas nessa verso do Glasssh utilizaro o EclipseLink como implementao do JPA. Contudo, queremos utilizar o provedor JPA Hibernate. Podemos facilmente substituir os jars do EclipseLink pelos jars do Hibernate atravs da interface de administrao do Glasssh.

Mais Sobre
Consulte o artigo da K19 sobre a substituio dos jars do provedor JPA EclipseLink pelos jars do provedor JPA Hibernate.

http://www.k19.com.br/artigos/configurando-hibernate-no-glassfish-3-1/

Utilizaremos o MySQL Server como SGDB. Dessa forma, devemos adicionar o driver JDBC do MySQL Server no classpath das aplicaes JSF. O Glasssh 3.0.1 no possui os jars desse driver JDBC. Contudo, podemos adicion-los manualmente. Para isso, basta acrescentar os jars do driver JDBC do MySQL em uma pasta apropriada do Glasssh. Nos exerccios deste captulo, mostraremos como realizar tal tarefa.

Congurao
Como vimos no Captulo 3, devemos congurar as unidades de persistncia utilizadas atravs do arquivo persistence.xml da pasta META-INF do classpath da aplicao.
1 2 3 4 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance "

www.k19.com.br

187

I NTEGRAO JSF E JPA


5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " 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:33 6 / K19 - DB " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 13.1: persistence.xml

188

Mapeamento
Tambm devemos denir o mapeamento das entidades. No Captulo 3, vimos como utilizar as anotaes do JPA para estabelecer esse mapeamento.
1 2 3 4 5 6 7 8 9 1 11 @Entity public class Produto { @Id @GeneratedValue private Long id ; private String nome ; private Double preco ; // GETTERS e SETTERS }
Cdigo Java 13.1: Produto.java

Inicializao e Finalizao
As unidades de persistncia devem ser inicializadas antes de serem utilizadas, e nalizadas quando no forem mais necessrias. A inicializao e a nalizao de uma unidade de persistncia devem ser realizadas apenas uma vez durante a execuo da aplicao. Para implementar essa caracterstica em aplicaes web Java, podemos utilizar um ltro. Os ltros de uma aplicao web Java so inicializados automaticamente depois que a aplicao implantada no Web Container e antes da primeira requisio HTTP. Alm disso, eles so nalizados ao trmino da execuo da aplicao. Para adicionar um ltro em uma aplicao web Java, necessrio criar uma classe que implemente a interface javax.servlet.Filter.
188
www.k19.com.br

189
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 @WebFilter ( servletNames ={ " Faces Servlet " }) public class JPAFilter implements Filter { private EntityManagerFactory factory ;

I NTEGRAO JSF E JPA

@Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // por enquanto vazio } }
Cdigo Java 13.2: JPAFilter.java

Um ltro pode ser registrado no Web Container atravs da anotao @WebFilter. Com essa anotao, podemos denir qual servlet ser associada ao ltro. No exemplo acima, o ltro denido pela classe JPAFilter foi associado a servlet Faces Servlet. O mtodo init() chamado automaticamente na inicializao do ltro. No exemplo acima, esse mtodo inicializa a unidade de persistncia K19-PU. O mtodo destroy() chamado automaticamente para desativar o ltro no encerramento da aplicao. No exemplo acima, nalizamos a unidade de persistncia K19-PU.

Transaes
Como vimos no Captulo 3, para atualizar as informaes armazenadas no SGDB de acordo com os dados da memria da aplicao, devemos abrir uma transao e conrm-la atravs do mtodo commit(). O ltro criado anteriormente para controlar a inicializao e nalizao das unidades de persistncia pode tambm gerenciar a abertura e a conrmao das transaes da aplicao. Para isso, utilizaremos o mtodo doFilter() desse ltro.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 @WebFilter ( servletNames ={ " Faces Servlet " }) public class JPAFilter implements Filter { private EntityManagerFactory factory ; @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; }

www.k19.com.br

189

I NTEGRAO JSF E JPA


16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; entityManager . getTransaction () . begin () ; // CHEGADA // FACES SERVLET chain . doFilter ( request , response ) ; // FACES SERVLET // SADA try { entityManager . getTransaction () . commit () ; } catch ( Exception e ) { entityManager . getTransaction () . rollback () ; } finally { entityManager . close () ; } // SADA } }
Cdigo Java 13.3: JPAFilter.java

190

No exemplo acima, o mtodo doFilter() chamado toda vez que uma requisio realizada para a servlet Faces Servlet. Antes de repassar a requisio para a Faces Servlet, o mtodo doFilter() cria um EntityManager, armazena-o na requisio e abre uma transao. Depois que a Faces Servlet processou a requisio, o mtodo doFilter() tenta conrmar a transao atravs do mtodo commit(). Se um erro ocorrer nessa tentativa, o mtodo rollback() chamado para cancelar a transao.

Recuperando o EntityManager da Requisio


O EntityManager armazenado dentro da requisio pelo ltro pode ser recuperado a qualquer momento durante o processamento da requisio. Veja o cdigo abaixo.
1 2 3 4 FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ;
Cdigo Java 13.4: Recuperando o EntityManager da requisio

O EntityManager ser utilizado pela aplicao para realizar as operaes de persistncia.

Exerccios de Fixao
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 glassfishv3/glassfish/lib tambm da sua rea de Trabalho. OBS: O Glasssh deve ser reiniciado para reconhecer o driver JDBC do MySQL.
1 2

Crie um projeto do tipo Dynamic Web Project chamado K19-Integracao-JSF-JPA seguindo os


www.k19.com.br

190

191

I NTEGRAO JSF E JPA

passos vistos no exerccio do Captulo 5.


3 4

Adicione uma pasta chamada META-INF na pasta src do projeto K19-Integracao-JSF-JPA. Congure o JPA adicionando o arquivo persistence.xml na pasta META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - PU " 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 = " 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:33 6 / K19 - DB " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 13.2: persistence.xml

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

Abra um terminal; entre no cliente do MySQL Server; apague se existir a base de dados K19-DB; e crie uma base de dados nova chamada K19-DB.
5
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password : Welcome to the MySQL monitor . Commands end with ; or \ g . Your MySQL connection id is 36 Server version : 5.1.58 -1 ubuntu1 ( Ubuntu ) Copyright ( c ) 2 , 2 1 , Oracle and / or its affiliates . All rights reserved . This software comes with ABSOLUTELY NO WARRANTY . This is free software , and you are welcome to modify and redistribute it under the GPL v2 license Type help ; or \h for help . Type \c to clear the current input statement . mysql > DROP DATABASE IF EXISTS K19 - DB ; Query OK , rows affected , 1 warning ( . mysql > CREATE DATABASE K19 - DB ; Query OK , 1 row affected ( . 2 sec )

sec )

6 7

Crie um pacote chamado filters na pasta src do projeto K19-Integracao-JSF-JPA. No pacote filters, crie uma classe chamada JPAFilter com o seguinte contedo:
package filters ; @WebFilter ( servletNames ={ " Faces Servlet " }) public class JPAFilter implements Filter { private EntityManagerFactory factory ;

1 2 3 4 5 6 7

www.k19.com.br

191

I NTEGRAO JSF E JPA


8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; manager . getTransaction () . begin () ; // CHEGADA // FACES SERVLET chain . doFilter ( request , response ) ; // FACES SERVLET // SADA try { manager . getTransaction () . commit () ; } catch ( Exception e ) { manager . getTransaction () . rollback () ; } finally { manager . close () ; } // SADA } }
Cdigo Java 13.5: JPAFilter.java

192

8 9

Crie um pacote chamado model na pasta src do projeto K19-Integracao-JSF-JPA. No pacote model, crie uma classe chamada Carro com o seguinte contedo:
package model ; @Entity public class Carro { @Id @GeneratedValue private Long id ; private String marca ; private String modelo ; // GETTERS E SETTERS }
Cdigo Java 13.6: Carro.java

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

10

No pacote model, crie uma classe chamada CarroRepository com o seguinte contedo:
package model ; public class CarroRepository { private EntityManager manager ; public CarroRepository ( EntityManager manager ) { this . manager = manager ;

1 2 3 4 5 6 7 8

192

www.k19.com.br

193
9 1 11 12 13 14 15 16 17 18 19 } public void adiciona ( Carro carro ) { this . manager . persist ( carro ) ; } public List < Carro > buscaTodos () { Query query = this . manager . createQuery ( " select x from Carro x " ) ; return query . getResultList () ; } }
Cdigo Java 13.7: CarroRepository.java

I NTEGRAO JSF E JPA

11 12

Crie um pacote chamado managedbeans na pasta src do projeto K19-Integracao-JSF-JPA. No pacote managedbeans, crie uma classe chamada CarroBean com o seguinte cdigo:
package managedbeans ; @ManagedBean public class CarroBean { private Carro carro = new Carro () ; public void adicionaCarro () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; repository . adiciona ( this . carro ) ; this . carro = new Carro () ; } public List < Carro > getCarros () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; return repository . buscaTodos () ; } private EntityManager getEntityManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } // GETTERS E SETTERS }
Cdigo Java 13.8: CarroBean.java

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

No diretrio WebContent, crie um arquivo XHTML chamado carros.xhtml com o seguinte contedo:
13

1 2 3 4 5 6 7 8 9 1 11

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head >

www.k19.com.br

193

I NTEGRAO JSF E JPA


12 13 14 15 16 17 18 19 2 21 22 23 24 25 <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Marca : " for = " campo - marca " / > <h : inputText value = " #{ carroBean . carro . marca } " id = " campo - marca " / > <h : outputLabel value = " Modelo : " for = " campo - modelo " / > <h : inputText value = " #{ carroBean . carro . modelo } " id = " campo - modelo " / > <h : commandButton value = " Adicionar " action = " #{ carroBean . adicionaCarro } " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML 13.1: carros.xhtml

194

14

No arquivo carros.xhtml, adicione um trecho de cdigo para exibir os carros adicionados.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Marca : " for = " campo - marca " / > <h : inputText value = " #{ carroBean . carro . marca } " id = " campo - marca " / > <h : outputLabel value = " Modelo : " for = " campo - modelo " / > <h : inputText value = " #{ carroBean . carro . modelo } " id = " campo - modelo " / > <h : commandButton value = " Adicionar " action = " #{ carroBean . adicionaCarro } " / > </ h : panelGrid > </ h : form > <h : panelGroup rendered = " #{ not empty carroBean . carros } " > < h1 > Lista de carros : </ h1 > < ul > < ui : repeat value = " #{ carroBean . carros } " var = " carro " > < li > <h : outputText value = " #{ carro . marca } #{ carro . modelo } " / > </ li > </ ui : repeat > </ ul > </ h : panelGroup > </ h : body > </ html >
Cdigo XHTML 13.2: carros.xhtml

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

15

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Integracao-JSF-JPA/carros.xhtml
Adicione alguns carros e verique se eles foram adicionados no SGDB.

Otimizando o nmero de consultas ao SGDB


194
www.k19.com.br

195

I NTEGRAO JSF E JPA

Durante o processamento de uma requisio, os mtodos getters so chamados pelo JSF. A quantidade de chamadas no pode ser controlada pela aplicao. A lgica implementada nos getters pode comprometer a performance da aplicao. Por exemplo, nos exerccios anteriores, toda vez que o mtodo getCarros() do managed bean carroBean chamado, uma consulta realizada no SGBD atravs do repositrio de carros. Podemos diminuir a quantidade de consultas armazenando o resultado da primeira chamada em um atributo da classe CarroBean. Esse resultado pode ser mantido at que alguma alterao na listagem de carros ocorra. Por exemplo, se um carro for adicionado ou removido, a listagem armazenada deve ser descartada e recuperada novamente do SGDB. Veja o cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 package managedbeans ; @ManagedBean public class CarroBean { private Carro carro = new Carro () ; private List < Carro > carros ; public void adicionaCarro () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; repository . adiciona ( this . carro ) ; this . carro = new Carro () ; this . carros = null ; } public List < Carro > getCarros () { if ( this . carros == null ) { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; this . carros = repository . buscaTodos () ; } return this . carros ; } private EntityManager getEntityManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } // GETTERS E SETTERS }

Cdigo Java 13.9: CarroBean.java

No cdigo acima, o atributo carros armazena a ltima lista carregada do SGDB. No mtodo getCarros(), vericamos se j existe uma lista carregada no atributo carros. Se no existir uma lista carregada ento utilizamos o repositrio de carros para recuperar os dados do SGDB e carregar a lista. Caso contrrio, simplesmente utilizamos a lista que j estava carregada. No mtodo adicionaCarro(), depois que o repositrio de carros acionado para persistir um carro, descartamos o contedo do atributo carros. Dessa forma, na prxima chamada do mtodo getCarros(), a lista ser carregada novamente e conter o carro que acabou de ser adicionado.
www.k19.com.br

195

I NTEGRAO JSF E JPA

196

Exerccios de Fixao
Vamos monitorar a quantidade de chamadas ao mtodo getCarros() do managed bean carroBean. Altere a classe desse managed bean da seguinte forma:
16

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

package managedbeans ; @ManagedBean public class CarroBean { private Carro carro = new Carro () ; public void adicionaCarro () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; repository . adiciona ( this . carro ) ; this . carro = new Carro () ; } public List < Carro > getCarros () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; System . out . println ( " CHAMANDO O REPOSITORIO " ) ; return repository . buscaTodos () ; } private EntityManager getEntityManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } // GETTERS E SETTERS }
Cdigo Java 13.10: CarroBean.java

Acesse a pgina http://localhost:8 8 /K19-Integracao-JSF-JPA/carros.xhtml e depois verique no console do Eclipse quantas vezes o repositrio de carros foi acionado.
17

Altere o comportamento do managed bean carroBean para diminuir o nmero de chamadas ao repositrio de carros.
18

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

package managedbeans ; @ManagedBean public class CarroBean { private Carro carro = new Carro () ; private List < Carro > carros ; public void adicionaCarro () { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; repository . adiciona ( this . carro ) ; this . carro = new Carro () ; this . carros = null ;

196

www.k19.com.br

197
17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 } public List < Carro > getCarros () { if ( this . carros == null ) { EntityManager manager = this . getEntityManager () ; CarroRepository repository = new CarroRepository ( manager ) ; System . out . println ( " CHAMANDO O REPOSITORIO " ) ; this . carros = repository . buscaTodos () ; } return this . carros ; }

I NTEGRAO JSF E JPA

private EntityManager getEntityManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; EntityManager manager = ( EntityManager ) request . getAttribute ( " EntityManager " ) ; return manager ; } // GETTERS E SETTERS }
Cdigo Java 13.11: CarroBean.java

19 Acesse novamente a pgina http://localhost:8 8 /K19-Integracao-JSF-JPA/carros.xhtml e depois verique no console do Eclipse quantas vezes o repositrio de carros foi acionado.

www.k19.com.br

197

I NTEGRAO JSF E JPA

198

198

www.k19.com.br

APNDICE
Cdigo Java A.1: AutenticadorBean.java

AUTENTICAO

Neste captulo, apresentaremos uma maneira de implementar o processo de autenticao dos usurios de uma aplicao JSF.

Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Autenticacao seguindo os passos vistos no exerccio do Captulo 5.
1

Por simplicidade, utilizaremos um atributo de um managed bean para armazenar os usurios da aplicao e suas respectivas senhas. A implementao que ser apresentada a seguir pode ser alterada para que esses dados sejam armazenadas em um arquivo ou em um banco de dados.
2

Importante
Por motivos de segurana, as senhas dos usurios no devem ser armazenadas literalmente. Ao invs disso, as senhas dos usurios devem passar por um processo de transformao (criptograa) antes de serem armazenadas. Quando um usurio tenta logar no sistema, ele digita o seu nome de usurio e sua senha. Para garantir que o usurio tenha acesso ao sistema, precisamos vericar se o nome de usurio digitado est cadastrado no sistema e se sua senha est correta. Como ns no armazenamos a senha do usurio, o que fazemos aplicar a mesma transformao feita anteriormente e comparar o valor obtido com aquele armazenado no servidor. Se esses valores forem iguais, ento permitimos que o usurio acesse o sistema. Caso contrrio, o acesso ao sistema negado.

Crie uma classe chamada AutenticadorBean em um pacote chamado managedbeans no projeto K19-Autenticacao com o seguinte contedo:
1 2 3 4 5 6 @ManagedBean public class AutenticadorBean { private static Map < String , String > mapa = new HashMap < String , String >() ; }

Acrescente alguns usurios e suas respectivas senhas no atributo mapa.


@ManagedBean public class AutenticadorBean { private static Map < String , String > mapa = new HashMap < String , String >() ;

1 2 3 4

www.k19.com.br

199

AUTENTICAO
5 6 7 8 9 1 11 12

200

static { AutenticadorBean . mapa . put ( " k19 " , " k19 " ) ; AutenticadorBean . mapa . put ( " jonas . hirata " , " jonas . hirata " ) ; AutenticadorBean . mapa . put ( " marcelo . martins " , " marcelo . martins " ) ; AutenticadorBean . mapa . put ( " rafael . cosentino " , " rafael . cosentino " ) ; } }
Cdigo Java A.2: AutenticadorBean.java

Crie propriedades para armazenar os dados enviados atravs do formulrio de identicao, um mtodo para implementar o processo de autenticao e outro mtodo para registrar a sada do usurio.
4

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

@ManagedBean public class AutenticadorBean { private static Map < String , String > mapa = new HashMap < String , String >() ; private String usuario ; private String senha ; static { AutenticadorBean . mapa . put ( " k19 " , " k19 " ) ; AutenticadorBean . mapa . put ( " jonas . hirata " , " jonas . hirata " ) ; AutenticadorBean . mapa . put ( " marcelo . martins " , " marcelo . martins " ) ; AutenticadorBean . mapa . put ( " rafael . cosentino " , " rafael . cosentino " ) ; } public String autentica () { FacesContext fc = FacesContext . getCurrentInstance () ; if ( AutenticadorBean . mapa . containsKey ( this . usuario ) && AutenticadorBean . mapa . get ( this . usuario ) . equals ( this . senha ) ) { ExternalContext ec = fc . getExternalContext () ; HttpSession session = ( HttpSession ) ec . getSession ( false ) ; session . setAttribute ( " usuario " , this . usuario ) ; return " / home " ; } else { FacesMessage fm = new FacesMessage ( " usurio e / ou senha invlidos " ) ; fm . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; fc . addMessage ( null , fm ) ; return " / login " ; } } public String registraSaida () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpSession session = ( HttpSession ) ec . getSession ( false ) ; session . removeAttribute ( " usuario " ) ; return " / login " ; } // GETTERS E SETTERS }
Cdigo Java A.3: AutenticadorBean.java

O mtodo autentica() verica se os dados enviados pelo formulrio de autenticao esto cadastrados no mapa. Se esses dados estiverem cadastrados, registramos o nome do usurio na sesso
200
www.k19.com.br

201

AUTENTICAO

HTTP e navegamos para a pgina principal da aplicao. Caso contrrio, adicionamos no contexto do processamento da requisio uma mensagem de erro e navegamos para a pgina do formulrio de autenticao. O mtodo registraSaida() simplesmente retira da sesso HTTP o nome do usurio anteriormente autenticado.
5

Para testar, crie a tela do formulrio de autenticao e a tela principal da aplicao.


<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : messages / > <h : form > <h : outputLabel value = " Usurio : " for = " campo - usuario " / > <h : inputText value = " #{ autenticadorBean . usuario } " id = " campo - usuario " / > <h : outputLabel value = " Senha : " for = " campo - senha " / > <h : inputSecret value = " #{ autenticadorBean . senha } " id = " campo - senha " / > <h : commandButton value = " Entrar " action = " #{ autenticadorBean . autentica } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML A.1: login.xhtml

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

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > Ol #{ sessionScope . usuario }! Voc est logado . <h : form > <h : commandLink value = " Sair " action = " #{ autenticadorBean . registraSaida } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML A.2: home.xhtml

Na tela principal da aplicao, utilizamos a varivel sessionScope para recuperar o nome do usurio autenticado.
6 7

Teste a aplicao acessando http://localhost:8 8 /K19-Autenticacao/login.xhtml Somente usurios autenticados podem acessar a pgina principal da aplicao. Para controlar
www.k19.com.br

201

AUTENTICAO

202

o acesso s pginas da aplicao, implemente um ltro para interceptar todas as requisies HTTP direcionadas Faces Servlet. Crie uma classe chamada ControleDeAcesso em um pacote chamado filtros no projeto K19-Autenticacao com o seguinte contedo:
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 @WebFilter ( servletNames ={ " Faces Servlet " }) public class ControleDeAcesso 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 ( " usuario " ) != 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 () { } }

Cdigo Java A.4: ControleDeAcesso.java

A anotao @WebServlet registra o ltro no Web Container. O atributo servletNames utilizado para denir quais servlets sero interceptadas pelo ltro. O mtodo doFilter() chamado toda vez que uma requisio HTTP servlet Faces Servlet realizada. Esse mtodo verica se existe um usurio registrado na sesso HTTP ou se a pgina requisitada a do formulrio de autenticao. Se uma dessas condies for satisfeita, o ltro permite que o uxo prossiga para a Faces Servlet. Caso contrrio, ele redireciona o usurio para a pgina do formulrio de autenticao. Reinicie a aplicao e tente acessar diretamente a pgina principal da aplicao acessando http://localhost:8 8 /K19-Autenticacao/home.xhtml. Observe que a aplicao redireciona o navegador para a pgina do formulrio de autenticao.
8

202

www.k19.com.br

203

AUTENTICAO

www.k19.com.br

L HTMscript a Jav SS C

Requisio HTTP

Resposta HTTP

Filtro de Controle de Acesso

Faces Servlet

Restore View

Apply Request Values

Process Validation

Update Model

Ivoke Application

Render Response

MANAGED BEANS

CONTROLE MODELO VISO

TELAS ENTIDADES TEMPLATES

REPOSITRIOS

TELAS PARCIAIS

Figura A.1: Filtro e Managed Bean para implementar o controle de autenticao

www.k19.com.br

203

AUTENTICAO

204

204

www.k19.com.br

APNDICE

PGINAS DE E RRO

Por padro, quando determinados erros ocorrem no processamento de uma requisio, pginas com informaes tcnicas sobre o problema que ocorreu so geradas e enviadas para os usurios. Na fase de desenvolvimento, essas pginas so teis para os desenvolvedores. Por outro lado, na fase de produo, essas pginas podem confundir os usurios da aplicao e revelar a estrutura do sistema, expondo possveis falhas de segurana.
Caused by: java.lang.IllegalArgumentException: id to load is required for loading at org.hibernate.event.LoadEvent.<init>(LoadEvent.java:89) at org.hibernate.event.LoadEvent.<init>(LoadEvent.java:61) at org.hibernate.impl.SessionImpl.get(SessionImpl.java:994) at org.hibernate.impl.SessionImpl.get(SessionImpl.java:990) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:554) at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:529) at model.repositories.TimeRepository.procura(TimeRepository.java:38) at managedbeans.JogadorBean.adiciona(JogadorBean.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.el.parser.AstValue.invoke(AstValue.java:234) at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297) at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) ... 41 more

Hi Hi Hi!!

Figura B.1: Expondo possveis falhas de segurana

Neste captulo, apresentaremos uma maneira de personalizar as pginas de erro da aplicao.

Exerccios de Fixao
Crie um projeto do tipo Dynamic Web Project chamado K19-Paginas-de-Erro seguindo os passos vistos no exerccio do Captulo 5.
1

Criaremos uma pgina de erro padro. Adicione na pasta WebContent um arquivo XHTML com o seguinte contedo.
2

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Ocorreu um erro interno no sistema . </ h1 > < h3 > Tente novamente em alguns instantes . </ h3 >

www.k19.com.br

205

PGINAS DE E RRO
16 17 </ h : body > </ html >
Cdigo XHTML B.1: pagina-de-erro.xhtml

206

Criaremos uma pgina com um boto que sempre produzir um erro ao ser clicado. Adicione na pasta WebContent um arquivo XHTML com o seguinte contedo.
3

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : commandButton value = " Gera Erro " action = " #{ erroBean . geraErro } " / > </ h : form > </ h : body > </ html >
Cdigo XHTML B.2: gerador-de-erro.xhtml

Crie um managed bean que provoque propositalmente um erro. Adicione em um pacote chamado managedbeans uma classe com o seguinte cdigo:
4

1 2 3 4 5 6

@ManagedBean public class ErroBean { public void geraErro () { System . out . println (1 / ) ; } }
Cdigo Java B.1: AutenticadorBean.java

Teste a aplicao acessando o seguinte endereo:

http://localhost:8 8 /K19-Paginas-de-Erro/gerador-de-erro.xhtml
Congure o Web Container para direcionar todas as exceptions para a pgina de erro padro. Adicione o seguinte cdigo no arquivo web.xml.
6

1 2 3 4 5 6

... < error - page > < exception - type > java . lang . Exception </ exception - type > < location >/ pagina - de - erro . xhtml </ location > </ error - page > ...
Cdigo XML B.1: web.xml

Teste a aplicao novamente acessando o seguinte endereo:

http://localhost:8 8 /K19-Paginas-de-Erro/gerador-de-erro.xhtml

206

www.k19.com.br

APNDICE

P ROJETO F UTEBOL K19

Para consolidar o conhecimento obtido durante o treinamento, desenvolveremos uma aplicao completa para auxiliar no gerenciamento de um campeonato de futebol. Essa aplicao dever permitir que os usurios possam cadastrar novos times e jogadores, bem como list-los, alter-los e remov-los. Essa aplicao tambm dever possibilitar que jogadores sejam associados a times de futebol, respeitando-se a restrio de que cada jogador deve pertencer a no mximo um time de futebol.

Integrao JSF e JPA


Criaremos uma aplicao web Java com JSF e adicionaremos os recursos do JPA nessa aplicao como foi visto no Captulo 13.

Exerccios de Fixao
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 a pasta glassfishv3/glassfish/lib tambm da sua rea de Trabalho. OBS: O Glasssh deve ser reiniciado para reconhecer o driver JDBC do MySQL.
1

Crie um projeto do tipo Dynamic Web Project chamado K19-Futebol seguindo os passos vistos no exerccio do Captulo 5.
2 3 4

Adicione uma pasta chamada META-INF na pasta src do projeto K19-Futebol. Congure o JPA adicionando o arquivo persistence.xml na pasta META-INF.
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 - Futebol - PU " 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 = " 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 " / >

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

www.k19.com.br

207

P ROJETO F UTEBOL K19


19 2 21 22 23

208

< property name = " javax . persistence . jdbc . url " value = " jdbc:mysql: // localhost:33 6 / K19 - Futebol - DB " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML C.1: persistence.xml

5 Abra um terminal; entre no cliente do MySQL Server; apague se existir a base de dados K19-Futebol-DB; e crie uma base de dados nova chamada K19-Futebol-DB.
k19@k19 -11:~/ rafael$ mysql -u root -p Enter password : Welcome to the MySQL monitor . Commands end with ; or \ g . Your MySQL connection id is 36 Server version : 5.1.58 -1 ubuntu1 ( Ubuntu ) Copyright ( c ) 2 , 2 1 , Oracle and / or its affiliates . All rights reserved . This software comes with ABSOLUTELY NO WARRANTY . This is free software , and you are welcome to modify and redistribute it under the GPL v2 license Type help ; or \h for help . Type \c to clear the current input statement . mysql > DROP DATABASE IF EXISTS K19 - Futebol - DB ; Query OK , rows affected , 1 warning ( . sec ) mysql > CREATE DATABASE K19 - Futebol - DB ; Query OK , 1 row affected ( . 2 sec )

6 7

Crie um pacote chamado filters na pasta src do projeto K19-Futebol. No pacote filters, crie uma classe chamada JPAFilter com o seguinte contedo:
package filters ; @WebFilter ( servletNames ={ " Faces Servlet " }) public class JPAFilter implements Filter { private EntityManagerFactory factory ; @Override public void init ( FilterConfig filterConfig ) throws ServletException { this . factory = Persistence . createEntityManagerFactory ( " K19 - Futebol - PU " ) ; } @Override public void destroy () { this . factory . close () ; } @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { // CHEGADA EntityManager manager = this . factory . createEntityManager () ; request . setAttribute ( " EntityManager " , manager ) ; manager . getTransaction () . begin () ; // CHEGADA // FACES SERVLET chain . doFilter ( request , response ) ; // FACES SERVLET // SADA try { manager . getTransaction () . commit () ; } catch ( Exception e ) {

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

208

www.k19.com.br

209
36 37 38 39 4 41 42 manager . getTransaction () . rollback () ; } finally { manager . close () ; } // SADA } }
Cdigo Java C.1: JPAFilter.java

P ROJETO F UTEBOL K19

Modelo
Na camada de modelo da nossa aplicao, implementaremos duas entidades: Jogador e Time. Alm disso, criaremos os respectivos repositrios para implementar as diversas operaes relacionadas persistncia dessas duas entidades.

Exerccios de Fixao
8 9

Na pasta src do projeto K19-Futebol, crie um pacote chamado model.entities. No pacote model.entities, crie duas classes para modelar os times e jogadores.
package model . entities ; @Entity public class Time { @Id @GeneratedValue private Long id ; private String nome ; private String tecnico ; // GETTERS E SETTERS }
Cdigo Java C.2: Time.java

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

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

package model . entities ; @Entity public class Jogador { @Id @GeneratedValue private Long id ; private String nome ; private String posicao ; private Calendar dataDeNascimento = new GregorianCalendar () ; @ManyToOne private Time time ; // GETTERS E SETTERS }

www.k19.com.br

209

P ROJETO F UTEBOL K19

210

Cdigo Java C.3: Jogador.java

10 11

Crie um pacote chamado model.repositories na pasta src. No pacote model.repositories, implemente as classes JogadorRepository e TimeRepository.
package model . repositories ; public class JogadorRepository { private EntityManager manager ; public JogadorRepository ( EntityManager manager ) { this . manager = manager ; } public void adiciona ( Jogador jogador ) { this . manager . persist ( jogador ) ; } public void remove ( Long id ) { Jogador jogador = this . procura ( id ) ; this . manager . remove ( jogador ) ; } public Jogador atualiza ( Jogador jogador ) { return this . manager . merge ( jogador ) ; } public Jogador procura ( Long id ) { return this . manager . find ( Jogador . class , id ) ; } public List < Jogador > getLista () { Query query = this . manager . createQuery ( " select x from Jogador x " ) ; return query . getResultList () ; } }
Cdigo Java C.4: JogadorRepository.java

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

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

package model . repositories ; public class TimeRepository { private EntityManager manager ; public TimeRepository ( EntityManager manager ) { this . manager = manager ; } public void adiciona ( Time time ) { this . manager . persist ( time ) ; } public void remove ( Long id ) { Time time = this . procura ( id ) ; Query query = this . manager . createQuery ( " select x from Jogador x " ) ; List < Jogador > jogadores = query . getResultList () ; for ( Jogador jogador : jogadores ) { jogador . setTime ( null ) ; } this . manager . remove ( time ) ; }

210

www.k19.com.br

211
25 26 27 28 29 3 31 32 33 34 35 36 37 public Time atualiza ( Time time ) { return this . manager . merge ( time ) ; } public Time procura ( Long id ) { return this . manager . find ( Time . class , id ) ; } public List < Time > getLista () { Query query = this . manager . createQuery ( " select x from Time x " ) ; return query . getResultList () ; } }
Cdigo Java C.5: TimeRepository.java

P ROJETO F UTEBOL K19

Managed Beans
Na camada de controle, implementaremos managed beans para controlar as operaes relacionadas s entidades Jogador e Time.

Exerccios de Fixao
12 13

Na pasta src, crie um pacote chamado managedbeans. No pacote managedbeans, implemente a classe TimeBean.
package managedbeans ; @ManagedBean public class TimeBean { private Time time = new Time () ; private List < Time > times ; public void adiciona () { EntityManager manager = this . getManager () ; TimeRepository repository = new TimeRepository ( manager ) ; if ( this . time . getId () == null ) { repository . adiciona ( this . time ) ; } else { repository . atualiza ( this . time ) ; } this . time = new Time () ; this . times = null ; } public void preparaAlteracao () { Map < String , String > params = FacesContext . getCurrentInstance () . getExternalContext () . getRequestParameterMap () ; Long id = Long . parseLong ( params . get ( " id " ) ) ; EntityManager manager = this . getManager () ; TimeRepository repository = new TimeRepository ( manager ) ; this . time = repository . procura ( id ) ; } public void remove () { Map < String , String > params = FacesContext . getCurrentInstance () . getExternalContext () . www.k19.com.br

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

211

P ROJETO F UTEBOL K19


getRequestParameterMap () ; Long id = Long . parseLong ( params . get ( " id " ) ) ; EntityManager manager = this . getManager () ; TimeRepository repository = new TimeRepository ( manager ) ; repository . remove ( id ) ; this . times = null ; } public List < Time > getTimes () { if ( this . times == null ) { EntityManager manager = this . getManager () ; TimeRepository repository = new TimeRepository ( manager ) ; this . times = repository . getLista () ; } return this . times ; } private EntityManager getManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; return ( EntityManager ) request . getAttribute ( " EntityManager " ) ; } // GETTERS E SETTERS }
Cdigo Java C.6: TimeBean.java

212

33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57

14

No pacote managedbeans, implemente a classe JogadorBean.


package managedbeans ; @ManagedBean public class JogadorBean { private Jogador jogador = new Jogador () ; private Long timeID ; private List < Jogador > jogadores ; public void adiciona () { EntityManager manager = this . getManager () ; TimeRepository timeRepository = new TimeRepository ( manager ) ; JogadorRepository jogadorRepository = new JogadorRepository ( manager ) ; if ( this . timeID != null ) { Time time = timeRepository . procura ( this . timeID ) ; this . jogador . setTime ( time ) ; } if ( this . jogador . getId () == null ) { jogadorRepository . adiciona ( this . jogador ) ; } else { jogadorRepository . atualiza ( this . jogador ) ; } this . jogador = new Jogador () ; this . jogadores = null ; } public void preparaAlteracao () { Map < String , String > params = FacesContext . getCurrentInstance () . getExternalContext () . getRequestParameterMap () ; Long id = Long . parseLong ( params . get ( " id " ) ) ; EntityManager manager = this . getManager () ;

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

212

www.k19.com.br

213
38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 JogadorRepository repository = new JogadorRepository ( manager ) ; this . jogador = repository . procura ( id ) ; }

P ROJETO F UTEBOL K19

public void remove () { Map < String , String > params = FacesContext . getCurrentInstance () . getExternalContext () . getRequestParameterMap () ; Long id = Long . parseLong ( params . get ( " id " ) ) ; EntityManager manager = this . getManager () ; JogadorRepository repository = new JogadorRepository ( manager ) ; repository . remove ( id ) ; this . jogadores = null ; } public List < Jogador > getJogadores () { if ( this . jogadores == null ) { EntityManager manager = this . getManager () ; JogadorRepository repository = new JogadorRepository ( manager ) ; this . jogadores = repository . getLista () ; } return this . jogadores ; } private EntityManager getManager () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpServletRequest request = ( HttpServletRequest ) ec . getRequest () ; return ( EntityManager ) request . getAttribute ( " EntityManager " ) ; } // GETTERS E SETTERS }
Cdigo Java C.7: JogadorBean.java

Telas
Vamos implementar a camada de apresentao da nossa aplicao. Criaremos algumas telas usando templates e telas parciais.

Exerccios de Fixao
Na pasta WebContent, crie um diretrio chamado resources. Nesse diretrio, crie diretrios chamados css e imagens.
15 16

No diretrio resources/css, crie um arquivo chamado style.css com o seguinte contedo:


body { font : 18 px Arial ; margin : ; background - color :# EEEEEE ; } h1 { margin : ; padding : 16 px ; color : # ; font : bold 4 px Arial ; }

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

www.k19.com.br

213

P ROJETO F UTEBOL K19


13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 72 73

214

h2 { font : bold 24 px Arial ; color : #595959; } a { color : #3 a34c3 ; text - decoration : none ; } a : hover { text - decoration : underline ; } . dados { border - collapse : collapse ; } . dados td ,. dados th { border : 1 px solid # c6 ; padding : 3 px 7 px 2 px 7 px ; } . dados th { padding - top : 5 px ; padding - bottom : 4 px ; background - color : #156 bbd ; color : # ffffff ; } . dados tr . impar td { color : # ; background - color : # d4d4d9 ; } . dados tr . par td { color : # ; background - color : # f6f6fa ; } input { font - size : 16 px ; border : 1 px solid # c6 ; background - color : # f6f6fa ; } # header { color : # FFFFFF ; background - color : #252525; padding : 1 px px 28 px 1 px ; } # header a { color : # FFFFFF ; font : bold 24 px Arial ; } # conteudo { margin : px }

px 5 px 1 px ;

Cdigo CSS C.1: style.css

17

Copie o arquivo k19-logo.png da pasta K19-Arquivos da rea de Trabalho para a pasta resources/imagens.
www.k19.com.br

214

215

P ROJETO F UTEBOL K19

18 19

Na pasta WEB-INF, crie um diretrio chamado templates.

No diretrio WEB-INF/templates, crie um arquivo chamado template.xhtml com o seguinte contedo:


1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Futebol </ title > </ h : head > <h : body > <h : outputStylesheet library = " css " name = " style . css " / > < div id = " header " > <h : form style = " float : left ; " > <h : link value = " Times " outcome = " times " / > & nbsp ; <h : link value = " Jogadores " outcome = " jogadores " / > </ h : form > <h : graphicImage library = " imagens " name = " k19 - logo . png " style = " float : right ; " / > < div style = " clear : both " > </ div > </ div > < div id = " conteudo " > < ui : insert name = " conteudo " > Espao para o contedo da tela </ ui : insert > </ div > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML C.1: template.xhtml

20

Na pasta WebContent, crie um arquivo chamado times.xhtml com o contedo abaixo.


< ui : composition template = " / WEB - INF / templates / template . xhtml " 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 : define name = " conteudo " > < h1 > Times </ h1 > <h : form > < ui : include src = " / formulario - novo - time . xhtml " / > < ui : include src = " / lista - de - times . xhtml " / > </ h : form > </ ui : define > </ ui : composition >
Cdigo XHTML C.2: times.xhtml

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

www.k19.com.br

215

P ROJETO F UTEBOL K19


21

216

Tambm na pasta WebContent, crie as telas parciais denidas pelos arquivos formulario-novo-time.xhtml e lista-de-times.xhtml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 < ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : inputHidden value = " #{ timeBean . time . id } " / > <h : panelGrid columns = " 3 " > <h : outputLabel value = " Nome : " for = " nome " / > <h : inputText id = " nome " required = " true " requiredMessage = " O nome do time obrigatrio " value = " #{ timeBean . time . nome } " > </ h : inputText > <h : message for = " nome " / > <h : outputLabel value = " Tcnico : " for = " tecnico " / > <h : inputText id = " tecnico " required = " true " requiredMessage = " O nome do tcnico obrigatrio " value = " #{ timeBean . time . tecnico } " > </ h : inputText > <h : message for = " tecnico " / > <h : commandButton value = " Cadastrar " > <f : ajax event = " click " execute = " @form " listener = " #{ timeBean . adiciona } " render = " @all " / > </ h : commandButton > </ h : panelGrid > </ ui : composition >
Cdigo XHTML C.3: formulario-novo-time.xhtml

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

< ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : panelGroup rendered = " #{ not empty timeBean . times } " > < h2 > Lista de Times </ h2 > <h : dataTable id = " tabela " value = " #{ timeBean . times } " var = " time " styleClass = " dados " rowClasses = " par , impar " > <h : column > <f : facet name = " header " > <h : outputText value = " Id " / > </ f : facet > #{ time . id } </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Nome " / > </ f : facet >

216

www.k19.com.br

217
28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 #{ time . nome } </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Tcnico " / > </ f : facet > #{ time . tecnico } </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Alterar " / > </ f : facet > <f : ajax event = " click " render = " @form " listener = " #{ timeBean . preparaAlteracao } " > <h : commandLink > <f : param name = " id " value = " #{ time . id } " / > Alterar </ h : commandLink > </ f : ajax > </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Remover " / > </ f : facet > <f : ajax event = " click " render = " @form " listener = " #{ timeBean . remove } " > <h : commandLink > <f : param name = " id " value = " #{ time . id } " / > Remover </ h : commandLink > </ f : ajax > </ h : column > </ h : dataTable > </ h : panelGroup > </ ui : composition >
Cdigo XHTML C.4: lista-de-times.xhtml

P ROJETO F UTEBOL K19

22

Na pasta WebContent, crie um arquivo chamado jogadores.xhtml com o contedo abaixo.


< ui : composition template = " / WEB - INF / templates / template . xhtml " 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 : define name = " conteudo " > < h1 > Jogadores </ h1 > <h : form > < ui : include src = " / formulario - novo - jogador . xhtml " / > < ui : include src = " / lista - de - jogadores . xhtml " / > </ h : form > </ ui : define > </ ui : composition >
Cdigo XHTML C.5: jogadores.xhtml

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

www.k19.com.br

217

P ROJETO F UTEBOL K19


23

218

Ainda na pasta WebContent, crie as telas parciais denidas pelos arquivos formulario-novo-jogador.xhtml e lista-de-jogadores.xhtml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 < ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : inputHidden value = " #{ jogadorBean . jogador . id } " / > <h : panelGrid columns = " 3 " > <h : outputLabel value = " Nome : " for = " jogador - nome " / > <h : inputText id = " jogador - nome " required = " true " requiredMessage = " O nome do jogador obrigatrio " value = " #{ jogadorBean . jogador . nome } " > </ h : inputText > <h : message for = " jogador - nome " / > <h : outputLabel value = " Posio : " for = " jogador - posicao " / > <h : inputText id = " jogador - posicao " required = " true " requiredMessage = " A posio do jogador deve ser especificada " value = " #{ jogadorBean . jogador . posicao } " > </ h : inputText > <h : message for = " jogador - posicao " / > <h : outputLabel value = " Data de Nascimento : " for = " jogador - nascimento " / > <h : inputText id = " jogador - nascimento " required = " true " requiredMessage = " Informe a data de nascimento do jogador " value = " #{ jogadorBean . jogador . dataDeNascimento . time } " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : inputText > <h : message for = " jogador - nascimento " / > <h : outputLabel value = " Time : " for = " jogador - time " / > <h : selectOneMenu id = " jogador - time " value = " #{ jogadorBean . timeID } " > <f : selectItems value = " #{ timeBean . times } " var = " time " itemLabel = " #{ time . nome } " itemValue = " #{ time . id } " / > </ h : selectOneMenu > <h : message for = " jogador - time " / > <h : commandButton value = " Cadastrar " styleClass = " botao - formulario " > <f : ajax event = " click " execute = " @form " listener = " #{ jogadorBean . adiciona } " render = " @form " / > </ h : commandButton > </ h : panelGrid > </ ui : composition >
Cdigo XHTML C.6: formulario-novo-jogador.xhtml

1 2 3 4 5 6 7

< ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : panelGroup rendered = " #{ not empty jogadorBean . jogadores } " >

218

www.k19.com.br

219
8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 72 73 74 75 76 77 < h2 > Lista de Jogadores </ h2 > <h : dataTable id = " tabela " value = " #{ jogadorBean . jogadores } " var = " jogador " styleClass = " dados " rowClasses = " par , impar " > <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 = " Data de Nascimento " / > </ f : facet > <h : outputText value = " #{ jogador . dataDeNascimento . time } " > <f : convertDateTime pattern = " dd / MM / yyyy " / > </ h : outputText > </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Time " / > </ f : facet > #{ jogador . time . nome } </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Alterar " / > </ f : facet > <f : ajax event = " click " render = " @form " listener = " #{ jogadorBean . preparaAlteracao } " > <h : commandLink > <f : param name = " id " value = " #{ jogador . id } " / > Alterar </ h : commandLink > </ f : ajax > </ h : column > <h : column > <f : facet name = " header " > <h : outputText value = " Remover " / > </ f : facet > <f : ajax event = " click " render = " @form "

P ROJETO F UTEBOL K19

www.k19.com.br

219

P ROJETO F UTEBOL K19


78 79 8 81 82 83 84 85 86 87 listener = " #{ jogadorBean . remove } " > <h : commandLink > <f : param name = " id " value = " #{ jogador . id } " / > Remover </ h : commandLink > </ f : ajax > </ h : column > </ h : dataTable > </ h : panelGroup > </ ui : composition >
Cdigo XHTML C.7: lista-de-jogadores.xhtml

220

24

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Futebol/times.xhtml

Autenticao
Vamos acrescentar um controle de segurana nossa aplicao como vimos no Apndice A.
25

Na pasta src/managedbeans, crie um managed bean de autenticao.


package managedbeans ; @ManagedBean public class AutenticadorBean { private static Map < String , String > mapa = new HashMap < String , String >() ; private String usuario ; private String senha ; static { AutenticadorBean . mapa . put ( " k19 " , " k19 " ) ; AutenticadorBean . mapa . put ( " jonas . hirata " , " jonas . hirata " ) ; AutenticadorBean . mapa . put ( " marcelo . martins " , " marcelo . martins " ) ; AutenticadorBean . mapa . put ( " rafael . cosentino " , " rafael . cosentino " ) ; } public String autentica () { FacesContext fc = FacesContext . getCurrentInstance () ; if ( AutenticadorBean . mapa . containsKey ( this . usuario ) && AutenticadorBean . mapa . get ( this . usuario ) . equals ( this . senha ) ) { ExternalContext ec = fc . getExternalContext () ; HttpSession session = ( HttpSession ) ec . getSession ( false ) ; session . setAttribute ( " usuario " , this . usuario ) ; return " / times " ; } else { FacesMessage fm = new FacesMessage ( " usurio e / ou senha invlidos " ) ; fm . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; fc . addMessage ( null , fm ) ; return " / login " ; } } public String registraSaida () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpSession session = ( HttpSession ) ec . getSession ( false ) ;

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

220

www.k19.com.br

221
42 43 44 45 46 47 48 session . removeAttribute ( " usuario " ) ; return " / login " ; } // GETTERS E SETTERS }
Cdigo Java C.8: AutenticadorBean.java

P ROJETO F UTEBOL K19

26

Na pasta filters, implemente um ltro para o controle de acesso.


package filters ; @WebFilter ( servletNames ={ " Faces Servlet " }) public class ControleDeAcesso 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 ( " usuario " ) != 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 () { } }
Cdigo Java C.9: ControleDeAcesso.java

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

Na pasta WebContent, crie um arquivo chamado login.xhtml e implemente o formulrio de autenticao.


27

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

< ui : composition template = " / WEB - INF / templates / template . xhtml " 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 : define name = " conteudo " > <p > Preencha o formulrio abaixo para entrar no sistema . </ p > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Usurio : " for = " campo - usuario " / > <h : inputText value = " #{ autenticadorBean . usuario } " id = " campo - usuario " / > <h : outputLabel value = " Senha : " for = " campo - senha " / > <h : inputSecret value = " #{ autenticadorBean . senha } " id = " campo - senha " / > </ h : panelGrid > <h : commandButton value = " Entrar " action = " #{ autenticadorBean . autentica } " / >

www.k19.com.br

221

P ROJETO F UTEBOL K19


19 2 21 22 23 </ h : form > <h : messages / > </ ui : define > </ ui : composition >
Cdigo XHTML C.8: login.xhtml

222

No arquivo template.xhtml, acrescente um link para o usurio fazer logout. O menu de navegao deve ser exibido apenas se o usurio estiver logado.
28

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

<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > K19 Futebol </ title > </ h : head > <h : body > <h : outputStylesheet library = " css " name = " style . css " / > < div id = " header " > <h : form style = " float : left ; " rendered = " #{ not empty sessionScope . usuario } " > <h : link value = " Times " outcome = " times " / > & nbsp ; <h : link value = " Jogadores " outcome = " jogadores " / > & nbsp ; <h : commandLink value = " Logout " action = " #{ autenticadorBean . registraSaida } " / > </ h : form > <h : graphicImage library = " imagens " name = " k19 - logo . png " style = " float : right ; " / > < div style = " clear : both " > </ div > </ div > < div id = " conteudo " > < ui : insert name = " conteudo " > Espao para o contedo da tela </ ui : insert > </ div > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML C.9: template.xhtml

29

Acessa a aplicao no endereo:

http://localhost:8 8 /K19-Futebol/login.xhtml

222

www.k19.com.br

APNDICE
Cdigo Java 2.7: InsereLivros.java

R ESPOSTAS

Resposta do Complementar 2.1


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

public class InsereLivros { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; System . out . println ( " Digite o ttulo do livro : " ) ; String titulo = entrada . nextLine () ; System . out . println ( " Digite o preo do livro : " ) ; String preco = entrada . nextLine () ; System . out . println ( " Digite o id da editora do livro : " ) ; String id = entrada . nextLine () ; String sql = " INSERT INTO Livro ( titulo , preco , editora_id ) " + " VALUES ( " + titulo + " , " + preco + " , " + id + " ) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }

Resposta do Complementar 2.3

1 2

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

www.k19.com.br

223

R ESPOSTAS
3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 import java . sql . PreparedStatement ; import java . util . Scanner ; public class InsereLivros { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ; System . out . println ( " Digite o ttulo do livro : " ) ; String titulo = entrada . nextLine () ; System . out . println ( " Digite o preo do livro : " ) ; String preco = entrada . nextLine () ; System . out . println ( " Digite o id da editora do livro : " ) ; String id = entrada . nextLine () ; String sql = " INSERT INTO Livro ( titulo , preco , editora_id ) " + " VALUES (? , ? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , titulo ) ; comando . setString (2 , preco ) ; comando . setString (3 , id ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.12: InsereLivros.java

224

Resposta do Complementar 2.5

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

import import import import

java . sql . Connection ; java . sql . DriverManager ; java . sql . PreparedStatement ; java . sql . ResultSet ;

public class ListaLivros { public static void main ( String [] args ) { String stringDeConexao = " jdbc : mysql :// localhost :33 6/ livraria " ; String usuario = " root " ; String senha = " root " ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = DriverManager . getConnection ( stringDeConexao , usuario , senha ) ;

224

www.k19.com.br

225
17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 String sql = " SELECT * FROM Livro ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; ResultSet resultado = comando . executeQuery () ; System . out . println ( " Resultados encontrados : \ n " ) ; while ( resultado . next () ) { System . out . printf ( " ID : % d - TTULO : % s - PREO : % f - EDITORA : % d \ n " , resultado . getInt ( " id " ) , resultado . getString ( " titulo " ) , resultado . getDouble ( " preco " ) , resultado . getInt ( " editora_id " ) ) ; } System . out . println ( " \ nFechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.18: ListaLivros.java

R ESPOSTAS

Resposta do Complementar 2.6

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

import java . sql . Connection ; import java . sql . PreparedStatement ; import java . util . Scanner ; public class InsereLivros { public static void main ( String [] args ) { Scanner entrada = new Scanner ( System . in ) ; try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; System . out . println ( " Digite o ttulo do livro : " ) ; String titulo = entrada . nextLine () ; System . out . println ( " Digite o preo do livro : " ) ; String preco = entrada . nextLine () ; System . out . println ( " Digite o id da editora do livro : " ) ; String id = entrada . nextLine () ; String sql = " INSERT INTO Livro ( titulo , preco , editora_id ) " + " VALUES (? , ? , ?) " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; comando . setString (1 , titulo ) ; comando . setString (2 , preco ) ; comando . setString (3 , id ) ; System . out . println ( " Executando comando ... " ) ; comando . execute () ; System . out . println ( " Fechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ;

www.k19.com.br

225

R ESPOSTAS
38 39 4 } } }
Cdigo Java 2.23: InsereLivros.java

226

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

import java . sql . Connection ; import java . sql . PreparedStatement ; import java . sql . ResultSet ; public class ListaLivros { public static void main ( String [] args ) { try { System . out . println ( " Abrindo conexo ... " ) ; Connection conexao = ConnectionFactory . createConnection () ; String sql = " SELECT * FROM Livro ; " ; PreparedStatement comando = conexao . prepareStatement ( sql ) ; System . out . println ( " Executando comando ... " ) ; ResultSet resultado = comando . executeQuery () ; System . out . println ( " Resultados encontrados : \ n " ) ; while ( resultado . next () ) { System . out . printf ( " ID : % d - TTULO : % s - PREO : % f - EDITORA : % d \ n " , resultado . getInt ( " id " ) , resultado . getString ( " titulo " ) , resultado . getDouble ( " preco " ) , resultado . getInt ( " editora_id " ) ) ; } System . out . println ( " \ nFechando conexo ... " ) ; conexao . close () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
Cdigo Java 2.24: ListaLivros.java

Resposta do Complementar 6.1 No diretrio src do projeto K19-Componentes-Visuais, crie uma classe chamada ContatoSACBean para implementar o managed bean que dar suporte ao formulrio.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 @ManagedBean public class ContatoSACBean { private String nome ; private String email ; private String codigoDeArea ; private String numeroDoTelefone ; private Integer numeroDoPedido ; private String assunto ; private String comentario ; private Boolean sexoFeminino ; private List < String > assuntos = new ArrayList < String >() ; public ContatoSACBean () { assuntos . add ( " Entrega " ) ; assuntos . add ( " Pagamento " ) ;

226

www.k19.com.br

227
2 21 22 23 24 25 26 assuntos . add ( " Trocas ou devolues " ) ; assuntos . add ( " Dvidas gerais " ) ; assuntos . add ( " Comentrios " ) ; } // GETTERS E SETTERS }
Cdigo Java 6.8: ContatoSACBean.java

R ESPOSTAS

No diretrio WebContent, crie um arquivo chamado contato-sac.xhtml e implemente o formulrio de contato.


1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Servio de Atendimento ao Consumidor </ h1 > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ contatoSACBean . nome } " id = " campo - nome " / > <h : outputLabel value = "E - mail : " for = " campo - email " / > <h : inputText value = " #{ contatoSACBean . email } " id = " campo - email " / > <h : outputLabel value = " Telefone : " for = " campo - telefone " / > <h : panelGroup > ( <h : inputText value = " #{ contatoSACBean . codigoDeArea } " id = " campo - telefone " size = " 2 " / >) <h : inputText value = " #{ contatoSACBean . numeroDoTelefone } " / > ( DDD ) XXXX - XXXX </ h : panelGroup > <h : outputLabel value = " Sexo : " for = " campo - sexo " / > <h : selectOneRadio value = " #{ contatoSACBean . sexoFeminino } " id = " campo - sexo " > <f : selectItem itemLabel = " Feminino " itemValue = " true " / > <f : selectItem itemLabel = " Masculino " itemValue = " false " / > </ h : selectOneRadio > <h : outputLabel value = " Nmero do pedido : " for = " campo - pedido " / > <h : inputText value = " #{ contatoSACBean . numeroDoPedido } " id = " campo - pedido " / > <h : outputLabel value = " Assunto " for = " campo - assunto " / > <h : selectOneMenu value = " #{ contatoSACBean . assunto } " > <f : selectItem noSelectionOption = " true " itemLabel = " Escolha um assunto " / > <f : selectItems value = " #{ contatoSACBean . assuntos } " var = " assunto " itemLabel = " #{ assunto } " itemValue = " #{ assunto } " / > </ h : selectOneMenu > <h : outputLabel value = " Comentrio : " for = " campo - comentario " / > <h : inputTextarea value = " #{ contatoSACBean . comentario } " id = " campo - comentario " / > <h : commandButton value = " Enviar " / > </ h : panelGrid > </ h : form > </ h : body > </ html >

www.k19.com.br

227

R ESPOSTAS

228

Cdigo XHTML 6.36: contato-sac.xhtml

Acesse a aplicao em

http://localhost:8 8 /K19-Componentes-Visuais/contato-sac.xhtml
Resposta do Complementar 6.2 Primeiramente, crie a classe Produto no diretrio src do projeto K19-Componentes-Visuais.
1 2 3 4 5 6 7 8 9 1 11 public class Produto { private String nome ; private Double preco ; public Produto ( String nome , Double preco ) { this . nome = nome ; this . preco = preco ; } // GETTERS E SETTERS }
Cdigo Java 6.12: Produto.java

Agora, crie um managed bean que guardar a lista de produtos disponveis.


1 2 3 4 5 6 7 8 9 1 11 12 13 14 @ManagedBean public class ProdutosBean { private List < Produto > produtos = new ArrayList < Produto >() ; public ProdutosBean () { this . produtos . add ( new this . produtos . add ( new this . produtos . add ( new this . produtos . add ( new this . produtos . add ( new } // GETTER E SETTER }
Cdigo Java 6.13: ProdutosBean.java

Produto ( " Camiseta branca " , 29.9 ) ) ; Produto ( " Camiseta preta " , 39.99) ) ; Produto ( " Cala jeans " , 95.99) ) ; Produto ( " Gravata " , 19.9 ) ) ; Produto ( " Terno " , 289.95) ) ;

Finalmente, crie o arquivo lista-de-produtos.xhtml na pasta WebContent e implemente a listagem dos produtos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : dataTable value = " #{ produtosBean . produtos } " var = " produto " > <f : facet name = " header " > Lista de produtos </ f : facet > <h : column >

228

www.k19.com.br

229
16 17 18 19 2 21 22 23 24 25 26 27 28 <f : facet name = " header " > Nome </ f : facet > #{ produto . nome } </ h : column > <h : column > <f : facet name = " header " > Preo </ f : facet > <h : outputFormat value = " { , number , R$ . <f : param value = " #{ produto . preco } " / > </ h : outputFormat > </ h : column > </ h : dataTable > </ h : body > </ html >

R ESPOSTAS

}" >

Cdigo XHTML 6.51: lista-de-produtos.xhtml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Componentes-Visuais/lista-de-produtos.xhtml
Resposta do Complementar 6.3 Na classe Produto, adicione um atributo booleano chamado mostraPreco.
1 2 3 4 5 6 7 8 9 1 11 12 13 public class Produto { private String nome ; private Double preco ; private Boolean mostraPreco ; public Produto ( String nome , Double preco ) { this . nome = nome ; this . preco = preco ; this . mostraPreco = true ; } // GETTERS E SETTERS }
Cdigo Java 6.14: Produto.java

Modique a tabela de forma a exibir somente os preos dos produtos para os quais a propriedade

mostraPreco seja verdadeira. Use o atributo rendered para determinar quando um componente
deve ser exibido.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : dataTable value = " #{ produtosBean . produtos } " var = " produto " > <f : facet name = " header " > Lista de produtos </ f : facet > <h : column > <f : facet name = " header " > Nome </ f : facet > #{ produto . nome } </ h : column > <h : column >

www.k19.com.br

229

R ESPOSTAS
21 22 23 24 25 26 27 28 29 3 <f : facet name = " header " > Preo </ f : facet > <h : outputFormat value = " { , number , R$ . } " rendered = " #{ produto . mostraPreco } " > <f : param value = " #{ produto . preco } " / > </ h : outputFormat > <h : outputText value = " Adicione o produto ao carrinho para ver o preo " rendered = " #{! produto . mostraPreco } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 6.52: lista-de-produtos.xhtml

230

Dena como false o atributo mostraPreco de alguns produtos.


1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 @ManagedBean public class ProdutosBean { private List < Produto > produtos = new ArrayList < Produto >() ; public ProdutosBean () { this . produtos . add ( new Produto ( " Camiseta branca " , 29.9 ) ) ; this . produtos . add ( new Produto ( " Camiseta preta " , 39.99) ) ; this . produtos . add ( new Produto ( " Cala jeans " , 95.99) ) ; this . produtos . add ( new Produto ( " Gravata " , 19.9 ) ) ; Produto produto = new Produto ( " Terno " , 289.95) ; produto . setMostraPreco ( false ) ; this . produtos . add ( produto ) ; } // GETTER E SETTER }
Cdigo Java 6.15: ProdutosBean.java

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Componentes-Visuais/lista-de-produtos.xhtml
Resposta do Complementar 6.4 Essa mensagem pode ser criada no mtodo adicionaCurso() do managed bean cursosBean. Nesse mtodo, adicione uma mensagem usando o mtodo addMessage() da classe FacesContext.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 @ManagedBean @SessionScoped public class CursosBean { private List < Curso > cursos = new ArrayList < Curso >() ; private Curso curso = new Curso () ; public void adicionaCurso () { this . cursos . add ( this . curso ) ; this . curso = new Curso () ; this . adicionaMensagemDeConfirmacao ( curso ) ; } private void adicionaMensagemDeConfirmacao ( Curso curso ) { FacesMessage mensagem = new FacesMessage ( " O curso " + curso . getSigla () + " - " + curso . getNome () + " foi adicionado " ) ; FacesContext . getCurrentInstance () . addMessage ( " form - adiciona : botao - adiciona " , mensagem ) ; } // GETTERS E SETTERS }

230

www.k19.com.br

231

R ESPOSTAS

Cdigo Java 6.17: CursosBean.java

Modique o arquivo cursos.xhtml para exibir a mensagem. Faa isso usando a tag <h:message>, como mostrado abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form id = " form - adiciona " > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Sigla : " for = " campo - sigla " / > <h : inputText value = " #{ cursosBean . curso . sigla } " id = " campo - sigla " / > <h : outputLabel value = " Nome : " for = " campo - nome " / > <h : inputText value = " #{ cursosBean . curso . nome } " id = " campo - nome " / > <h : commandButton value = " Adicionar " action = " #{ cursosBean . adicionaCurso } " id = " botao - adiciona " / > </ h : panelGrid > </ h : form > <p > <h : message for = " botao - adiciona " style = " color : green " / > </ p > <h : dataTable value = " #{ cursosBean . cursos } " var = " curso " rendered = " #{ not empty cursosBean . cursos } " > <f : facet name = " header " > Lista de Cursos </ f : facet > <h : column > <f : facet name = " header " > Sigla </ f : facet > #{ curso . sigla } </ h : column > <h : column > <f : facet name = " header " > Nome </ f : facet > #{ curso . nome } </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 6.59: cursos.xhtml

Acesse a aplicao em:

http://localhost:8 8 /K19-Componentes-Visuais/cursos.xhtml
Resposta do Complementar 7.1 No pacote model, crie uma classe chamada Produto para representar os produtos da loja.
1 2 3 package model ; public class Produto {

www.k19.com.br

231

R ESPOSTAS
4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21

232

private private private private private

String nome ; String descricao ; String caminhoDaFigura ; double preco ; int id ;

public Produto ( String nome , String descricao , String caminhoDaFigura , double preco , int id ) { this . nome = nome ; this . descricao = descricao ; this . caminhoDaFigura = caminhoDaFigura ; this . preco = preco ; this . id = id ; } // GETTERS E SETTERS }
Cdigo Java 7.3: Produto.java

Na pasta WebContent do projeto, crie um diretrio chamado imagens. Copie os arquivos da pasta K19-Arquivos/imagens/loja-virtual para o diretrio WebContent/imagens. No pacote managedbeans, crie uma classe chamada ProdutosBean. Essa classe deve armazenar uma lista de produtos e deve ter um atributo para guardar o produto cujos detalhes devem ser exibidos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 package managedbeans ; @ManagedBean public class ProdutosBean { private Produto produtoSelecionado ; private int idDoProdutoSelecionado ; private List < Produto > produtos = new ArrayList < Produto >() ; public ProdutosBean () { this . produtos . add ( new Produto ( " Camiseta branca " , " Esta uma camiseta bsica na cor branca . Ela feita de algodo e " + " est disponvel nos tamanhos P , M e G . " , " / imagens / camiseta - branca . png " , 29.9 , 1) ) ; this . produtos . add ( new Produto ( " Camiseta preta " , " Esta uma camiseta na cor preta , que est disponvel " + " nos tamanhos P , M e G . Seu material 1 % algodo . " , " / imagens / camiseta - preta . png " , 39.9 , 2) ) ; this . produtos . add ( new Produto ( " Cala jeans " , " Cala jeans disponvel nos tamanhos 38 a 5 . " , " / imagens / calca - jeans . png " , 95.99 , 3) ) ; this . produtos . add ( new Produto ( " Terno " , " Terno de seda na cor cinza . " , " / imagens / terno . png " , 589.95 , 4) ) ; this . produtos . add ( new Produto ( " Gravata " , " Gravata nas cores vermelha , azul e verde . " , " / imagens / gravatas . png " , 19.9 , 5) ) ; this . produtoSelecionado = this . produtos . get ( ) ; }

232

www.k19.com.br

233
4 41 42 43 44 45 46 47 48 49 5 51

R ESPOSTAS

public void carregaProduto () { for ( Produto produto : produtos ) { if ( this . idDoProdutoSelecionado == produto . getId () ) { this . produtoSelecionado = produto ; break ; } } } // GETTERS E SETTERS }
Cdigo Java 7.4: ProdutosBean.java

No diretrio WEB-INF/templates, crie um arquivo chamado template-loja-virtual.xhtml para denir um template para as pginas da loja.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > < div id = " header " > < h1 > Loja virtual </ h1 > < hr / > </ div > < ui : insert name = " conteudo " / > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 7.13: template-loja-virtual.xhtml

No diretrio WEB-INF, crie um diretrio com o nome includes.No diretrio includes, crie um arquivo chamado produto-info.xhtml e implemente o pedao da tela responsvel por exibir os detalhes de um produto. O produto particular a ser exibido deve ser passado como parmetro para esse arquivo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 < ui : composition 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 " > <h : panelGrid columns = " 2 " cellspacing = " 5 " > <h : graphicImage value = " #{ produto . caminhoDaFigura } " width = " 1 <h : panelGroup > < h2 > #{ produto . nome } </ h2 > Preo : <h : outputFormat value = " { , number , R$ . <f : param value = " #{ produto . preco } " / > </ h : outputFormat >

" />

} " style = " color : red " >

www.k19.com.br

233

R ESPOSTAS
15 16 17 18 19 2 21 </ h : panelGroup > </ h : panelGrid > < h3 > Descrio </ h3 > #{ produto . descricao } </ ui : composition >
Cdigo XHTML 7.14: produto-info.xhtml

234

Note que o parmetro para o arquivo produto-info.xhtml deve se chamar produto. No diretrio WebContent, crie um arquivo chamado loja.xhtml. Esse arquivo usar o template que voc acabou de criar. O contedo da pgina ser formado pela caixa de seleo de produto e pelo pedao de tela de informaes do produto.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 < ui : composition template = " / WEB - INF / templates / template - loja - virtual . xhtml " 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 : define name = " conteudo " > <h : form > <h : selectOneMenu value = " #{ produtosBean . idDoProdutoSelecionado } " > <f : selectItems value = " #{ produtosBean . produtos } " var = " produto " itemValue = " #{ produto . id } " itemLabel = " #{ produto . nome } " > </ f : selectItems > </ h : selectOneMenu > <h : commandButton value = " Detalhes " action = " #{ produtosBean . carregaProduto } " / > </ h : form > < ui : include src = " / WEB - INF / includes / produto - info . xhtml " > < ui : param name = " produto " value = " #{ produtosBean . produtoSelecionado } " / > </ ui : include > </ ui : define > </ ui : composition >
Cdigo XHTML 7.15: loja.xhtml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Templates-e-Modularizacao/loja.xhtml
Resposta do Complementar 8.1 Primeiramente, crie um pacote chamado managedbeans na pasta src do projeto K19-Navegacao. Nesse pacote, crie uma classe chamada UsuarioBean e implemente um managed bean para armazenar a preferncia do usurio.
1 2 3 4 5 6 package managedbeans ; @SessionScoped @ManagedBean public class UsuarioBean { private String versaoPreferida = " Simples " ;

234

www.k19.com.br

235
7 8 9 1 11 12 13 14 15 16

R ESPOSTAS

public String principal () { if ( this . versaoPreferida . equals ( " Avanada " ) ) return " principal - avancada . xhtml " ; else return " principal - simples . xhtml " ; } // GETTER E SETTER }
Cdigo Java 8.3: UsuarioBean.java

O mtodo principal() da classe UsuarioBean ser usado para determinar a pgina de resposta quando o link para a pgina principal for clicado. Na pasta WebContent/WEB-INF, crie um diretrio chamado templates. Nesse diretrio, crie um arquivo chamado template-aplicacao.xhtml para implementar um template para as pginas da aplicao.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > < div id = " header " style = " text - align : center " > <h : outputText value = " Loja Virtual " style = " font - size : 36 px ; font - weight : bold " / > <h : form > <h : commandLink value = " Pgina principal " action = " #{ usuarioBean . principal } " / > <h : link value = " Configuraes " outcome = " configuracoes " / > </ h : form > </ div > < ui : insert name = " conteudo " / > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 8.18: template-aplicacao.xhtml

Note que o menu para navegar entre as pginas da aplicao foi denido nesse arquivo. Observe que a navegao para a pgina de conguraes foi denida de forma esttica, enquanto que a navegao para a pgina principal foi denida de forma dinmica. No diretrio WebContent, crie dois arquivos chamados principal-simples.xhtml e principal-avancada.xhtml para implementar as verses simples e avanada da pgina principal, respectivamente.
1 2 < ui : composition template = " / WEB - INF / templates / template - aplicacao . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml "

www.k19.com.br

235

R ESPOSTAS
3 4 5 6 7 8 9 1 11 12 xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " conteudo " > < h1 > Pgina Principal Simples </ h1 > < ul > < li > <h : link > Visualizar produtos cadastrados </ h : link > </ li > </ ul > </ ui : define > </ ui : composition >
Cdigo XHTML 8.19: principal-simples.xhtml

236

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

< ui : composition template = " / WEB - INF / templates / template - aplicacao . xhtml " xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : ui = " http :// java . sun . com / jsf / facelets " > < ui : define name = " conteudo " > < h1 > Pgina Principal Avanada </ h1 > < ul > < li > <h : link > Visualizar produtos cadastrados </ h : link > </ li > < li > <h : link > Editar produtos cadastrados </ h : link > </ li > < li > <h : link > Adicionar ou remover produtos </ h : link > </ li > < li > <h : link > Adicionar ou remover usurios </ h : link > </ li > </ ul > </ ui : define > </ ui : composition >
Cdigo XHTML 8.20: principal-avancada.xhtml

Finalmente, na pasta WebContent, crie um arquivo chamado configuracoes.xhtml para implementar a pgina da aplicao em que o usurio pode alterar suas preferncias.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 < ui : composition template = " / WEB - INF / templates / template - aplicacao . xhtml " 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 : define name = " conteudo " > < h1 > Configuraes </ h1 > <p > Voc est usando a verso <b > #{ usuarioBean . versaoPreferida } </ b > da aplicao . Se desejar , escolha outra verso abaixo e clique no boto " Salvar " . </ p > <h : form > <h : panelGrid columns = " 3 " > <h : outputLabel value = " Verso da aplicao : " for = " versao " / > <h : selectOneMenu value = " #{ usuarioBean . versaoPreferida } " id = " versao " > <f : selectItem itemLabel = " Simples " itemValue = " Simples " / > <f : selectItem itemLabel = " Avanada " itemValue = " Avanada " / > </ h : selectOneMenu > <h : commandButton value = " Salvar " / > </ h : panelGrid > </ h : form > </ ui : define > </ ui : composition >
Cdigo XHTML 8.21: conguracoes.xhtml

Acesse a aplicao no endereo:


236
www.k19.com.br

237

R ESPOSTAS

http://localhost:8 8 /K19-Navegacao/principal-simples.xhtml
Resposta do Complementar 8.2 No arquivo template-aplicacao.xhtml, altere o link para a pgina principal para que ele emita o sinal "principal".
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 " xmlns : ui = " http :// java . sun . com / jsf / facelets " > <h : head > < title > K19 Treinamentos </ title > </ h : head > <h : body > < div id = " header " style = " text - align : center " > <h : outputText value = " Loja Virtual " style = " font - size : 36 px ; font - weight : bold " / > <h : form > <h : link value = " Pgina principal " outcome = " principal " / > <h : link value = " Configuraes " outcome = " configuracoes " / > </ h : form > </ div > < ui : insert name = " conteudo " / > < div id = " footer " style = " text - align : center " > < hr / > & copy ; 2 12 K19 . Todos os direitos reservados . </ div > </ h : body > </ html >
Cdigo XHTML 8.22: template-aplicacao.xhtml

No arquivo faces-config.xhtml, dena as regras de navegao para a pgina principal. Se o usurio prefere a verso simples da aplicao, ento o sinal "principal" deve direcionar o usurio para a pgina denida pelo arquivo principal-simples.xhtml. Por outro lado, se o usurio prefere a verso avanada da aplicao, ento o sinal "principal" deve direcion-lo para a pgina denida pelo arquivo principal-avancada.xhtml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 ... < navigation - rule > < from - view - id >* </ from - view - id > < navigation - case > < from - outcome > principal </ from - outcome > < if > #{ usuarioBean . versaoPreferida == Simples } </ if > <to - view - id > principal - simples . xhtml </ to - view - id > </ navigation - case > < navigation - case > < from - outcome > principal </ from - outcome > < if > #{ usuarioBean . versaoPreferida == Avanada } </ if > <to - view - id > principal - avancada . xhtml </ to - view - id > </ navigation - case > </ navigation - rule > ...

www.k19.com.br

237

R ESPOSTAS

238

Cdigo XML 8.6: faces-cong.xml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Navegacao/principal-simples.xhtml
Resposta do Complementar 10.1 No diretrio src do projeto K19-Conversao-e-Validacao, crie um pacote chamado model. Nesse pacote, crie uma classe chamada Cotacao para modelar a cotao de uma moeda.
1 2 3 4 5 6 7 8 9 package model ; public class Cotacao { private Double valor ; private Double variacao ; private Date horario ; // GETTERS E SETTERS }
Cdigo Java 10.4: Cotacao.java

Crie um pacote chamado managedbeans no diretrio src. Nesse pacote, crie uma classe chamada CotacaoBean para armazenar os valores submetidos pelo formulrio.
1 2 3 4 5 6 7 8 package managedbeans ; @ManagedBean public class CotacaoBean { private Cotacao cotacao = new Cotacao () ; // GETTER E SETTER }
Cdigo Java 10.5: CotacaoBean.java

No diretrio WebContent, crie um arquivo chamado registrar-cotacao.xhtml e implemente o formulrio para registrar uma cotao.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Registrar cotao do dlar </ h1 > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Valor : " for = " valor " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . valor } " id = " valor " required = " true " > <f : convertNumber locale = " pt_BR " type = " currency " / > </ h : inputText > <h : message for = " valor " style = " color : red " / >

238

www.k19.com.br

239
21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 </ h : panelGroup >

R ESPOSTAS

<h : outputLabel value = " Variao : " for = " variacao " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . variacao } " id = " variacao " required = " true " > <f : convertNumber maxFractionDigits = " 5 " type = " percent " / > </ h : inputText > <h : message for = " variacao " style = " color : red " / > </ h : panelGroup > <h : outputLabel value = " Horrio : " for = " horario " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . horario } " id = " horario " required = " true " > <f : convertDateTime pattern = " HH : mm dd - MM - yyyy " / > </ h : inputText > <h : message for = " horario " style = " color : red " / > </ h : panelGroup > <h : commandButton value = " Registrar " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML 10.9: registrar-cotacao.xhtml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/registrar-cotacao.xhtml
Resposta do Complementar 10.2 No arquivo registrar-cotacao.xhtml, adicione as linhas em destaque do cdigo abaixo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Registrar cotao do dlar </ h1 > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Valor : " for = " valor " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . valor } " id = " valor " required = " true " > <f : convertNumber locale = " pt_BR " type = " currency " / > </ h : inputText > <h : message for = " valor " style = " color : red " / > </ h : panelGroup > <h : outputLabel value = " Variao : " for = " variacao " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . variacao } " id = " variacao " required = " true " > <f : convertNumber maxFractionDigits = " 5 " type = " percent " / > </ h : inputText > <h : message for = " variacao " style = " color : red " / > </ h : panelGroup >

www.k19.com.br

239

R ESPOSTAS
3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52

240

<h : outputLabel value = " Horrio : " for = " horario " / > <h : panelGroup > <h : inputText value = " #{ cotacaoBean . cotacao . horario } " id = " horario " required = " true " > <f : convertDateTime pattern = " HH : mm dd - MM - yyyy " / > </ h : inputText > <h : message for = " horario " style = " color : red " / > </ h : panelGroup > <h : commandButton value = " Registrar " / > </ h : panelGrid > </ h : form > <h : panelGroup rendered = " #{ cotacaoBean . cotacao . valor != null } " > < h2 > Cotao registrada : </ h2 > Valor : #{ cotacaoBean . cotacao . valor } < br / > Variao : #{ cotacaoBean . cotacao . variacao * 1 }% < br / > Horrio : #{ cotacaoBean . cotacao . horario } </ h : panelGroup > </ h : body > </ html >
Cdigo XHTML 10.10: registrar-cotacao.xhtml

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/registrar-cotacao.xhtml
Altere o valor do atributo timeZone do componente <f:convertDateTime>. Use, por exemplo, os valores GMT-2 e GMT-3. Teste o formulrio novamente. Resposta do Complementar 10.3 No diretrio src do projeto K19-Conversao-e-Validacao, crie um pacote chamado model. Nesse pacote, crie uma classe chamada Produto.
1 2 3 4 5 6 7 8 9 1 package model ; public class Produto { private String nome ; private String codigo ; private Integer tamanho ; private Double volume ; // GETTERS E SETTERS }
Cdigo Java 10.7: Produto.java

Crie um pacote chamado managedbeans no diretrio src. Nesse pacote, crie uma classe chamada ProdutoBean.
1 2 3 4 5 6 7 8 package managedbeans ; @ManagedBean public class ProdutoBean { private Produto produto = new Produto () ; // GETTER E SETTER }

240

www.k19.com.br

241

R ESPOSTAS

Cdigo Java 10.8: ProdutoBean.java

No diretrio WebContent, crie um arquivo chamado cadastro-de-produtos.xhtml e implemente o formulrio.


1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > < h1 > Cadastro de Produtos </ h1 > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome : " for = " nome " / > <h : panelGroup > <h : inputText value = " #{ produtoBean . produto . nome } " id = " nome " required = " true " > <f : validateRegex pattern = " [a - zA - Z \ s ]+ " / > </ h : inputText > <h : message for = " nome " style = " color : red " / > </ h : panelGroup > <h : outputLabel value = " Cdigo : " for = " codigo " / > <h : panelGroup > <h : inputText value = " #{ produtoBean . produto . codigo } " id = " codigo " required = " true " > <f : validateRegex pattern = " [A - Z ][ -9]+ " / > <f : validateLength minimum = " 4 " maximum = " 1 " / > </ h : inputText > <h : message for = " codigo " style = " color : red " / > </ h : panelGroup > <h : outputLabel value = " Tamanho : " for = " tamanho " / > <h : panelGroup > <h : inputText value = " #{ produtoBean . produto . tamanho } " id = " tamanho " > <f : validateRequired / > <f : validateLongRange minimum = " 1 " maximum = " 32 " / > </ h : inputText > <h : message for = " tamanho " style = " color : red " / > </ h : panelGroup > <h : outputLabel value = " Volume : " for = " volume " / > <h : panelGroup > <h : inputText value = " #{ produtoBean . produto . volume } " id = " volume " > <f : validateRequired / > <f : validateDoubleRange minimum = " .1 " / > </ h : inputText > <h : message for = " volume " style = " color : red " / > </ h : panelGroup > <h : commandButton value = " Enviar " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML 10.22: cadastro-de-produtos.xhtml

Teste a aplicao no endereo:


www.k19.com.br

241

R ESPOSTAS

242

http://localhost:8 8 /K19-Conversao-e-Validacao/cadastro-de-produtos.xhtml
Resposta do Complementar 10.4 Na pasta src do projeto K19-Conversao-e-Validacao, crie um pacote chamado model. Nesse pacote, crie uma classe chamada RIC.
1 2 3 4 5 6 7 8 package model ; public class RIC { private String numeroDeIdentificacao ; private String digitoVerificador ; // GETTERS E SETTERS }
Cdigo Java 10.20: RIC.java

Na pasta src, crie um pacote chamado converters. Nesse pacote, crie uma classe chamada ConversorDeRIC e implemente o conversor.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 package converters ; @FacesConverter ( forClass = RIC . class ) public class ConversorDeRIC implements Converter { @Override public Object getAsObject ( FacesContext context , UIComponent component , String value ) { String ricString = value . trim () ; if (! Pattern . matches ( " [ -9]{1 }[ -]?[ -9] " , ricString ) ) { FacesMessage mensagem = new FacesMessage ( " Nmero RIC invlido " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ConverterException ( mensagem ) ; } ricString = ricString . replaceAll ( " -" , " " ) ; RIC ric = new RIC () ; ric . setNumeroDeIdentificacao ( ricString . substring ( , 1 ) ) ; ric . setDigitoVerificador ( ricString . substring (1 , 11) ) ; return ric ; } @Override public String getAsString ( FacesContext context , UIComponent component , Object value ) { RIC ric = ( RIC ) value ; return ric . getNumeroDeIdentificacao () + " -" + ric . getDigitoVerificador () ; } }
Cdigo Java 10.21: ConversorDeRIC.java

Agora, voc deve testar o seu conversor. Na pasta src, crie um pacote chamado managedbeans. Nesse pacote, crie uma classe chamada RICBean e implemente o managed bean que dar suporte ao seu formulrio.
1 2 package managedbeans ;

242

www.k19.com.br

243
3 4 5 6 7 8 @ManagedBean public class RICBean { private RIC ric ; // GETTER E SETTER }
Cdigo Java 10.22: RICBean.java

R ESPOSTAS

Finalmente, no diretrio WebContent, crie um arquivo chamado ric.xhtml e implemente um formulrio que possua uma caixa de texto associada propriedade ric do managed bean rICBean.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " RIC : " for = " campo - ric " / > <h : inputText id = " campo - ric " value = " #{ rICBean . ric } " / > <h : commandButton value = " Enviar " / > </ h : form > <h : message for = " campo - ric " style = " color : red " / > </ h : body > </ html >
Cdigo XHTML 10.26: ric.xhtml

Faa alguns testes acessando a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/ric.xhtml
Resposta do Complementar 10.5 Primeiro, implemente o managed bean que armazenar a data escolhida pelo usurio. No diretrio src do projeto K19-Conversao-e-Validacao, crie um pacote chamado managedbeans. Nesse pacote, adicione a seguinte classe.
1 2 3 4 5 6 7 8 9 package managedbeans ; @ManagedBean public class ReservaBean { private Date data ; // GETTER E SETTER }
Cdigo Java 10.27: ReservaBean.java

No diretrio WebContent, crie um arquivo chamado reserva.xhtml e implemente o formulrio para o usurio digitar a data.
1 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN "

www.k19.com.br

243

R ESPOSTAS
2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 " 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 > K19 Treinamentos </ title > </ h : head > <h : body > <h : outputText value = " Escolha uma data entre 1/ 5/2 14 e 3 / 8/2 14. " / > <h : form > <h : outputLabel value = " Data : ( dd / MM / yyyy ) " for = " campo - data " / > <h : inputText id = " campo - data " value = " #{ reservaBean . data } " required = " true " > <f : convertDateTime pattern = " dd / MM / yyyy " / > <f : validator validatorId = " validators . ValidadorDeData " / > <f : attribute name = " padraoDeData " value = " dd / MM / yyyy " / > <f : attribute name = " inicio " value = " 1/ 5/2 14 " / > <f : attribute name = " fim " value = " 3 / 8/2 14 " / > </ h : inputText > <h : commandButton value = " Enviar " / > </ h : form > <h : message for = " campo - data " style = " color : red " / > </ h : body > </ html >
Cdigo XHTML 10.30: reserva.xhtml

244

Crie um pacote chamado validators no diretrio src. Nesse pacote, crie uma classe chamada ValidadorDeData para implementar o validador.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 package validators ; @FacesValidator ( " validators . ValidadorDeData " ) public class ValidadorDeData implements Validator { @Override public void validate ( FacesContext context , UIComponent component , Object value ) throws ValidatorException { String padraoDeData = ( String ) component . getAttributes () . get ( " padraoDeData " ) ; String inicio = ( String ) component . getAttributes () . get ( " inicio " ) ; String fim = ( String ) component . getAttributes () . get ( " fim " ) ; Date data = ( Date ) value ; Date dataInicio ; Date dataFim ; try { dataInicio = ( Date ) new SimpleDateFormat ( padraoDeData ) . parse ( inicio ) ; dataFim = ( Date ) new SimpleDateFormat ( padraoDeData ) . parse ( fim ) ; } catch ( ParseException e ) { FacesMessage mensagem = new FacesMessage ( " Erro ao criar as datas de incio e fim do intervalo . " ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ValidatorException ( mensagem ) ; } if ( data . before ( dataInicio ) || data . after ( dataFim ) ) { FacesMessage mensagem = new FacesMessage ( " A data escolhida precisa estar entre " + inicio + " e " + fim ) ; mensagem . setSeverity ( FacesMessage . SEVERITY_ERROR ) ; throw new ValidatorException ( mensagem ) ;

244

www.k19.com.br

245
33 34 35 } } }
Cdigo Java 10.28: ValidadorDeData.java

R ESPOSTAS

Acesse a aplicao no endereo:

http://localhost:8 8 /K19-Conversao-e-Validacao/reserva.xhtml
Teste o formulrio submetendo-o com diversas datas diferentes, inclusive com datas nos extremos do intervalo permitido. Agora, modique o arquivo reserva.xhtml de forma que o conversor de datas considere o fuso horrio da cidade de So Paulo, como no trecho de cdigo abaixo.
1 2 3 ... <f : convertDateTime pattern = " dd / MM / yyyy " timeZone = " GMT -3 " / > ...
Cdigo XHTML 10.31: reserva.xhtml

Teste o formulrio novamente.

www.k19.com.br

245

You might also like