P. 1
k19-k12-desenvolvimento-web-com-jsf2-e-jpa2

k19-k12-desenvolvimento-web-com-jsf2-e-jpa2

|Views: 30|Likes:
Published by Ariel Soares Teles

More info:

Published by: Ariel Soares Teles on Nov 07, 2011
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

11/07/2011

pdf

text

original

Sections

  • Banco de dados
  • 1.1 Bases de dados (Databases)
  • 1.2 Tabelas
  • 1.3 Operações Básicas
  • 1.4 Chaves Primária e Estrangeira
  • 1.5 Consultas Avançadas
  • 1.6 Exercícios
  • 2.1 Driver
  • 2.2 JDBC
  • 2.3 Instalando o Driver JDBC do MySQL Server
  • 2.4 Criando uma conexão
  • 2.5 Inserindo registros
  • 2.6 Exercícios
  • 2.7 SQL Injection
  • 2.8 Exercícios
  • 2.9 Listando registros
  • 2.10 Exercícios
  • 2.11 Fábrica de conexões (Factory)
  • 2.12 Exercícios
  • JPA 2 e Hibernate
  • 3.1 Múltiplas sintaxes da linguagem SQL
  • 3.2 Orientação a Objetos VS Modelo Entidade Relaciona- mento
  • 3.3 Ferramentas ORM
  • 3.4 O que é JPA e Hibernate
  • 3.5 Configuração
  • 3.6 Mapeamento
  • 3.7 Gerando o banco
  • 3.8 Exercícios
  • 3.9 Manipulando entidades
  • 3.9.1 Persistindo
  • 3.9.2 Buscando
  • 3.9.3 Removendo
  • 3.9.4 Atualizando
  • 3.9.5 Listando
  • 3.9.6 Transações
  • 3.10 Exercícios
  • 3.11 Repository
  • 3.12 Exercícios
  • Web Container
  • 4.1 Necessidades de uma aplicação web
  • 4.2 Web Container
  • 4.3 Especificação Java EE
  • 4.4 Exercícios
  • 4.5 Aplicação Web Java
  • 4.6 Exercícios
  • 4.7 Processando requisições
  • 4.8 Servlet
  • 4.8.1 Inserindo conteúdo na resposta
  • 4.9 Exercícios
  • 4.10 JSP
  • 4.11 Exercícios
  • 4.12 Frameworks
  • Visão Geral do JSF 2
  • 5.1 Aplicação de exemplo
  • 5.2 Managed Beans
  • 5.2.1 GeradorDeApostasBean
  • 5.3 Facelets e Componentes Visuais
  • 5.3.1 Tela de entrada
  • 5.3.2 Tela de Saída
  • 5.4 Exercícios
  • Componentes Visuais
  • 6.1 Formulários
  • 6.2 Panel Grid
  • 6.3 Panel Group
  • 6.4 Tabelas
  • 6.5 Namespaces
  • 6.6 Esqueleto HTML
  • 6.7 Exercícios
  • Facelets
  • 7.1 Templating
  • 7.2 Exercícios
  • 7.3 Particionando as telas
  • 7.4 Exercícios
  • Navegação
  • 8.1 Navegação Estática Implícita
  • 8.2 Navegação Estática Explícita
  • 8.3 Exercícios
  • 8.4 Navegação Dinâmica Implícita
  • 8.5 Navegação Dinâmica Explícita
  • 8.6 Exercícios
  • Managed Beans
  • 9.1 Criando Managed Beans
  • 9.2 Disponibilizando dados para as telas
  • 9.3 Recebendo dados das telas
  • 9.4 Definindo o tratamento das ações
  • 9.5 Expression Language
  • 9.5.1 Nome dos Managed Beans
  • 9.5.2 Acessando as propriedades dos Managed Beans
  • 9.6 Binding
  • 9.7 Escopo
  • 9.7.1 Request
  • 9.7.2 Session
  • 9.7.3 Application
  • 9.7.4 View
  • 9.8 Interdependência e Injeção
  • 9.9 Exercícios
  • Conversão e Validação
  • 10.1 Conversão
  • 10.1.1 Conversão Padrão Implícita
  • 10.1.2 Conversão Padrão Explícita
  • 10.2 Mensagens de Erro
  • 10.2.1 h:message
  • 10.2.2 h:messages
  • 10.2.3 Alterando as Mensagens de Erro
  • 10.3 Exercícios
  • 10.4 Validação
  • 10.4.1 Validação Padrão
  • 10.4.2 Campo Obrigatório (Required)
  • 10.4.3 f:validateLongRange
  • 10.4.4 f:validateDoubleRange
  • 10.4.5 f:validateLength
  • 10.4.6 f:validateRegex
  • 10.4.7 Bean Validation
  • 10.5 Exercícios
  • 11.1 Eventos de Aplicação (Application Events)
  • 11.1.1 ActionEvent
  • 11.1.2 ValueChangeEvent
  • 11.2 Eventos de Ciclo de Vida (Lifecycle Events)
  • 11.3 Exercícios
  • 12.1 Fazendo requisições AJAX
  • 12.2 Recarregando alguns “pedaços” das telas
  • 12.3 Processando alguns “pedaços” das telas
  • 12.4 Palavras especiais
  • 12.5 Exercícios
  • 13.1 Modelo
  • 13.2 Exercícios
  • 13.3 Persistência - Mapeamento
  • 13.4 Exercícios
  • 13.5 Persistência - Configuração
  • 13.6 Exercícios
  • 13.7 Persistência - Open Session in View
  • 13.7.1 Gerenciando as fábricas de Entity Managers
  • 13.7.2 Filtros
  • 13.7.3 Gerenciando os Entity Managers
  • 13.8 Exercícios
  • 13.9 Persistência - Repositórios
  • 13.10 Exercícios
  • 13.11 Apresentação - Template
  • 13.12 Exercícios
  • 13.13 Cadastrando e Listando Seleções
  • 13.14 Exercícios
  • 13.15 Mensagens de Erro
  • 13.16 Exercícios
  • 13.17 Removendo Seleções
  • 13.18 Exercícios
  • 13.19 Otimizando o número de consultas
  • 13.20 Exercícios
  • 13.21 Cadastrando, Listando e Removendo Jogadores
  • 13.22 Exercícios
  • 13.23 Removendo Seleções com Jogadores
  • 13.24 Exercícios
  • 13.25 Controle de Acesso
  • 13.26 Exercícios
  • 13.27 Ordem dos filtros
  • 13.28 Exercícios
  • 13.29 Controle de Erro
  • 13.30 Exercícios
  • 13.31 Enviando email
  • 13.32 Exercícios

TREINAMENTOS

Desenvolvimento Web com JSF2 e JPA2

Desenvolvimento Web com JSF 2 e JPA 2

15 de março de 2011

www.k19.com.br

ii

. 3 JPA 2 e Hibernate 3. . . . . . .5 Consultas Avançadas . . . . . 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Ferramentas ORM . . . . . . . . 2. . . . . . . .1 Bases de dados (Databases) . . . . . . . . . . . . . . . . . . . . . . . . . 3. . . . . . . . . . . . . . . . 3. . . . . . . . . . . . . . . . . iii . . . . . . . . . 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Driver . . . . . . . . . . . . . . . . . . . . . . . . .9. . . . . . . . . . . . . . . . .3 Operações Básicas . . . 1. . . .6 Exercícios . . . . . . . . .8 Exercícios . . . . . . . . . . . . . . . 3.6 Mapeamento . . . . . .4 Criando uma conexão . . . . . . . . . . . . . . . . . . . .5 Configuração . . . .9 Manipulando entidades . . . . . . . .3 Instalando o Driver JDBC do MySQL Server 2. . . . . . . . . . . . . . . . . . . . . . .3 Removendo . . . . . . . . .9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10 Exercícios . . . . . . . . .1 Múltiplas sintaxes da linguagem SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. . . . 1. . . . . . . . . . . . . . . . . 3. . . . . . . .9. . . . . . 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1. 3. . . . . . 3. . . . . . . . . .2 Orientação a Objetos VS Modelo Entidade Relacionamento 3. . . . . 2. . . . . 1 2 4 7 11 11 12 27 27 28 28 28 29 29 31 33 33 34 35 36 37 37 37 37 38 38 39 40 41 43 43 43 44 44 .4 O que é JPA e Hibernate . . . 3. . .7 SQL Injection . . . . . . . . . . . . . . .2 Buscando . 1. . . . . . . . . . . . . . .7 Gerando o banco . . . . . . . . . . . . . . . . . . .8 Exercícios . . . . . .5 Inserindo registros . . . . . . . . . . .11 Fábrica de conexões (Factory) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Atualizando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Tabelas . .9 Listando registros . . .6 Exercícios . . . . . . . . . . . . . . . . . . . . . 2. . 2 JDBC 2. . . . . . . . .2 JDBC . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . . 2. . .9. 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Chaves Primária e Estrangeira 1. . . .Sumário 1 Banco de dados 1. . . . . . . . . . . . . . . .1 Persistindo . .12 Exercícios . . . . . . . . . . 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .10 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. .4 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Web Container . . . . . . . . . . . . . . . . .5 Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Panel Grid . 7 Facelets 7. . . . . . . . . . . . . . . . . . .11 Exercícios . . . . . . . .3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6. . 4. . . . . . . . . . . . .9 Exercícios . . . . . . . . . . . . . . . . .6 Esqueleto HTML 6. . . . . . . . . . . . . . . .6 Transações 3. . . . . . . . . . 4. . . . . . . 7. . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . . . . . . . . . . . . . . . . . . . . . . .1 GeradorDeApostasBean 5. . . . . . . . . . 7. . . . . . . . . . . . . . . . . . . 3. . . . . . . . . . . . . .2 Managed Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 44 45 46 47 49 49 49 50 50 50 51 51 51 52 52 53 53 53 55 55 55 56 56 56 57 58 63 63 65 66 67 68 68 68 71 71 72 73 74 iv Web Container 4. . . . . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . . . . . . . . . .12 Exercícios . . . . . . . . . . . . . . . . . . .1 Aplicação de exemplo .1 Inserindo conteúdo na resposta 4. . . . . . . 3. . . . . . . . . . . . . . . . . . . . . . . . . .4 Exercícios . . . . . . . . .11 Repository . . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . www. . . . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .8. 5 . . . . . . . . . 5. . 5. . . . .2 Tela de Saída . .3 Facelets e Componentes Visuais 5. . . 6. . . . . . . . . . . . . . . . . . . . . . . . . . 6 . . . . . . 6. . .1 Formulários . . . . . . . . . . . . . . . . . . . .10 JSP . . . . . .SUMÁRIO 3. . . . .2. . . . . . . . . . .1 Tela de entrada . . .1 Necessidades de uma aplicação web . . . . . . . . . . . . . . . . . . . . . . .3. . . . 4 . . . . . . . . . . . . . . . . . . . .1 Templating . . . . . . . . . . . . . . . .4 Exercícios . . . .com. . . . . .3 Particionando as telas 7. . . . . . . . . . . . . . . . . . . . . . . .8 Servlet . . . . . . . . . .12 Frameworks . . . . . . . . . . . . 4. . . . . . .k19. . . . . . 4. . . . . .6 Exercícios . Componentes Visuais 6. . . . . . . . . . . . . .7 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Especificação Java EE . . . . . .7 Processando requisições . . . . . . . . . . . . . . . . . . . . . . . . . 6. . . . . . . . . . . . . . . .4 Tabelas . . . Visão Geral do JSF 2 5. . . . . . .9. . . . . . . . 4. . . . . . . . . . . . . . . . . .br . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Listando . . . . . . . . . . . . . .5 Aplicação Web Java . . . . . . . .9. . . . . 3. . . . . . . . . . . . . . . SUMÁRIO . . . . . . . . . .2 Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Panel Group . . . . . . .

. . . .4. . . . . 10. 10.1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Campo Obrigatório (Required) . . . . . . . . . . . 10. . . . . . . . . . . . . . . . .7 Bean Validation . . . . . . . . . . . . . . . . . . . . . . .7. . . . . . . . . . . . . . . . . . . . . . .4.8 Interdependência e Injeção . . . 10. . . . . . . . . . . 10. .7. . . . . . . . . .3 Application . . . . . . . . . . . . . . 9. 9 Managed Beans 9. . . . . . .7 Escopo . . . . . . . . . . . . . . . .3 Recebendo dados das telas . . . . . . . . . . . .7. . . . .3 Exercícios . . .SUMÁRIO 8 Navegação 8. . . . . . . . . . . . . . . . . . . . . . K19 Treinamentos . . . . . . . . . .1 Navegação Estática Implícita . . . . .5 Expression Language .4 Validação . . . .4. . . . . .6 Exercícios . . .2 h:messages . . . . . . . . . . . . . . . . . . . . .1 Conversão Padrão Implícita . . . . . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . . . . . . . 10. . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . . . . . .1 Nome dos Managed Beans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . .5. . . . . . . . .5 f:validateLength . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Alterando as Mensagens de Erro 10. . . . . . . . . . . . 9.4 Navegação Dinâmica Implícita 8. . . . .1 Request . . . . . . . . . . . . . . . 10. . . . . . . . . . . .1 h:message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Conversão e Validação 10. . . . 8. . . . . . . . . .4 Definindo o tratamento das ações . . . . . . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . .2 Navegação Estática Explícita . . . 9. . . . . . . . .2. . . . . . . . . . . . . . . . . . . . . . 9. . .1. . . . . . . . . . . . . 9. . . .1 Criando Managed Beans . . . 10. . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . . .4 f:validateDoubleRange . . . . . . . . . .4. . . . . . . . . . . . . . . .2 Mensagens de Erro . .2.6 f:validateRegex . . . . . . . . . . . . . . 10. . . . 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Disponibilizando dados para as telas . 9. . . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . 9. . . . .4. . . . . . . . . . . .7. . . .4. . . . . . . . . . . .2 Acessando as propriedades dos Managed Beans 9. . . . . . . . . . . . . . . . 8. .5 Navegação Dinâmica Explícita 8. . . . . . . . . . . . . . .9 Exercícios . . . . . . . . . . SUMÁRIO 77 77 78 78 80 81 81 85 85 86 86 86 87 87 87 87 88 88 89 90 90 91 92 95 95 95 96 97 97 98 98 99 101 101 101 101 102 102 102 102 103 . . . . . . . . . . . . 9. . . . 8. . . . . . .3 f:validateLongRange . . . . . 10. . . . . . . . . . . .2. . . . . . . . . . . . v . . . . . . . . . . . . . . . . . .1 Conversão . . . .4. . . . .1 Validação Padrão . . . . . . . . . . 10. . . . .4 View . . . . . . . . . . . . . . . . . . . . . . .6 Binding . . . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . 10. . .5 Exercícios . . .3 Exercícios . . . . .2 Conversão Padrão Explícita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . .20Exercícios . . . . . . . . . . . . . . . . . . . .3 Persistência . 13. . . . . . . . . . . . .com. . . . . . . . . . . . . . . .28Exercícios . . . . . . . . . . . . . . . . . . . . . . . . .Template . . . . . . . . . . . . . . .25Controle de Acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Exercícios . . . . . . . . . . .17Removendo Seleções . . . . . . . . . . 12. . . . . . . . . . . . .Open Session in View . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Palavras especiais . 13.7.7 Persistência . . . . . . . . . . . . . . . . .14Exercícios . . . . . . . . . . . . 13. . . . . .21Cadastrando. .7. . . . . . . . . . . . . . . . . . . . . . .Mapeamento . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . .1. . .13Cadastrando e Listando Seleções . . .1 ActionEvent . . . . 13. . . 13. . . . . . . . . .k19. . . 12. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .br . . . . . . . . .1 Eventos de Aplicação (Application Events) 11. . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Exercícios . . . .23Removendo Seleções com Jogadores . . . . . 13. . . . . . . . 13. .26Exercícios . . . . . . . . . . . .5 Persistência . . . . 13. . . .12Exercícios . . . . . . . . . . 11. . . . . . 13. . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12. . . . . . . . . . . . . 13. . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Exercícios . . . . . . . . 13. . SUMÁRIO 107 107 107 108 109 109 113 113 114 115 115 116 119 119 119 120 120 121 121 122 122 123 123 124 125 126 127 127 129 130 132 132 133 133 133 134 135 135 139 139 140 140 143 143 vi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Listando e Removendo Jogadores . . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . .2 Recarregando alguns “pedaços” das telas . . . . . . . . . . . . . . . . . . . . . . . . .11Apresentação . . . . . . 12 Ajax 12. . . .SUMÁRIO 11 Eventos 11.2 Filtros . . .16Exercícios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .10Exercícios . . . . . . . . . 13. . . . . . .19Otimizando o número de consultas . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . .1. . . . . . .15Mensagens de Erro . . . . . . . . . . . . . . . .8 Exercícios . . . . . . . . . 13. . . . www. . . . 13. . . . . . . . . . . . . . .27Ordem dos filtros . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Exercícios . . . . . .18Exercícios . . . . 13 Projeto 13. 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . 13. . . . . . . .Configuração . . . . . . . . . . . . . . .2 Eventos de Ciclo de Vida (Lifecycle Events) 11. . . . . . . . . . . . . .1 Gerenciando as fábricas de Entity Managers 13. . . . . . . . . . . 13. . . . . . . . . 13. . . . . . . . . . .9 Persistência .2 ValueChangeEvent . . . . . . . 13. . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . .Repositórios . . . . . . . . . .7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Fazendo requisições AJAX . . . .4 Exercícios . . . . . . . . . . . . . . . . .3 Gerenciando os Entity Managers . . . . . . . . . . . . . . . . . . .3 Processando alguns “pedaços” das telas . . . . . . . . . .1 Modelo . . . . . .22Exercícios . . . . . .24Exercícios . . . . .

. . . . . . . . . . . . . .31Enviando email . . . . . . . . . . . . . . .30Exercícios . . . . . . . . . . . .SUMÁRIO 13. 144 144 146 147 vii K19 Treinamentos . . . . . . .29Controle de Erro 13. . .32Exercícios . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . . . . . . . . . SUMÁRIO . . . . . 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

k19.SUMÁRIO SUMÁRIO www.br viii .com.

uma aplicação de gerenciamento de uma livraria deve armazenar os dados dos livros que ela comercializa. A seguir. Contudo. os dados não podem ser perdidos ou corrompidos. concluímos que seria necessária a utilização de um sistema complexo para manusear as informações das nossas aplicações. Uma forma de suprir essa necessidade seria armazenar essas informações em arquivos. há diversas opções de sistemas gerenciadores de banco de dados. Por exemplo. Felizmente. A seguir. apresentamos os mais populares: 1 . diversos sistemas e usuários acessarão as informações de forma concorrente. alguns fatores importantes nos levam a descartar tal opção. tal tipo de sistema já existe e é conhecido como Sistema Gerenciador de Banco de Dados (SGBD). Considerando todos esses aspectos. apresentamos as principais preocupações a serem consideradas ao trabalhar com dados: Segurança: As informações potencialmente confidenciais devem ser controladas de forma que apenas usuários e sistemas autorizados tenham acesso a elas. Sistemas gerenciadores de banco de dados No mercado. Concorrência: Usualmente. Integridade: Eventuais falhas de software ou hardware não devem corromper os dados. Apesar disso. Acesso: As funções de consulta e manipulação dos dados devem ser implementadas.Capítulo 1 Banco de dados O nosso objetivo é desenvolver aplicações em Java. Essas aplicações necessitam armazenar as informações relacionadas ao seu domínio em algum lugar.

Criando uma base de dados no MySQL Server Para criar uma base de dados no MySQL Server.Banco de dados • Oracle • SQL Server • MySQL Server • PostgreSQL MySQL Server Neste treinamento.1 Bases de dados (Databases) Um sistema gerenciador de banco de dados é capaz de gerenciar informações de diversos sistemas ao mesmo tempo. 1.com. Caso os dados fossem mantidos sem nenhuma separação lógica. Por exemplo. por exemplo. ou vice-versa. Tais regras criam restrições quanto ao conteúdo acessível por cada usuário. as informações dos clientes de um banco. seria mais difícil implementar regras de segurança referentes ao acesso dos dados. que é mantido pela Oracle e vastamente utilizado no mercado. os dados da nossa livraria.mysql. O MySQL Server pode ser obtido a partir do site: http://www. Determinado usuário. por exemplo. Daí surge o conceito de base de dados (database). utilizamos o comando CREATE DATABASE. por questões de organização e segurança.com. Além disso. a organização ficaria prejudicada. mas não às informações dos produtos da loja virtual. poderia ter permissão de acesso aos dados dos clientes do banco.k19. Então. além dos produtos de uma loja virtual. MySQL Query Browser Para interagir com o MySQL Server. os dados devem ser armazenados separadamente no SGBD. utilizaremos um cliente com interface gráfica chamado de MySQL Query Browser. utilizaremos o MySQL Server. www.br 2 . como. Uma base de dados é um agrupamento lógico das informações de um determinado domínio.

Banco de dados 3 K19 Treinamentos .

é interessante separar o saldo e o limite de uma conta. 1.Banco de dados Repare que além da base de dados livraria há outras três bases.br .2 Tabelas Um servidor de banco de dados é dividido em bases de dados com o intuito de separar as informações de sistemas diferentes. no sistema de um banco. Essa separação é feita através de tabelas. do nome e CPF de um cliente. poderíamos criar uma tabela para os dados relacionados às contas e outra para os dados relacionados aos clientes. nome José Maria Cliente idade cpf 27 31875638735 32 30045667856 numero 1 2 Conta saldo 1000 2000 limite 500 700 4 www. Nessa mesma linha de raciocínio. Essas bases foram criadas automaticamente pelo próprio MySQL Server para teste ou para guardar algumas configurações. Quando uma base de dados não é mais necessária. ela pode ser removida através do comando DROP DATABASE. podemos dividir os dados de uma base a fim de agrupá-los segundo as suas correlações. Então. Por exemplo.k19.com.

suponha uma tabela para armazenar as informações dos clientes de um banco. Por exemplo. Criando tabelas no MySQL Server As tabelas no MySQL Server são criadas através do comando CREATE TABLE. 5 K19 Treinamentos . Na criação de uma tabela é necessário definir quais são os nomes e os tipos das colunas.Banco de dados Uma tabela é formada por registros(linhas) e os registros são formados por campos(colunas). Cada registro dessa tabela armazena em seus campos os dados de um determinado cliente.

k19.com.br 6 .Banco de dados www.

alterar e remover registros respectivamente. Essas operações são realizadas através da linguagem de consulta denominada SQL. SELECT. ler. alterar e remover. UPDATE e DELETE. 1.Banco de dados Se uma tabela não for mais desejada ela pode ser removida através do comando DROP TABLE. 7 K19 Treinamentos . ler.3 Operações Básicas As operações básicas para manipular os dados das tabelas são: inserir. Esta linguagem oferece quatro comandos básicos: INSERT. Estes comandos são utilizados para inserir.

br 8 .Banco de dados www.k19.com.

Banco de dados 9 K19 Treinamentos .

k19.br 10 .Banco de dados www.com.

podemos adicionar um campo numérico chamado editora_id que deve ser utilizado para guardar o valor da chave primária da editora correspondente ao livro. Para armazenar esses dados. com esse nome. poderíamos adicionar um campo numérico na tabela Editora e torná-lo chave primária. será necessário descobrir qual é a editora de um determinado livro ou quais são os livros de uma determinada editora. há um problema nessa abordagem. Para resolver esse problema no MySQL Server. Normalmente. Porém ainda teríamos mais um problema: na tabela livro poderíamos adicionar registros com editoras inexistentes. Dessa forma. Toda tabela pode ter uma chave primária.Banco de dados 1. se alguém quiser recuperar as informações da editora de um determinado livro. devemos utilizar o conceito de chave primária e chave estrangeira. um livro não pode ser inserido com o valor do campo editora_id inválido. eventualmente. deve consultar a tabela Editora para obter as informações da editora. poderíamos adicionar uma coluna para armazenar o nome da editora a qual ele pertence. Além disso. que é um conjunto de um ou mais campos que devem ser únicos para cada registro. teríamos duas tabelas (Livro e Editora). poderíamos adicionar a propriedade UNIQUE no campo nome da tabela Editora. não conseguiríamos descobrir os dados corretos da editora de um determinado livro. descobrir todos os livros de uma determinada editora. Para isso. Depois. Por exemplo. Dessa forma. Nesse momento. Para estabelecer esse vínculo o campo editora_id deve ser uma chave estrangeira associada ao campo id. 1. Uma editora possui nome e telefone. Para solucionar estes problemas. Na tabela Livro. os registros da tabela Editora devem estar relacionados aos da tabela Livro. uma nova tabela deve ser criada. Vamos chamar esse campo de id. deveríamos criar uma restrição na tabela Editora que proíba a inserção de editoras com o mesmo nome. um campo numérico é escolhido para ser a chave primária de uma tabela. Uma chave estrangeira é um conjunto de uma ou mais colunas de uma tabela que possuem valores iguais aos da chave primária de outra tabela. 11 K19 Treinamentos . Caso tentássemos obteríamos uma mensagem de erro.4 Chaves Primária e Estrangeira Suponha que os livros da nossa livraria são separados por editoras. Na tabela Livro.5 Consultas Avançadas Com o conceito de chave estrangeira. Eventualmente. pois não há nenhum vínculo explícito entre as tabelas. o campo editora_id deve estar explicitamente vinculado com o campo id da tabela Editora. Para resolver esse problema. deve consultar a tabela Livro para obter o nome da editora correspondente. pois as consultas podem ser realizadas com melhor desempenho. Então. a tabela Editora aceita duas editoras com o mesmo nome. Porém. podemos fazer consultas complexas envolvendo os registros de duas ou mais tabelas. Com a definição da chave estrangeira.

br 12 . Abra o MySQL Query Browser utilizando localhost como Server Hostname. Caso exista uma base de dados chamada Livraria. 2.k19. root como Username e root como Password. remova-a conforme a figura abaixo: www.Banco de dados 1.com.6 Exercícios 1.

Crie uma nova base de dados chamada livraria. Você vai utilizar esta base nos exercícios seguintes. 13 K19 Treinamentos . conforme mostrado na figura abaixo. Selecione a base de dados livraria como padrão.Banco de dados 3. 4.

www. Crie uma tabela chamada Editora conforme as figuras abaixo. Altere o modo de criação da tabela para InnoDB. conforme mostrado na figura.br 14 .com.Banco de dados 5.k19.

15 K19 Treinamentos . Além disso o campo id deve ser uma chave primária e automaticamente incrementada. marcando a opção NOT NULL.Banco de dados Crie os campos conforme a figura e não esqueça de tornar todos os campos obrigatórios.

Crie uma tabela chamada Livro conforme as figuras abaixo: Altere o modo de criação da tabela para InnoDB.k19.Banco de dados 6. www.br 16 .com. conforme mostrado na figura.

adicione os campos conforme a figura abaixo. lembrando de marcar a opção NOT NULL. Além disso o campo id deve ser uma chave primária e automaticamente incrementada.Banco de dados Novamente. 17 K19 Treinamentos .

k19.Banco de dados Você precisa tornar o campo editora_id em uma chave estrangeira.br 18 . www. Selecione a aba Foreign Keys e clique no botão com o símbolo de mais para adicionar uma chave estrangeira.com. Depois siga os procedimentos conforme mostrados na figura abaixo.

Banco de dados 7. Veja exemplos na figura abaixo: 19 K19 Treinamentos . Adicione alguns registros na tabela Editora.

Veja exemplos na figura abaixo: www.br 20 .com.Banco de dados 8. Adicione alguns registros na tabela Livro.k19.

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

Veja o exemplo abaixo: www.k19.br 22 .Banco de dados 10.com. Veja o exemplo abaixo: 11. Altere alguns dos registros da tabela Livro. Altere alguns dos registros da tabela Editora.

Remova alguns registros da tabela Livro.Banco de dados 12. Veja o exemplo abaixo: 23 K19 Treinamentos .

k19. Faça uma consulta para buscar todos os livros de uma determinada editora.com.Banco de dados 13. Preste atenção para não remover uma editora que tenha algum livro relacionado já adicionado no banco. Veja o exemplo abaixo: 14.br 24 . Veja um exemplo na figura abaixo: www. Remova alguns registros da tabela Editora.

Banco de dados 25 K19 Treinamentos .

Banco de dados

www.k19.com.br

26

Capítulo 2 JDBC
No capítulo anterior, aprendemos que utilizar bancos de dados é uma boa solução para o armazenamento dos dados de uma aplicação. Entretanto, você deve ter percebido que a interface de utilização do MySQL (e dos outros bancos de dados em geral) não é muito amigável. A desvantagem deste tipo de interface, é que ela exige que o usuário conheça a sintaxe da linguagem SQL para escrever as consultas. Além disso, quando o volume de dados é muito grande, é mais difícil visualizar os resultados. Na prática uma aplicação com interface simples é desenvolvida para permitir que os usuários do sistema possam manipular os dados do banco, evitando desse modo que um usuário necessite conhecer SQL. Por isso, precisamos fazer com que essa aplicação consiga se comunicar com o banco de dados utilizado no sistema.

2.1

Driver

Como a aplicação precisa conversar com o banco de dados, ela deve trocar mensagens com o mesmo. O formato das mensagens precisa ser definido previamente. Por questões de economia de espaço, cada bit de uma mensagem tem um significado diferente. Resumidamente, o protocolo de comunicação utilizado é binário. Mensagens definidas com protocolos binários são facilmente interpretadas por computadores. Por outro lado, são complexas para um ser humano compreender. Dessa forma, é mais trabalhoso e mais suscetível a erro desenvolver uma aplicação que converse com um banco de dados através de mensagens binárias. Para resolver esse problema e facilitar o desenvolvimento de aplicações que devem se comunicar com bancos de dados, as empresas que são proprietárias desses bancos oferecem os drivers de conexão. Os drivers de conexão atuam como “tradutores” de comandos escritos em uma determinada linguagem de programação para comandos no protocolo do banco de dados. Do ponto de vista do desenvolvedor da aplicação, não é necessário conhecer o complexo protocolo binário do banco. Em alguns casos, o protocolo binário de um determinado banco de dados é fechado. Consequentemente, a única maneira de se comunicar com o banco de dados é através de um driver de conexão. 27

JDBC

2.2

JDBC

Suponha que os proprietários dos bancos de dados desenvolvessem os drivers de maneira totalmente independente. Consequentemente, cada driver teria sua própria interface, ou seja, seu próprio conjunto de instruções. Dessa maneira, o desenvolvedor da aplicação precisa conhecer as instruções de cada um dos drivers dos respectivos bancos que ele for utilizar. Para facilitar o trabalho do desenvolvedor da aplicação, foi criado o JDBC (Java Database Connectivity). O JDBC é uma API que generaliza a interface com os banco de dados. Assim, quando uma empresa proprietária de um banco de dados pretende desenvolver um driver para ser utilizado com a linguagem Java, ela segue a especificação JDBC com o intuito de incentivar a adoção do driver.

2.3

Instalando o Driver JDBC do MySQL Server

O driver oficial JDBC desenvolvido para funcionar com o MySQL se chama MySQL Connector/J. É necessário fazer o download do driver na seguinte url: http://www.mysql.com/downloads/connector/j/. É só descompactar o arquivo e depois incluir o jar com o driver no BUILD PATH da aplicação.

2.4

Criando uma conexão

Com o driver de conexão JDBC adicionado ao projeto, já é possível criar uma conexão com o banco de dados correspondente. Abaixo, estão os passos necessários para criar uma conexão. • Escolher o driver de conexão; • Definir a localização do banco de dados; • Informar o nome da base de dados; • Ter um usuário e senha cadastrados no banco de dados. As informações sobre o driver, localização e nome da base de dados são definidas no que chamamos de url de conexão (ou string de conexão). O usuário e a senha, informamos no momento de criar uma conexão. Para criar esta conexão, utilizamos as classes D RIVER M ANAGER (que instancia a conexão) e C ONNECTION (que armazena a nossa conexão), ambas presentes no pacote JAVA . SQL.
1 2 3 4 5 6 7 8 String urlDeConexao = "jdbc:mysql://localhost/livraria"; String usuario = "root"; String senha = ""; try { Connection conn = DriverManager.getConnection(urlDeConexao, usuario, senha); } catch (SQLException e) { e.printStackTrace(); }

www.k19.com.br

28

2.com. email)" + "VALUES (’K19’. 4. devemos fechar a conexão através do método CLOSE (). 1 2 string textoDoComando = "INSERT INTO Editora (nome.13.1.br’). ’contato@k19. Quando não desejamos executar mais comandos.1.execute(). JAR ao build path (veja figura). iremos inserir registros em uma tabela. Crie uma pasta chamada lib no projeto JDBC. Em seguida.JAVA -5. devemos “pedir” para uma conexão JDBC através do método PREPARE S TATE criar o comando que queremos executar. Este método devolve um objeto da interface P REPARED S TATEMENT.BIN . 1 close.". Podemos utilizar a mesma conexão para executar diversos comandos.JAVA -5.close(). comando.6 Exercícios 1. 29 K19 Treinamentos . 3. Fechar as conexões que não são mais necessárias é importante pois os SGBD’s possuem um número limitado de conexões abertas.CONNECTOR . MENT () 1 2 3 4 5 // criando comando PreparedStatement comando = conexao.JDBC 2. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da Área de Trabalho e copie o arquivo MYSQL . // executando o comando comando.CONNECTOR .5 Inserindo registros Estabelecida a conexão com o banco de dados. já podemos executar comandos.1. Adicione o arquivo MYSQL . O comando não é executado na chamada do método PREPARE S TA TEMENT () e sim posteriormente quando o método EXECUTE () for utilizado. 2. O primeiro passo para executar um comando é defini-lo em linguagem SQL. Como primeiro exemplo.close().prepareStatement(textoDoComando). Crie um projeto java no eclipse chamado JDBC. JAR para pasta lib do projeto JDBC.

br 30 . e adicione o seguinte conteúdo ao arquivo: www.com. com o nome InsereEditora.k19. Crie uma nova classe.JDBC 5.

Scanner entrada = new Scanner(System. Os dados obtidos do usuário através do teclado não são tratados antes de serem enviados para o banco de dados. java. senha).getConnection(stringDeConexao.in). String textoDoComando = "INSERT INTO Editora (nome. email) " + "VALUES (’" + nome + "’.out..println("Digite o email da editora: ").7 SQL Injection Apesar de funcional.prepareStatement(textoDoComando). System.out. System. try { System.DriverManager.println("Executando comando. Connection conexao = DriverManager. ’" + email + "’)".").util.. a implementação da inserção de registros feita anteriormente apresenta uma falha grave.. conexao.nextLine().PreparedStatement. 6.."). Esses dados podem conter algum carácter especial que altere o comportamento desejado da consulta impedindo que algum registro seja inserido corretamente ou até abrindo uma brecha para que um usuário mal intencionado execute alguma consulta SQL para utilizar de maneira inadequada os dados da nossa aplicação.sql. String usuario = "root".println("Digite o nome da editora: "). java.").println("Abrindo conexao.. String senha = "root".close(). String email = entrada.out. ao exercício anterior crie um programa para inserir livros.sql. comando. public class InsereEditora { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria". System.JDBC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import import import import java. 2.printStackTrace().out.execute().sql.Connection..nextLine().Scanner. } catch (Exception e) { e.out. PreparedStatement comando = conexao.println("Fechando conexao. String nome = entrada. System. } } } Rode e veja se o registro foi inserido com sucesso na base de dados. (Opcional) Analogamente. java. usuario. 31 K19 Treinamentos .

k19. etc. nome).prepareStatement(textoDoComando). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // lendo a entrada feita pelo usuario System.setString(1. variando conforme o tipo do campo que foi definido no banco.out. A desvantagem desse processo é que. ?)". comando. Isso é feito com o método SET S TRING .com. por exemplo: ponto-e-vírgula e apóstrofo.println("Digite o email da editora: ").nextLine().setString(2. pois o “\” não é padronizado e cada banco tem o seu próprio método de escape de caracteres especiais. Os métodos acima mostrados. www. que recebe o índice (posição) do parâmetro na consulta e o valor correspondente.JDBC O problema de SQL Injection pode ser resolvido manualmente. Observe que a sentença SQL foi definida com parâmetros através do carácter “?”. Para tornar mais prática a comunicação com o banco de dados. é diferente para cada banco de dados. email) " + "VALUES (?. além de trabalhoso. realizam a tarefa de “sanitizar”(limpar) os valores enviados pelo usuário. Basta fazer “escape” dos caracteres especiais. String nome = entrada. // texto do comando inclui parâmetros String textoDoComando = "INSERT INTO Editora (nome. o próprio driver faz o tratamento das sentenças SQL. De maneira similar.br 32 . os caracteres especiais devem ser precedidos pelo carácter “\”. Esse processo é denominado sanitize. // criação e adição de parâmetros ao comando PreparedStatement comando = conexao. SET D OUBLE. email). SET DATE. Então seria necessário acrescentar \ em todas as ocorrências de caracteres especiais nos valores passados pelo usuário. é necessário atribuir valores aos parâmetros.println("Digite o nome da editora: "). String email = entrada. temos os métodos SET I NT.out.nextLine(). Antes de executar o comando. System. No MySQL Server. comando.

nextLine().setString(2. String textoDoComando = "INSERT INTO Editora (nome.close().").in). String senha = "root".setString(1. usuario. 33 K19 Treinamentos . String email = entrada.8 Exercícios 7. } catch (Exception e) { e. Agora tente causar novamente o problema de SQL Injection ao inserir novas editoras. email) " + "VALUES (?. System. try { System. comando. Altere o código para eliminar o problema do SQL Injection.JDBC 2. Connection conexao = DriverManager. PreparedStatement comando = conexao..println("Digite o nome da editora: "). ?)".println("Executando comando. ← senha).println("Digite o email da editora: ").").. comando. Tente causar um erro de SQL Injection na classe feita no exercício de inserir editoras.out.nextLine()..prepareStatement(textoDoComando). String nome = entrada.getConnection(stringDeConexao. System.out. comando. Você deve deixar a classe com o código abaixo: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class InsereEditora { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria".println("Fechando conexao. conexao.execute()..9 Listando registros O processo para executar um comando de consulta é bem parecido com o processo de inserir registros.").out.out. } } } 9.. 2. (Dica: tente entradas com aspas simples) 8.out. String usuario = "root". nome). System. Scanner entrada = new Scanner(System. System. email)..println("Abrindo conexao.printStackTrace().

getString("email").next(). ResultSet resultado = comando. Esse método devolve um objeto da interface JAVA . 1 2 3 4 5 while(resultado. Agora.".getString("nome"). String email1 = resultado.out.prepareStatement(textoDoComando). } 2. String nome1 = resultado.getString("email"). que é responsável por armazenar os resultados da consulta. int id2 = resultado.getString("nome").getInt("id"). GET I NT . System. etc.getString("nome"). Adicione uma nova classe ao projeto chamada ListaEditoras. String email = resultado. www.R ESULT S ET . Adicione o seguinte código à esta classe.println("Executando comando. Insira algumas editoras utilizando a classe I NSERE E DITORA que você criou nos exercícios acima. O objetivo é listar as editoras que foram salvas no banco.getInt("id").10 Exercícios 10. String nome2 = resultado.com. Os dados contidos no R ESULT S ET podem ser acessados através de métodos.getString("email").. GET D OUBLE. Esses métodos recebem como parâmetro uma string referente ao nome da coluna correspondente.getString("email"). String email = resultado. O próprio método NEXT devolve um valor booleano para indicar se o R ESULT S ET conseguiu avançar para o próximo registro.br 34 . 1 2 3 int id = resultado.getInt("id").executeQuery(). Quando esse método devolver FALSE significa que não há mais registros para serem consultados. de acordo com o tipo do campo.next()) { int id = resultado. String nome = resultado. O código acima mostra como os campos do primeiro registro da consulta são recuperados..").getInt("id"). PreparedStatement comando = conexao.JDBC 1 2 3 4 5 6 String textoDoComando = "SELECT * FROM Editora. como o GET STRING . String email2 = resultado. 11. resultado. A diferença é que para executar um comando de consulta é necessário utilizar o método EXECUTE Q UERY () ao invés do EXECUTE ().k19. String nome = resultado. para recuperar os outros registros é necessário avançar o R ESULT S ET através do método NEXT . 1 2 3 4 5 6 7 8 9 int id1 = resultado.getString("nome"). SQL .

. Teríamos que alterar o código da nossa aplicação em muitos lugares. public class ListaEditoras { public static void main(String[] args) { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria".JDBC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import import import import java. ResultSet resultado = comando.next()) { System. usuario. Connection conexao = DriverManager. System.getInt("id"). Para diminuir o trabalho de manutenção. senha).println("Abrindo conexao. mais precisamente. Nessa e somente nessa classe estaria definida a url de conexão. 35 K19 Treinamentos .ResultSet.. em cada ocorrência da url de conexão.".out. A probabilidade de algum ponto não ser corrigido é grande. nós poderíamos criar uma classe responsável pela criação e distribuição de conexões.sql. java.println("Resultados encontrados: \n").getConnection(stringDeConexao. PreparedStatement comando = conexao.sql.."). resultado. só acarreta mudanças nesta classe. String senha = "root".getString("nome").sql.DriverManager.out. while (resultado. resultado.").PreparedStatement. Dessa forma. String usuario = "root".. Imagine que o driver do banco seja atualizado ou que o ip do SGBD seja alterado.println("\nFechando conexao. try { System.out.close().Connection. System. } } } 2.prepareStatement(textoDoComando).printf("%d : %s .printStackTrace().sql. } System. Se a url de conexão for definida em cada um desses pontos teremos um problema de manutenção..%s\n".out.getString("email")).11 Fábrica de conexões (Factory) Você deve ter percebido que em diversos pontos diferentes da nossa aplicação precisamos de uma conexão JDBC. java.out.executeQuery(). java. resultado.. } catch (Exception e) { e. conexao.println("Executando comando. String textoDoComando = "SELECT * FROM Editora. qualquer alteração no modo em que nos conectamos à base de dados.").

Adicione uma nova classe chamada FABRICA D E C ONEXAO e adicione o seguinte código: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.SQLException.com. import java.printStackTrace().sql. 15.sql. } return conexao.Connection. usuario. } } 13. 2.br 36 .C RIAC ONEXAO (). } catch (SQLException e) { e. String usuario = "root". O resto do sistema não precisa mais conhecer os detalhes sobre a criação das conexões com o banco de dados. Execute-as novamente. www. String senha = "root". Altere as classes I NSERE E DITORA e L ISTA E DITORAS para que elas utilizem a fábrica de conexão. Connection conexao = null.12 Exercícios 12. diminuindo o acoplamento da aplicação. senha).getConnection(stringDeConexao. (Opcional) Implemente um teste que remove uma editora pelo id.sql. try { conexao = DriverManager. 14.k19. } } Agora podemos obter uma nova conexão apenas chamando FABRICA D E C ONEXAO .printStackTrace(). } catch (SQLException e) { e. import java. senha).getConnection(stringDeConexao. } return conexao. public class FabricaDeConexao { public static Connection CriaConexao() { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria".DriverManager. Connection conexao = null. try { conexao = DriverManager. (Opcional) Implemente um teste que altera os dados de uma editora pelo id. usuario. String senha = "root". String usuario = "root".JDBC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class FabricaDeConexao { public static Connection criaConexao() { String stringDeConexao = "jdbc:mysql://localhost:3306/livraria".

3. Desse modo. ao utilizar uma ferramenta de ORM. voltado à uma interface ou especificação. é que a sintaxe da linguagem SQL. classes podem ser mapeadas para tabelas. Seria bom se. utilizam o paradigma orientado a objetos. O banco de dados é organizado seguindo o modelo entidade relacionamento. atributos para campos e referência entre objetos para chaves estrangeiras. Por exemplo. os desenvolvedores teriam que aprender as diferenças entres as sintaxes do SQL correspondentes aos banco de dados que ele utilizará. Outra consequência. é que não é necessário escrever consultas em SQL. podemos utilizar ferramentas que automatizam a transição de dados entre as aplicações e os diferente bancos de dados e que são conhecidas como ferramentas de ORM (Object Relational Mapper). pode variar conforme o banco de dados que está sendo utilizado. Para realizar essa transição. é necessário definir um mapeamento entre os conceitos desses dois paradigmas. Uma desvantagem dessa abordagem. objetos para registros. você aprendeu a utilizar a especificação JDBC para fazer uma aplicação Java interagir com um banco de dados. A transição de dados entre o modelo entidade relacionamento e o modelo orientado a objetos não é simples.Capítulo 3 JPA 2 e Hibernate 3. apesar de parecida.2 Orientação a Objetos VS Modelo Entidade Relacionamento Outro problema na comunicação entre uma aplicação Java e um banco de dados é o conflito de paradigmas.3 Ferramentas ORM Para facilitar a comunicação entre aplicações Java que seguem o modelo orientado a objetos e os banco de dados que seguem o modelo entidade relacionamento. assim poderíamos escrever o código independente de SQL. pois a própria ferramenta gera as consultas de acordo com a sintaxe da 37 . geralmente. 3.1 Múltiplas sintaxes da linguagem SQL No capítulo anterior. ao invés de programar direcionado a um determinado banco de dados. pudéssemos programar de uma maneira mais genérica. Essa interação é realizada através de consultas escritas em SQL. enquanto as aplicações Java.

com. As outras implementações de JPA mais conhecidas são: TopLink. Assim podemos programar voltado à especificação e substituir uma implementação pela outra. A url do site oficial do Hibernate é esta: (http://www. EclipseLink e OpenJPA. utilizaremos a versão 3. Neste curso. Mas.1. A principal ferramenta ORM para Java utilizada no mercado de TI é o Hibernate. Para isso. O conteúdo desse arquivo possuíra informações sobre o banco de dados.k19.org/) Para configurar o Hibernate em uma aplicação. Claro que teríamos que alterar alguns arquivos de configuração.xml. usuário e senha. essa especificação está na sua segunda versão. XML : www. a especificação JPA (Java Persistence API) foi criada com o objetivo de padronizar as ferramentas ORM para aplicações Java e consequentemente diminuir a complexidade do desenvolvimento. mas o código da aplicação permaneceria o mesmo. utilizamos alguma das diversas implementações da JPA. O arquivo PERSISTENCE . sem precisar reescrever o código da nossa aplicação. Ela específica um conjunto de classes e métodos que as ferramentas de ORM devem implementar. 3. é necessário baixar no site oficial o bundle que inclui os jar’s do hibernate e todas as suas dependências. Optamos por utilizar o Hibernate por ele ser o mais antigo e mais utilizado atualmente. Além de dados sobre a implementação de JPA que será utilizada. Atualmente. Caso você queira utilizar outro framework ORM.JPA 2 e Hibernate linguagem SQL correspondente ao banco que está sendo utilizado. utilizaremos o Hibernate como implementação de JPA.hibernate. como a url de conexão. existem outras que possuem o mesmo objetivo.4 O que é JPA e Hibernate Após o sucesso do Hibernate. Veja abaixo um exemplo de configuração para o PERSIS TENCE . poderá aplicar os conceitos aqui aprendidos justamente por que eles seguem a mesma especificação. XML deve estar em uma pasta chamada META-INF. devemos criar um arquivo chamado persistence. Veja que a JPA é apenas uma especificação. 3. que deve estar no classpath da aplicação.5 Configuração Antes de começar a utilizar o Hibernate.br 38 . Neste curso.5. ela não implementa nenhum código.

Este mapeamento pode ser definido através de xml ou de maneira mais prática com anotações Java. Ela que deve aparecer antes do nome de uma classe.sun.jdbc.jdbc.com/xml/← ns/persistence/persistence_1_0. 39 K19 Treinamentos . Geralmente o atributo anotado com @I D é do tipo L ONG.JPA 2 e Hibernate 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.driver" value="com. podemos alterar esse padrão utilizando a anotação @C OLUMN. Outra vez.persistence.hibernate. evitamos a criação de extensos arquivos em xml. As classes anotadas com @E NTITY são mapeadas para tabelas.persistence.w3.mysql. A seguir veremos as principais anotações Java de mapeamento do JPA.dialect. @Entity É a principal anotação do JPA.url" value="jdbc:mysql://← localhost:3306/k19"/> </properties> </persistence-unit> </persistence> A propriedade hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.Driver← "/> <property name="javax. Mas.hibernate. as tabelas possuem os mesmos nomes das classes.xsd" version="1.persistence. por convenção.sun.jdbc. podemos alterar esse comportamento utilizando a anotação @TABLE. as colunas possuem os mesmos nomes dos atributos. E deve ser definida em todas as classes que terão objetos persistidos no banco de dados.password" value="senha"/> <property name="javax.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.auto" value="create"/> <property name="javax. Por convenção.dialect permite que a aplicação escolha qual sintaxe de SQL que deve ser utilizada pelo Hibernate. no momento em que um novo registro é inserido. @GeneratedValue Geralmente vem acompanhado da anotação @I D. Essas anotações estão no pacote javax.6 Mapeamento Um dos principais objetivos dos frameworks ORM é estabelecer o mapeamento entre os conceitos do modelo orientado a objetos e os conceitos do modelo entidade relacionamento.← MySQL5InnoDBDialect"/> <property name="hibernate. Serve para indicar que o atributo é gerado pelo banco.persistence.sun. @Id Utilizada para indicar qual atributo de uma classe anotada com @E NTITY será mapeado para a chave primária da tabela correspondente à classe.0"> <persistence-unit name="K19" transaction-type="RESOURCE_LOCAL"> <provider>org. 3.jdbc.com/xml/ns/persistence http://java.hbm2ddl.persistence.jdbc.user" value="usuario"/> <property name="javax. E novamente.com/xml/ns/persistence" xmlns:xsi="http://www.dialect" value="org. Quando utilizamos anotações. Os atributos declarados em uma classe anotada com @E NTITY são mapeados para colunas na tabela correspondente à classe.0" encoding="UTF-8"?> <persistence xmlns="http://java.

pelo nome. ou arquivos binários contendo imagens ou sons que serão persistidos no banco de dados. // . tanto data quanto hora são armazenados no banco de dados.JPA 2 e Hibernate @Table Utilizada para alterar o nome padrão da tabela. @Temporal Utilizado para atributos do tipo C ALENDAR ou DATE. B YTE [].. @Lob Utilizado para atributos que armazenam textos muito grandes. HBM 2 DDL . você pode mudar através dessa anotação. As tabelas são geradas através de método da classe P ERSISTENCE. O parâmetro ENTITY U NIT permite escolher. no qual os nomes das colunas já foram definidos. uma unidade de persistência definida no PERSISTENCE . @Column Utilizado para alterar o nome da coluna que será utilizado na tabela. é que ele é capaz de gerar as tabelas do banco para a nossa aplicação. Ele faz isso de acordo com as anotações colocadas nas classes e as informações presentes no PERSISTENCE . podemos mandar persistir somente a data ou sementã a hora.. A política de criação das tabelas pode ser alterada configurando a propriedade HIBER NATE .DATE) private Calendar publicacao. BYTE [] ou JAVA . Caso você esteja utilizando um banco de dados legado.br 40 . o CREATE E NTITY M A NAGER FACTORY ( STRING ENTITY U NIT )..com. SQL . Além disso. 1 2 3 4 @Entity public class Editora { @Column(name="publisher_name". Ela recebe o parâmetro name para indicar qual nome que deve ser utilizado na tabela.nullable=false) private String nome.B LOB. Podemos. XML . @Transient Serve para indicar um atributo que não deve ser persistido. O tipo do atributo deve ser S TRING. com a anotação @T EMPORAL. os atributos anotados com @T RANSIENT não são mapeados para colunas. ou seja. 3. Veja o exemplo: 1 2 3 4 @Table(name="Publisher") @Entity public class Editora { // .. Mas. 1 2 3 4 5 @Entity public class Livro { @Temporal(TemporalType. podemos estabelecer certas restrições. por exemplo.7 Gerando o banco Uma das vantagens de utilizar o Hibernate. XML. como determinar se o campo pode ou não ser nulo. Por padrão. AUTO no arquivo PERSISTENCE .k19. XML. fazer com www.

2.xml na pasta META-INF. Crie um projeto no eclipse chamado JPA2-Hibernate e feche o projeto JDBC para não gerar confusão na hora de manipular os arquivos. AUTO com o valor CREATE .8 Exercícios 1.JAVA -5. Crie uma pasta chamada META-INF na pasta src no projeto JPA2-Hibernate. 9. Crie uma pasta chamada lib dentro do projeto JPA2-Hibernate. HBM 2 DDL . é configurar o Hibernate para simplesmente atualizar as tabelas de acordo com as mudanças nas anotações sem removê-las.13.hbm2ddl.16. basta configurar a propriedade BERNATE .CONNECTOR . JAR para pasta lib do projeto JPA2-Hibernate. JAR para pasta lib do projeto JPA2Hibernate. HBM 2 DDL . 1 <property name="hibernate.1. Entre na pasta K19-Arquivos/Log4J da Área de Trabalho e copie o arquivo 1. BIN . 8. 3. Nesse caso. Entre na pasta K19-Arquivos/SLF4J da Área de Trabalho e copie os jar’s para pasta lib do projeto JPA2-Hibernate. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da Área de Trabalho e copie o arquivo MYSQL .auto" value="create-drop"/> HI - Uma outra opção. Adicione os jar’s da pasta lib ao build path do projeto JPA2-Hibernate.auto" value="update"/> 3.hbm2ddl. 1 <property name="hibernate. 4. Crie o arquivo de configurações persistence. o valor da propriedade HIBER NATE . 6.JPA 2 e Hibernate que o Hibernate sempre sobrescreva as tabelas existentes. AUTO deve ser UPDATE . 41 K19 Treinamentos LOG 4 J - . 5. Entre na pasta K19-Arquivos/Hibernate da Área de Trabalho e copie os jar’s do Hibernate para a pasta lib do projeto JPA2-Hibernate.DROP .2. 7.

CONSOLE.com/xml/ns/persistence" xmlns:xsi="http://www.user" value="root"/> <property name="javax.0" encoding="UTF-8"?> <persistence xmlns="http://java.auto" value="create"/> <property name="javax. Gere as tabelas através da classe P ERSISTENCE. private String email.dialect" value="org.jdbc.hibernate.com/xml/← ns/persistence/persistence_1_0. crie uma classe com método MAIN . private String nome.hibernate.sun.br 42 . www. Apague a tabela Livro e depois a Editora.sun.jdbc. Obs: As classes devem ser importadas do pacote JAVAX .← MySQL5InnoDBDialect"/> <property name="hibernate.com.password" value="root"/> <property name="javax.layout=org.jdbc.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.log4j.k19. 12.dialect.com/xml/ns/persistence http://java.xsd" version="1. Para isso.persistence. Crie uma classe para modelar as editoras da nossa livraria e acrescente as anotações necessárias para fazer o mapeamento.appender.rootCategory=INFO.hbm2ddl.ConsoleAppender log4j.persistence.Driver← "/> <property name="javax. CONSOLE log4j.sun.%m%n 13. Configure o Log4J criando um arquivo chamado log4j.ConversionPattern=%r [%t] %-5p %c .persistence.properties na pasta src do projeto JPA2-Hibernate. PERSISTENCE .jdbc.w3.apache. Obs: As anotações devem ser importadas do pacote JAVAX . 1 2 3 4 5 6 7 8 9 10 11 @Entity public class Editora { @Id @GeneratedValue private Long id.persistence.jdbc. // GETTERS AND SETTERS } 11.layout.mysql. PERSISTENCE .JPA 2 e Hibernate 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?xml version="1.driver" value="com.url" value="jdbc:mysql://← localhost:3306/livraria"/> </properties> </persistence-unit> </persistence> 10.appender.ejb.CONSOLE.PatternLayout log4j.HibernatePersistence</provider> <properties> <property name="hibernate.CONSOLE=org. log4j.0"> <persistence-unit name="livraria" transaction-type="RESOURCE_LOCAL"> <provider>org.apache.appender.log4j.

createEntityManager().find(Editora.getReference(Editora. EntityManager manager = factory. devemos utilizar um E NTITY M ANAGER que é obtido através de uma E NTITY M ANAGER FACTORY. 1 2 3 4 5 Editora novaEditora = new Editora(). 3. 3.createEntityManagerFactory("livraria"). 1L). 3.1 Persistindo Para armazenar as informações de um objeto no banco de dados basta utilizar o método PERSIST () do E NTITY M ANAGER . manager. 43 K19 Treinamentos .setNome("K19 .createEntityManagerFactory("K19").setEmail("contato@k19.class. 2L). Editora editora1 = manager.persist(novaEditora). A diferença entre os dois métodos básicos de busca FIND () e GET R EFERENCE () é que o primeiro recupera os dados desejados imediatamente já o segundo posterga até a primeira chamada de um método GET do objeto.close() } } Através do MySQL Query Browser verifique se a tabela E DITORA foi criada corretamente.9.Livros") novaEditora.JPA 2 e Hibernate 1 2 3 4 5 6 7 8 public class GeraTabelas { public static void main(String[] args) { EntityManagerFactory factory = Persistence.br"). factory. 1 2 3 4 EntityManagerFactory factory = Persistence.2 FIND () 1 2 Buscando Para obter um objeto que contenha informações do banco de dados basta utilizar o método ou o GET R EFERENCE () do E NTITY M ANAGER.class.9. novaEditora. Editora editora2 = manager.9 Manipulando entidades Para manipular as entidades da nossa aplicação.com.

www.getResultList().class. Essa sincronização deve ser realizada através de uma transação JPA criada pelo E NTITY M ANAGER que administra os objetos que desejamos sincronizar.9.class. 3. 1L).getTransaction().flush().9. 1L).6 Transações As modificações realizadas nos objetos administrados por um E NTITY M ANAGER são mantidas em memória. manager. editora.br 44 .createQuery("SELECT e FROM Editora e"). Editora editora1 = manager.9.remove(editora1).Livros e Publicações").9. 3. FLUSH () 1 2 3 4 5 Com a transação aberta podemos sincronizar os dados com o banco através do método ou COMMIT ().begin().4 Atualizando Para alterar os dados de um registro correspondente a um objeto basta utilizar os próprios métodos setters desse objeto. é necessário sincronizar os dados da memória com os dados do banco de dados.find(Editora.find(Editora. devemos utilizar a linguagem de consulta do JPA.JPA 2 e Hibernate 3. List<Editora> editoras = query. 3.getTransaction(). 1 2 Editora editora1 = manager. 1 2 Query query = manager.3 Removendo REMOVE () Para remover um registro correspondente a um objeto basta utilizar o método do E NTITY M ANAGER.setNome("K19 . Para abrir uma transação utilizamos o método BEGIN ().class. A vantagem do JPQL em relação ao SQL é que a sintaxe é a mesma para bancos de dados diferentes. 1 2 Editora editora1 = manager.setNome("K19 . manager. manager.com.5 Listando Para obter uma listagem com todos os objetos referentes aos registros de uma tabela.find(Editora. editora. 1L).Livros e Publicações").k19. 1 manager. Em certos momentos. a JPQL que é muito parecida com a linguagem SQL.begin().

factory.println("Digite o nome da editora: "). System. Crie um teste para inserir editoras no banco de dados.setNome(entrada. Assim as tabelas não serão recriadas a cada execução e sim apenas atualizadas. novaEditora.commit(). No arquivo de configurações PERSISTENCE .nextLine()). manager.setEmail(entrada. manager. System. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class InsereEditoraComJPA { public static void main(String[] args) { EntityManagerFactory factory = Persistence. } } 16.out. XML.createEntityManager().nextLine()). manager. Editora novaEditora = new Editora().begin().getTransaction(). 3.println("Digite o email da editora: ").getTransaction().Livros e Publicações").setNome("K19 . EntityManager manager = factory. AUTO para UPDATE .close(). altere o valor da propriedade HIBER NATE .begin().10 Exercícios 14. novaEditora. editora.JPA 2 e Hibernate 1 2 3 4 5 Editora editora1 = manager. 45 K19 Treinamentos .class. Crie um teste para listar as editoras inseridas no banco de dados.find(Editora.out.getTransaction().createEntityManagerFactory("livraria").getTransaction(). manager. 15. HBM 2 DDL . 1L).in).commit(). manager.persist(novaEditora). Scanner entrada = new Scanner(System.

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

3.11

Repository

A interface E NTITY M ANAGER do JPA oferece recursos suficientes para que os objetos do domínio sejam recuperados ou persistidos no banco de dados. Porém, em aplicações com alta complexidade e grande quantidade de código, “espalhar” as chamadas aos métodos do E NTITY M ANAGER pode gerar dificuldades na manutenção e no entendimento do sistema. Para melhorar a organização das nossas aplicações, diminuindo o custo de manutenção e aumentando a legibilidade do código, podemos aplicar o padrão Repository do DDD(Domain Driven Design). Conceitualmente, um repositório representa o conjunto de todos os objetos de um determinado tipo. Ele deve oferecer métodos para recuperar e para adicionar elementos. Os repositórios podem trabalhar com objetos prontos na memória ou reconstruí-los com dados obtidos de um banco de dados. O acesso ao banco de dados pode ser realizado através de ferramenta ORM como o Hibernate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class EditoraRepository { private EntityManager manager; public EditoraRepository(EntityManager manager) { this.manager = manager; } public void adiciona(Editora e) { this.manager.persist(e); } public Editora busca(Long id) { return this.manager.find(Editora.class, id); } public List<Editora> buscaTodas() { Query query = this.manager.createQuery("SELECT e FROM Editora e"); return query.getResultList(); } }

www.k19.com.br

46

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

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

3.12

Exercícios

17. Implemente um repositório de editoras criando uma nova classe no projeto JPA2-Hibernate.

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

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

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

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

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

www.k19.com.br

48

ao desenvolver uma aplicação web. Outra necessidade das aplicações web é gerar conteúdo dinâmico. O desenvolvedor web precisa utilizar algum mecanismo eficiente que permita que o conteúdo que os usuários requisitam seja gerado dinamicamente. 49 . 4. quando um usuário de uma aplicação de email acessa a sua caixa de entrada. devemos estar preparados para receber requisições HTTP e enviar respostas HTTP. Por isso. ele deseja ver a listagem atualizada dos seus emails. é extremamente trabalhoso implementar essas características.Capítulo 4 Web Container 4. Glassfish ou WebSphere pois eles possuem um Web Container internamente. as aplicações web devem ser acessadas por diversos usuários simultaneamente. Também podemos utilizar um servidor de aplicação Java EE como o JBoss. Um Web Container é responsável pelo envio e recebimento de mensagens HTTP. A comunicação entre os navegadores e as aplicações web é realizada através de requisições e respostas definidas pelo protocolo HTTP. Por exemplo. Portando. Portanto. Dessa forma. permite que as aplicações implantadas nele sejam acessadas simultaneamente por múltiplos usuários de uma maneira eficiente e oferece mecanismos para que as aplicações gerem conteúdo dinamicamente. é fundamental que a listagem dos emails seja gerada no momento da requisição do usuário. a plataforma Java oferece uma solução para diminuir o trabalho no desenvolvimento de aplicações web. Na verdade. o desenvolvedor web precisa saber como permitir o acesso simultâneo. Além disso.1 Necessidades de uma aplicação web As aplicações web são acessadas pelos navegadores (browsers). Os dois Web Container’s mais importantes do mercado são: Tomcat e Jetty.2 Web Container Uma aplicação web Java deve ser implantada em um Web Container para obter os recursos fundamentais que as aplicações web necessitam. na grande maioria dos casos. Trabalhar diretamente com as requisições e repostas HTTP e criar um mecanismo eficiente para permitir o acesso simultâneo e para gerar conteúdo dinâmico não são tarefas simples.

Descompacte este arquivo na própria Área de Trabalho. Pare o glassfish executando o script stopserv que está na mesma pasta do script startserv. Dessa forma. 7.3 Especificação Java EE Como é comum na plataforma Java. Apesar das especificações. 5. entre na pasta glassfishv3/glassfish/bin e execute o script startserv para executar o glassfish. 4.Web Container 4. entre na pasta K19-Arquivos e copie glassfish-3.1-with-hibernate. 4. os Web Container’s possuem algumas diferenças nas configurações que devem ser realizadas pelos desenvolvedores. 3. Essas especificações fazem parte do conjunto de especificações do Java EE. 2. No eclipse.xml www. Sendo assim.k19.com. 4. se você conhece bem um dos Web Container também conhece bastante dos outros.zip para o seu Desktop. Pare o glassfish pela view servers. especificações foram definidas.4 Exercícios 1. Verifique se o glassfish está executando através de um navegador acessando a url: http://localhost:8080. O Java EE é uma especificação que agrupa diversas outras especificações. Ainda na Área de Trabalho.5 Aplicação Web Java Para que uma aplicação Web Java possa ser implantada em um Web Container. não há 100% portabilidade entre os Web Container’s. a maior parte das configurações e do modelo de programação é padronizado. para padronizar a interface dos recursos oferecidos pelos Web Container’s. abra a view servers e clique com o botão direito no corpo dela.br 50 . Execute o glassfish pela view servers e verifique se ele está funcionando acessando através de um navegador a url: http://localhost:8080.0. 6. Na Área de Trabalho. a estrutura de pastas precisa seguir algumas regras. K19-App/ pasta raiz pode ter qualquer nome WEB-INF/ classes/ lib/ web. Contudo. Escolha a opção new e configure o glassfish.

o código compilado das aplicações Web Java deve ser salvo nessa pasta. 4. Então.8 Servlet Para criar uma Servlet.http. Há duas maneiras fundamentais de gerar conteúdo dinâmico: programando uma Servlet ou um JSP. Os arquivos dentro da pasta raiz da aplicação mas fora da pasta WEB-INF podem ser acessados diretamente pelos usuários através de um navegador. 10. As IDE’s já criam toda a estrutura de pastas exigidas pelos Web Container’s.0. Crie um projeto no eclipse do tipo Dynamic Web Project chamado App-Web-Java selecionando na última tela a opção Generate web. as requisições e respostas HTTP já estão sendo processadas pelo Web Container que também já permite o acesso de múltiplos usuários à nossa aplicação. 51 K19 Treinamentos . na prática. os JSPs são “traduzidos” para Servlets automaticamente pelos Web Container’s. não temos o trabalho de criar esses diretórios manualmente. O arquivo web.xml deployment descriptor. o nome dessa pasta pode ser definido pelo desenvolvedor. Utilizar a anotação @WebServlet para definir a url que será utilizada para acessar a Servlet. 4. Herdar da classe javax. 4. 9. Execute o projeto no glassfish clicando com o botão direito no nome do projeto e escolhendo a opção Run on Server dentro de Run As. Verifique o funcionamento da nossa aplicação acessando a url: http://localhost:8080/K19-App/ através de um navegador. Antes essa configuração era realizada através do arquivo web. A pasta classes deve ser criada dentro da pasta WEB-INF.xml. Na verdade. A pasta WEB-INF deve ser criada dentro da pasta raiz de todas as aplicações Web Java. 3. Em seguida devemos definir como o conteúdo da nossa aplicação deve ser gerado.servlet.HttpServlet.xml contém configurações do Web Container e deve ser criado na pasta WEB-INF. o conteúdo dessa pasta não pode ser acessado diretamente pelos usuários. Reescrever o método service 4. Criar uma classe 2.6 Exercícios 8. Então.7 Processando requisições Após implantar a nossa aplicação web Java em um Web Container.Web Container A pasta K19-App é raiz da nossa aplicação. Essa anotação existe após a especificação de Servlet 3. escrever um JSP é apenas uma maneira diferente de escrever uma Servlet. todos os jar’s das bibliotecas que serão utilizadas devem ser colocados nessa pasta. A pasta lib deve ser criada dentro da pasta WEB-INF. podemos seguir os seguintes passos básicos: 1.

k19. 12. IOException { PrintWriter writer = resp.8.getWriter().Web Container 1 2 3 4 5 6 7 8 9 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req. } } 4.println("<html><body><h1>Olá Mundo</h1></body></html>"). Em geral. 4.com. Crie um pacote chamado servlets no projeto K19-App. HttpServletResponse resp) throws ServletException.1 Inserindo conteúdo na resposta Para inserir conteúdo na resposta HTTP que será enviada para o navegador do usuário.9 Exercícios 11. o conteúdo inserido na resposta HTTP é texto HTML.println("<html><body><h1>Olá Mundo</h1></body></html>"). IOException { PrintWriter writer = resp. 1 2 3 4 5 6 7 8 9 10 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req.getWriter(). HttpServletResponse resp) throws ServletException. writer. HttpServletResponse resp) throws ServletException.br 52 . IOException { // Lógica para processar as regras de negócio e gerar conteúdo } } Quando um usuário fizer uma requisição para url definida através da anotação @W EB S ER VLET. Crie uma classe chamada OlaMundo no pacote servlets da seguinte forma: 1 2 3 4 5 6 7 8 9 10 @WebServlet("/OlaMundo") public class OlaMundo extends HttpServlet{ @Override protected void service(HttpServletRequest req. Esse método recebe dois parâmetros: o primeiro é uma referência para um objeto da classe HttpServletRequest que guarda todos os dados da requisição HTTP realizada pelo navegador do usuário. } } www. o método service() será executado. writer. devemos utilizar o método getWriter(). o segundo é uma referência para um objeto da classe HttpServletResponse que permite que a resposta HTTP que será enviada para o navegador do usuário seja construída pela aplicação.

Essas bibliotecas são os chamados Frameworks web. Eis uma lista dos principais Frameworks web para aplicações web Java: 53 K19 Treinamentos .expression --> <%= geradorDeNumeros.10 JSP Outra maneira de criar uma Servlet é escrever um JSP.jsp 4. Verifique o funcionamento da Servlet acessando através de um navegador a url: http://localhost:8080/K19-App/OlaMundo 4.11 Exercícios 14. %> <!-. Crie um arquivo JSP chamado olaMundo. é improvável que uma empresa decida começar um projeto utilizando diretamente Servlets e JSPs pois a produtividade é pequena e a manutenção é difícil. Para criar um JSP basta adicionar um arquivo .util.jsp na pasta WebContent com o seguinte conteúdo. %> <!-. Por isso bibliotecas que definem um modelo de programação baseado no padrão MVC são utilizadas nos projetos. 1 2 3 4 5 6 7 8 9 <!-.expression --> <%= geradorDeNumeros. O código Java pode aparecer em diversos lugares. 1 2 3 4 5 6 7 8 9 <!-.util.scriptlet --> <% java. 4.Random().jsp --> <html> <body> <!-. Verifique o funcionamento do JSP acessando através de um navegador a url: http://localhost:8080/K19-App/olaMundo. dentro de scriptlets ou expressions.Random geradorDeNumeros = new java.nextInt(100) %> </body> </html> 15.util.Random().util. Por exemplo.Web Container 13.olaMundo.nextInt(100) %> </body> </html> Um arquivo JSP pode conter texto HTML e código Java.olaMundo.jsp.12 Frameworks Hoje em dia.Random geradorDeNumeros = new java. Lembrando que os JSPs são “traduzidos” para Servlets automaticamente pelos Web Containers.scriptlet --> <% java.jsp --> <html> <body> <!-.

x • Struts 2.Web Container • JSF • Struts 1.com.x • Spring MVC Nos próximos capítulos mostraremos o funcionamento e explicaremos os conceitos relacionados ao framework JSF.k19.br 54 . www.

1 Aplicação de exemplo Inspirados na sorte de um dos nossos alunos que ganhou na Loto Mania utilizando um programa que ele fez baseado em algumas dicas que o instrutor Rafael Cosentino deu a ele para gerar números aleatórios em Java. Criar uma classe com a anotação @ManagedBean. 55 .2 Managed Beans Os Managed Beans são objetos utilizados nas aplicações JSF e possuem três responsabilidades principais: 1. é interessante ter uma visão geral dos recursos principais e do relacionamento entre eles sem se aprofundar em muito nos detalhes individuais de cada recurso. Disponibilizar os dados que devem ser apresentados nas telas da aplicação. 2. Cada um desses recursos por si só já são suficientemente grandes e podem ser abordados em separado. 5. Receber os dados enviados pelos usuários através das telas da aplicação. Executar as lógicas para tratar as requisições dos usuários. Nos próximos capítulos. 3. discutiremos de maneira mais detalhada as diversas partes do JSF 2. Porém. Para definir o funcionamento de um Managed Bean no JSF 2. no primeiro contato com JSF 2. devemos seguir os seguintes passos: 1.Capítulo 5 Visão Geral do JSF 2 O JSF 2 oferece muitos recursos para o desenvolvimento de uma aplicação web Java. mostraremos de forma sucinta e direta o funcionamento e os conceitos principais do JSF 2. neste capítulo. Portanto. 5. vamos montar uma pequena aplicação em JSF 2 que gera apostas de loteria.

Os componentes visuais que formam as telas da aplicação são inseridos através de tags xhtml. Este método deve devolver no final o “nome” da tela que apresentará as apostas geradas para os usuários. devemos criar um Managed Bean para receber alguns parâmetros que devem ser definidos pelos usuários para gerar as apostas corretamente.1 GeradorDeApostasBean Na aplicação que gera apostas de loteria. 1 2 3 4 5 6 7 8 9 10 @ManagedBean public class GeradorDeApostasBean { private int quantidadeDeNumeros. private int tamanhoDaAposta.br 56 . 3. Definir métodos para implementar as lógicas de tratamento das possíveis requisições dos usuários.1 Tela de entrada Na nossa aplicação de gerar apostas.k19. 1 2 3 private List<List<Integer>> apostas. Definir atributos com os correspondentes getters e setters para poder receber dados das telas ou enviar dados para as telas.3.com. 5. private int quantidadeDeApostas. // getters e setters } Devemos acrescentar no G ERADOR D E A POSTAS B EAN um método para implementar a lógica de gerar as apostas. } Por fim. 5. www. // getters e setters 5.2. Esses arquivos são processados pela engine do Facelets que faz parte do JSF 2. 1 2 3 4 public String geraApostas() { // Aqui deve ser implementa a lógica para gerar as apostas return "lista-de-apostas". devemos definir uma tela para os usuários passarem os parâmetros necessários para que as apostas sejam geradas.Visão Geral do JSF 2 2. devemos adicionar um atributo no G ERADOR D E A POSTAS B EAN para disponibilizar as apostas geradas para a tela que irá apresentá-las aos usuários.3 Facelets e Componentes Visuais As telas das aplicações JSF 2 podem ser definidas através de arquivos xhtml.

quantidadeDeApostas}"/> <h:commandButton action="#{geradorDeApostasBean.dtd"> <html xmlns="http://www.w3.tamanhoDaAposta}"/> <h:outputLabel value="Quantidade de apostas:"/> <h:inputText value="#{geradorDeApostasBean.0 Transitional//EN" "http://www. 57 K19 Treinamentos .w3.geraApostas}" value="Gerar"/> </h:panelGrid> </h:form> </h:body> </html> 5.org/TR/xhtml1/DTD/xhtml1-transitional.Visão Geral do JSF 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.sun.com/jsf/html"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <h:form> <h:panelGrid> <h:outputLabel value="Quantidade total de números:"/> <h:inputText value="#{geradorDeApostasBean.3.quantidadeDeNumeros}"/> <h:outputLabel value="Quantidade de números por aposta:"/> <h:inputText value="#{geradorDeApostasBean.org/1999/xhtml" xmlns:h="http://java. devemos apresentar aos usuários uma listagem das apostas que foram criadas pelo G ERADOR D E A POSTAS B EAN.2 Tela de Saída Na tela de saída.

dtd"> <html xmlns="http://www.com/jsf/html" xmlns:ui="http://java.4 Exercícios 1.w3.sun.org/1999/xhtml" xmlns:h="http://java.com. Siga as imagens abaixo para configurar corretamente o projeto.com/jsf/facelets"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <ui:repeat var="aposta" value="#{geradorDeApostasBean.Visão Geral do JSF 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. Crie um projeto do tipo Dynamic Web Project chamado K19-Loteria.k19.w3.0 Transitional//EN" "http://www.apostas}" varStatus="status"> <h:outputText value="Aposta #{status.br 58 .index + 1}: "/> <h:outputText value="#{aposta}"/> <br/> </ui:repeat> </h:body> </html> 5. www.org/TR/xhtml1/DTD/xhtml1-transitional.sun.

Visão Geral do JSF 2 59 K19 Treinamentos .

com.br 60 .Visão Geral do JSF 2 www.k19.

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

3. No pacote managedbeans crie uma classe chamada GeradorDeApostasBean com o seguinte conteúdo.

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

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

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

Visão Geral do JSF 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <h:form> <h:panelGrid> <h:outputLabel value="Quantidade total de números:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeNumeros}"/> <h:outputLabel value="Quantidade de números por aposta:"/> <h:inputText value="#{geradorDeApostasBean.tamanhoDaAposta}"/> <h:outputLabel value="Quantidade de apostas:"/> <h:inputText value="#{geradorDeApostasBean.quantidadeDeApostas}"/> <h:commandButton action="#{geradorDeApostasBean.geraApostas}" value="Gerar"/> </h:panelGrid> </h:form> </h:body> </html>

5. Na pasta WebContent, crie um arquivo chamado lista-de-apostas.xhtml para apresentar as apostas geradas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>Gerador de Apostas</title> </h:head> <h:body> <ui:repeat var="aposta" value="#{geradorDeApostasBean.apostas}" varStatus="status"> <h:outputText value="Aposta #{status.index + 1}: "/> <h:outputText value="#{aposta}"/> <br/> </ui:repeat> </h:body> </html>

6. Preencha o formulário e clique no botão de gerar apostas para verifique o funcionamento da nossa aplicação. Acesse a url: http://localhost:8080/K19-Loteria/formulario.xhtml

www.k19.com.br

62

Capítulo 6 Componentes Visuais
A arquitetura de componentes visuais do JSF permite que novos componentes além dos que estão definidos na especificação sejam desenvolvidos por terceiros. Isso permitiu que bibliotecas de componentes extremamente “ricos” visualmente fossem desenvolvidas. Inclusive, em geral, essas bibliotecas utilizam recursos como o AJAX para melhorar a interatividade com o usuário. A mais famosa dessas bibliotecas é a RichFaces cujo site oficial pode ser visitado através da url: (http://www.jboss.org/richfaces). Porém, não devemos deixar nossos olhos nos enganarem. Os componentes visuais do JSF vão além da questão visual. Esses componentes podem ser reaproveitados em diversos pontos da mesma aplicação ou em aplicações diferentes mostrando de forma concreta o poder da Orientação a Objetos e o desenvolvimento Orientado a Componentes. Além disso, a arquitetura do JSF permite que outros tipos de componentes sejam conectados aos componentes visuais. Por exemplo, podemos conectar componentes validadores aos componentes visuais para que os dados vindos dos usuários sejam verificados de acordo com alguma regra. Neste capítulo apresentaremos os principais componentes visuais definidos pela especificação do JSF.

6.1

Formulários

Os formulários são necessários em todas as telas que precisam receber dados dos usuários. O componente visual h:form cria formulários. 63

Componentes Visuais 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <h:form> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <br/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <br/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="País: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <br/> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <br/> <h:outputLabel value="Li e estou de acordo com os termos de uso. Definimos o atributo id para que o campo pudesse ser conectado ao rótulo loga acima. se o usuário clicar no rótulo o cursor de digitação aparecerá nesse campo. utilizamos o componente visual h:outputLabel para criar um rótulo para o campo no qual deve ser digitado o nome da pessoa que se cadastra." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <br/> <h:commandButton value="Cadastrar"/> </h:form> Na linha 2.br 64 . www.com. Observe que o atributo for conecta o rótulo ao id do campo do nome. Dessa forma. utilizamos o componente visual h:inputText para criar o campo do nome. Na linha 3.k19.

Assim como no radio button. O componente utilizado para isso foi o h:selectBooleanCheckbox.Componentes Visuais Na linha 9.2 Panel Grid O componente h:panelGrid é utilizado para organizar outros componentes em tabelas de uma forma prática. na linha 38. Na linha 19. criamos um combo box para que o usuário escolha qual é o país de origem da pessoa que será cadastrada. para utilizar este componente. aplicamos o componente h:selecOneRadio para criar um radio button que permite o usuário escolher o sexo (masculino e feminino). Por fim. inserimos na tela um check box para saber se o usuário aceita ou não os termos de cadastro. A diferença básica é que a área de digitação do h:inputTextarea é maior. utilizamos o componente h:inputSecret para criar um campo de texto que não mostra na tela o valor que já foi digitado. Na linha 13. Basicamente. As opções do radio button são definidas pelo componente f:selectItem utilizado nas linhas 14 e 15. as opções do combo box são definidas com o componente f:selectItem. para criar um campo para texto maiores. O funcionamento dele é muito semelhante ao do h:inputText. Na linha 34. utilizamos o componente h:inputTextarea. Esse componente é útil para senhas. devemos definir quantas colunas queremos e ele automaticamente distribui os componentes em um número suficiente de linhas. 6. acrescentamos um botão para o usuário confirmar o cadastro. 65 K19 Treinamentos . Na linha 28.

devemos aplicar o componente h:panelGroup." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <h:commandButton value="Cadastrar"/> </h:panelGrid> </h:form> 6. www. A ideia é inserir dois ou mais componentes em um panel Group e depois inserir o panel Group no lugar que só aceita um componente.k19.br 66 . Por exemplo. Nesses casos.com.3 Panel Group Em certas situações não conseguimos colocar dois ou mais componentes em um determinado local.Componentes Visuais 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="País: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:outputLabel value="Li e estou de acordo com os termos de uso. em uma célula de um panel Grid.

1 2 3 4 5 6 7 8 <h:dataTable value="#{geradorDeApostasBean.Componentes Visuais 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="País: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:panelGroup> <h:outputLabel value="Li e estou de acordo com os termos de uso.apostas}" var="aposta" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Apostas"></h:outputText> </f:facet> <h:outputText value="#{aposta}"></h:outputText> </h:column> </h:dataTable Na linha 2. Basicamente. a diferença dos Data Tables e dos Panel Grids é que os Data Tables iteram diretamente nos ítames de coleções. o componente h:column é utilizado para adicionar uma coluna na tabela defi67 K19 Treinamentos .4 Tabelas Podemos criar tabelas utilizando o componente h:dataTable com dados de alguma coleção." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> </h:panelGroup> <h:commandButton value="Cadastrar"/> </h:panelGrid> </h:form> 6.

6. O segundo corresponde a biblioteca de tags do JSF que não está atrelada a um tipo de visualização.com/jsf/facelets"> <!-.sun.com/jsf/html" xmlns:f="http://java.k19. Veremos em outro capítulo o funcionamento das tags desse namespace.org/1999/xhtml" xmlns:h="http://java. Crie um projeto do tipo Dynamic Web Project chamado ComponentesVisuais seguindo os passos vistos no exercício do capítulo 5.sun.7 Exercícios 1. ou seja. O primeiro é o namespace da biblioteca de tags do JSF que geram conteúdo HTML especificamente.sun.com.org/1999/xhtml" xmlns:h="http://java.com/jsf/html e http://java.sun. aplicamos o componente f:facet para adicionar um cabeçalho na coluna correspondente.com/jsf/core. Outro namespace importante é o http://java.5 Namespaces Para poder aplicar as tags que definem as telas das aplicações JSF. são tags mais genéricas.com/jsf/core" xmlns:ui="http://java.6 Esqueleto HTML Um documento HTML possui um esqueleto constituído por algumas tags principais.com/jsf/html"> <h:head> </h:head> <h:body> </h:body> </html> 6. 1 2 3 4 5 6 7 8 <html xmlns="http://www. 6. Para refletir essa estrutura devemos inserir algumas tags nos documentos XHTML que definem as telas JSF. Na linha 3.sun.Componentes Visuais nida com o h:dataTable.Conteúdo Aqui --> </html> Os dois principais namespaces são: http://java. 1 2 3 4 5 6 7 8 9 10 <html xmlns="http://www.w3. precisamos adicionar os namespaces correspondentes às bibliotecas de tags que desejamos utilizar. www.br 68 .sun.w3.com/jsf/facelets que contém tags que nos ajudam a reaproveitar o código das telas.sun.

1 2 3 4 5 6 7 <h:form> <h:panelGrid columns="2"> <!-. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.CONTEÚDO DO FORMULÁRIO --> </h:panelGrid> </h:form> Verifique o resultado através de um navegador.dtd"> <html xmlns="http://www.xhtml.Componentes Visuais 2. Utilize o componente h:panelGrid para alinhar melhor os itens do formulário criado no exercício anterior.w3. 3.org/TR/xhtml1/DTD/xhtml1-transitional.com/jsf/core"> <h:head> <title>Cadastro de Usuário</title> </h:head> <h:body> <h:form> <h:outputLabel value="Nome: " for="input-nome"/> <h:inputText id="input-nome"/> <h:outputLabel value="Sobre: " for="input-sobre"/> <h:inputTextarea id="input-sobre"/> <h:outputLabel value="Sexo: "/> <h:selectOneRadio> <f:selectItem itemLabel="Masculino" itemValue="M"/> <f:selectItem itemLabel="Feminino" itemValue="F"/> </h:selectOneRadio> <h:outputLabel value="País: "/> <h:selectOneMenu> <f:selectItem itemLabel="Argertina" itemValue="ar"/> <f:selectItem itemLabel="Brasil" itemValue="br"/> <f:selectItem itemLabel="Espanha" itemValue="es"/> </h:selectOneMenu> <h:outputLabel value="Escolha uma senha: " for="input-senha"/> <h:inputSecret id="input-senha"/> <h:outputLabel value="Li e concordo.0 Transitional//EN" "http://www.sun. Adicione um arquivo na pasta WebContent do projeto ComponentesVisuais para criar uma tela utilizando os principais componentes de formulários. Este arquivo deve se chamar formulario." for="checkbox-termo"/> <h:selectBooleanCheckbox id="checkbox-termo" value="aceito"/> <h:commandButton value="Cadastrar"/> </h:form> </h:body> </html> Acesse a url adequada para visualizar o formulário. 69 K19 Treinamentos .org/1999/xhtml" xmlns:h="http://java.sun.w3.com/jsf/html" xmlns:f="http://java.

0 Transitional//EN" "http://www. } public void setPalavras(List<String> palavras) { this. } } 6.br 70 .sun. this.palavras. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.org/TR/xhtml1/DTD/xhtml1-transitional. adicione uma classe com o seguinte conteúdo para modelar um simples Managed Bean que gera palavras.palavras.com. 5.add("K19 Treinamentos"). Crie uma tela aplicando o componente h:dataTable para apresentar as palavras geradas pelo Managed Bean do exercício anterior.w3.com/jsf/core"> <h:head> <title>Palavras apenas palavras</title> </h:head> <h:body> <h:dataTable value="#{palavrasBean. public PalavraBean() { this.palavras = palavras. this.add("Jonas Hirata").Componentes Visuais 4.palavras. this.palavras.sun.k19.palavras}" var="palavra" border="1"> <h:column> <f:facet name="header"> <h:outputText value="Palavras"></h:outputText> </f:facet> <h:outputText value="#{palavra}"></h:outputText> </h:column> </h:dataTable </h:body> </html> Veja a tabela acessando a url correspondente.add("Rafael Cosentino"). Na pasta src crie um pacote chamado managedbeans.com/jsf/html" xmlns:f="http://java.dtd"> <html xmlns="http://www.org/1999/xhtml" xmlns:h="http://java. Nesse pacote.add("Alexandre Macedo"). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @ManagedBean public class PalavrasBean { private List<String> palavras = new ArrayList<String>(). www.w3. } public List<String> getPalavras() { return this. Utilize o componente h:panelGroup para agrupar dois ou mais componentes em uma célula do Panel Grid criado no exercício anterior.palavras.

basta criar um arquivo xhtml adicionando todos os componentes visuais que são fixos e devem aparecer em um determinado conjunto de telas.1 Templating A reutilização do código das telas é realizada principalmente pelo uso de templates. 71 . os objetivos do reaproveitamento de software são: diminuir o tempo e o custo para desenvolver e facilitar a manutenção também diminuindo gastos e tempo.Capítulo 7 Facelets Certamente. A ideia é identificar um padrão em um determinado conjunto de telas de uma aplicação JSF e defini-lo através de um esqueleto (template) que possua trechos dinâmicos que possam ser preenchidos posteriormente. O Facelets já faz parte do JSF 2 sendo a engine padrão dessa tecnologia para a definição das telas das aplicações web. A criação de um template é simples. algumas pessoas desenvolveram um projeto chamado Facelets que tem como principal objetivo facilitar todo o processo de desenvolvimento e manutenção das telas de uma aplicação JSF. 7. Para os trechos dinâmicos. Nesse contexto. devemos aplicar o componente ui:insert criando um espaço que pode ser preenchido depois. você já ouviu alguém falar da importância da reutilização no desenvolvimento de software. Levando a ideia do reaproveitamento adiante.

Todos os direitos reservados.org/TR/xhtml1/DTD/xhtml1-transitional.w3.sun. o atributo name do componente ui:insert é utilizado para identificar o espaço que será preenchido depois.sun. 1 2 3 4 5 6 7 8 9 10 <html xmlns="http://www. www. Crie um projeto do tipo Dynamic Web Project chamado Facelets seguindo os passos vistos no exercício do capítulo 5.sun. Copie o arquivo k19-logo. 2.br 72 .sun.0 Transitional//EN" "http://www.png" /> <hr /> </div> <ui:insert name="conteudo"> Espaço para o conteúdo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy. Após escrever o template. devemos aplicar o componente ui:composition.png da pasta K19-Arquivos/imagens que está na Área de Trabalho para pasta WebContent do projeto Facelets.xhtml"> <ui:define name="conteudo"> <h:outputText value="Conteúdo da página que utiliza o template.w3. Para preencher um espaço deixado no template.com/jsf/html" xmlns:ui="http://java.com. Crie um template na pasta WebContent chamado template. Para indicar que desejamos utilizar um template. </div> </h:body> </html> Na linha 16. Essas telas são definidas também através de arquivos xhtml.org/1999/xhtml" xmlns:h="http://java.xhtml.com/jsf/html" xmlns:ui="http://java.dtd"> <html xmlns="http://www.w3.com/jsf/facelets"> <ui:composition template="/template.xhtml"/> </ui:define> <ui:composition> </html> 7.k19.org/1999/xhtml" xmlns:h="http://java.com/jsf/facelets"> <h:head> <title>K19 Treinamentos</title> </h:head> <h:body> <div id="header"> <img src="k19-logo.Facelets 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. devemos inserir o componente ui:define no código. 2010 K19.2 Exercícios 1. devemos criar as telas que o utilizarão.

sun.xhtml 7.Facelets 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.org/1999/xhtml" xmlns:h="http://java.w3.sun.xhtml.png" /> <hr /> </div> <ui:insert name="conteudo"> Espaço para o conteúdo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy. O nome do arquivo deve ser teste-template.w3. </div> </h:body> </html> 3. 2010 K19.com/jsf/html" xmlns:ui="http://java. Todos os direitos reservados.com/jsf/facelets"> <ui:composition template="/template. O recurso de separar uma tela ou um template em vários arquivos se torna mais interessante e útil quando temos a possibilidade de passar dados do arquivo principal para os secundários.sun.dtd"> <html xmlns="http://www.0 Transitional//EN" "http://www.xhtml"> <ui:define name="conteudo"> <h:form> <h:outputLabel value="Nome: " for="campo-nome"/> <h:inputText id="campo-nome"/> <h:commandButton value="Enviar"/> </h:form> </ui:define> </ui:composition> </html> Verifique o resultado acessando a url: http://localhost:8080/Facelets/teste-template. Monte uma tela que usa o template criado no exercício anterior. Essa passagem de dados é realizada através do componente ui:param.sun.com/jsf/facelets"> <h:head> <title>K19 Treinamentos</title> </h:head> <h:body> <div id="header"> <img src="k19-logo.com/jsf/html" xmlns:f="http://java. podemos dividir o conteúdo de uma tela ou de um template em vários arquivos através do componente ui:include. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <html xmlns="http://www.org/TR/xhtml1/DTD/xhtml1-transitional.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/core" xmlns:ui="http://java.3 Particionando as telas Com o intuito de organizar melhor o código das telas ou definir “pedaços” de telas que possam ser reaproveitados. 73 K19 Treinamentos .

4 Exercícios 4.logout" value="Log out"/> 1 2 3 4 5 <h:outputLabel value="Usuário: " for="campo-usuario"/> <h:inputText id="campo-usuario"/> <h:outputLabel value="Senha: " for="campo-senha"/> <h:inputSecret id="campo-senha"/> <h:commandButton action="usuarioBean.k19. Faça um Managed Bean que forneça uma lista de instrutores para uma tela de listagem de instrutores. // GETTERS AND SETTERS } 5.login" value="Log in"/> 7. Crie um pacote chamado managedbeans no projeto Facelets e adicione nele uma classe chamada InstrutorBean com seguinte código: www. private String dataDeNascimento.br 74 . O primeiro passo é criar uma classe para modelar os instrutores.nome}"/> <h:commandButton action="usuarioBean.usuario}"/> </ui:include> </c:if> <c:if test="#{!usuarioBean. Vamos implementar uma listagem de instrutores no nosso projeto Facelets.xhtml"/> </c:if> </div> Veja os fragmentos que teríamos que acrescentar nos arquivos secundários: 1 2 <h:outputText value="Olá #{usuario.xhtml"> <ui:param name="usuario" value="#{usuarioBean. estamos desenvolvendo uma aplicação e desejamos colocar o nome do usuário e um link para fazer logoff no canto superior direito sempre que alguém estiver logado ou um link para a página de login caso contrário.com.logado}"> <ui:include src="usuario-logado.logado}"> <ui:include src="usuario-nao-logado.Facelets Por exemplo. Crie um pacote chamado model no projeto Facelets e adicione nele uma classe chamada Instrutor com seguinte código: 1 2 3 4 5 6 public class Instrutor { private String nome. Veja o fragmento que teríamos que acrescentar nos arquivos principais: 1 2 3 4 5 6 7 8 9 10 11 <div id="header"> <c:if test="#{usuarioBean.

setDataDeNascimento("30/10/1984"). rafael. marcelo.instrutores.setDataDeNascimento("02/04/1985").instrutores.xhtml e com o seguinte código. Crie uma tela parcial para mostrar os dados de apenas um instrutor dentro de um item de uma lista HTML. this.add(rafael).Facelets 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @ManagedBean public class InstrutorBean { private List<Instrutor> instrutores = new ArrayList<Instrutor>(). Faça a tela principal da listagem de instrutores. public InstrutorBean() { Instrutor rafael = new Instrutor(). } public List<Instrutor> getInstrutores() { return instrutores.setNome("Rafael Cosentino"). Crie um arquivo na pasta WebContent do projeto Facelets e como o nome listagem-de-instrutores.dataDeNascimento}"/> </li> </html> 7. Instrutor marcelo = new Instrutor().com/jsf/html"> <li> <h:outputText value="Nome: #{instrutor.add(marcelo). } public void setInstrutores(List<Instrutor> instrutores) { this.setNome("Marcelo Martins").org/1999/xhtml" xmlns:h="http://java.w3. this.instrutores = instrutores. marcelo.sun.xhtml.nome}"/> <br/> <h:outputText value="Data Nascimento: #{instrutor. rafael. O arquivo deve ser adicionado na pasta WebContent do projeto Facelets e se chamar instrutor-info. } } 6. 75 K19 Treinamentos . 1 2 3 4 5 6 7 8 9 10 <html xmlns="http://www.

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

um sinal (outcome) fixo definido no próprio botão ou link é enviado para o JSF.xhtml. se o usuário clica em um botão ou link de uma tela definida por um arquivo chamado pagina1.dtd"> <html xmlns="http://www.xhtml que envia o outcome “pagina2” então ele será redirecionado para a tela definida pelo arquivo pagina2. O mecanismo de navegação do JSF é bem sofisticado e permite vários tipos de transições entre telas.w3.xhtml e pagina2. no clique de um botão ou link.w3.sun. Este sinal é uma string que será utilizada pelo tratador de navegação do JSF para definir a próxima tela que será apresentada ao usuário.xhtml dentro do mesmo diretório que está o arquivo pagina1. quando o usuário clica em algum botão ou link. 8.1 Navegação Estática Implícita Na navegação estática implícita. A ideia é muito simples. Veja como seria o código da pagina1. Nas navegações implícitas.org/TR/xhtml1/DTD/xhtml1-transitional.xhtml. os nomes dos arquivos que definem as telas de resposta são montados com as strings dos outcomes.org/1999/xhtml" xmlns:h="http://java.0 Transitional//EN" "http://www. Por exemplo.Capítulo 8 Navegação Navegar entre as telas de uma aplicação web é preciso. muda-se a tela apresentada ao usuário. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.com/jsf/html"> <h:head> <title>K19 Página 1</title> </h:head> <h:body> <h1>K19 Página 1</h1> <h:form> <h:commandButton value="Página 2" action="pagina2"/> </h:form> </h:body> </html> 77 .

os outcomes são os nomes dos arquivos que definem as telas.xml.xhtml.com.dtd"> <html xmlns="http://www. Porém.xhtml</from-view-id> <navigation-case> <from-outcome>proxima</from-outcome> <to-view-id>pagina2.com/jsf/html"> <h:head> <title>K19 Página 2</title> </h:head> <h:body> <h1>K19 Página 2</h1> <h:form> <h:commandLink action="pagina1"> <h:outputText value="Página 1"/> </h:commandLink> </h:form> </h:body> </html> 8. 2.2 Navegação Estática Explícita Na navegação implícita.xhtml emitir o sinal(outcome) “proxima” a transição deve ser realizada para a tela do arquivo pagina2.0 Transitional//EN" "http://www.sun.org/1999/xhtml" xmlns:h="http://java.w3. o faces-config. crie um arquivo chamado pagina1. devemos acrescentar algumas linhas no arquivo de configurações do JSF. Crie um projeto do tipo Dynamic Web Project chamado Navegacao seguindo os passos vistos no exercício do capítulo 5.k19.w3.xhtml com o seguinte código: www.org/TR/xhtml1/DTD/xhtml1-transitional.br 78 . 1 2 3 4 5 6 7 8 <navigation-rule> <from-view-id>pagina1. Na tela do arquivo pagina1.xhtml. nesse tipo de navegação.3 Exercícios 1. basta acrescentar um botão ou link que emita o sinal “next”. 1 <h:commandButton value="Próxima tela" action="proxima"/> 8.xhtml</to-view-id> </navigation-case> </navigation-rule> O código acima define que quando a tela do arquivo pagina1. Na pasta WebContent do projeto Navegacao. Para ter a liberdade de definir os nomes dos arquivos independentemente dos outcomes. podemos utilizar a navegação explícita.Navegação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.

dtd"> <html xmlns="http://www.Navegação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.sun.xhtml</to-view-id> </navigation-case> </navigation-rule> 6. Novamente. Navegue através dos links e botões da url: http://localhost:8080/Navegacao/pagina1.org/TR/xhtml1/DTD/xhtml1-transitional.0 Transitional//EN" "http://www.sun.w3.org/1999/xhtml" xmlns:h="http://java. 1 2 3 4 5 6 7 8 <navigation-rule> <from-view-id>pagina1.w3.com/jsf/html"> <h:head> <title>K19 Página 1</title> </h:head> <h:body> <h1>K19 Página 1</h1> <h:form> <h:commandButton value="Página 2" action="pagina2"/> </h:form> </h:body> </html> 3.xhtml 5.w3.xhtml que emita o sinal “proxima” abaixo do outro botão.xhtml</from-view-id> <navigation-case> <from-outcome>proxima</from-outcome> <to-view-id>pagina2. Adicione um botão na tela do arquivo pagina1. na pasta WebContent do projeto Navegacao.dtd"> <html xmlns="http://www.xhtml com o seguinte código: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. crie um arquivo chamado pagina2. Configure uma navegação explícita no arquivo faces-config.w3.org/TR/xhtml1/DTD/xhtml1-transitional. 79 K19 Treinamentos .0 Transitional//EN" "http://www.xml.com/jsf/html"> <h:head> <title>K19 Página 2</title> </h:head> <h:body> <h1>K19 Página 2</h1> <h:form> <h:commandLink action="pagina1"> <h:outputText value="Página 1"/> </h:commandLink> </h:form> </h:body> </html> 4.org/1999/xhtml" xmlns:h="http://java.

xml o tratador de navegação do JSF assumirá a navegação implícita. 1 2 3 4 5 6 7 8 9 10 11 @javax. temos que definir a lógica de escolha dos outcomes.5){ return "cara".com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>K19 Cara ou Coroa</h1> <h:form> <h:commandButton value="Lançar Moeda" action="#{managedBean. quando um usuário clica em um botão ou link.faces.Navegação 1 <h:commandButton value="Próxima tela" action="proxima"/> 7.br 80 . a escolha dos outcomes são realizadas dentro dos Managed Beans.org/TR/xhtml1/DTD/xhtml1-transitional. Se o outcome devolvido pelo Managed Bean não estiver configurado no faces-config. } else { return "coroa". o valor devolvido é o nome do arquivo que será processado para gerar a tela de resposta.random() < 0.xhtml 8. Normalmente. ou seja. Na navegação dinâmica. O arquivo cara.xhtml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. um Managed Bean é chamado para escolher um outcome e enviar para o JSF.com. } } } Os Managed Beans devem devolver uma string com o outcome escolhido.k19.org/1999/xhtml" xmlns:h="http://java.4 Navegação Dinâmica Implícita Na maioria dos casos. O arquivo cara-ou-coroa.proxima}"/> </h:form> </h:body> </html> Nos Managed Beans. Para isso.w3.ManagedBean public class ManagedBean { public String proxima(){ if(Math. associamos os botões ou os links a métodos dos Managed Beans.bean.xhtml: www.w3.dtd"> <html xmlns="http://www.sun. Navegue através dos links e botões da url: http://localhost:8080/Navegacao/pagina1. não queremos fixar nas telas os outcomes que elas podem enviar para o JSF.0 Transitional//EN" "http://www.

com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Cara!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html> O arquivo coroa.w3.w3.w3.sun. 8. Crie um pacote chamado managedbeans no projeto Navegacao e adicione uma classe chamada ManagedBean 81 K19 Treinamentos .dtd"> <html xmlns="http://www.0 Transitional//EN" "http://www.org/1999/xhtml" xmlns:h="http://java.sun.org/TR/xhtml1/DTD/xhtml1-transitional.0 Transitional//EN" "http://www.5 Navegação Dinâmica Explícita Para implementar a navegação dinâmica explícita.w3.com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Coroa!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html> 8.dtd"> <html xmlns="http://www.org/1999/xhtml" xmlns:h="http://java.org/TR/xhtml1/DTD/xhtml1-transitional. basta seguir os passos da navegação dinâmica implícita e acrescentar as regras de navegação no arquivo de configurações do JSF. Implemente um Managed Bean de forma aleatória escolha entre dois outcomes.xhtml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.6 Exercícios 8.Navegação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.

br 82 .k19.w3. O arquivo cara.xhtml: www.dtd"> <html xmlns="http://www.0 Transitional//EN" "http://www.sun. faça um arquivo chamado cara-ou-coroa.org/TR/xhtml1/DTD/xhtml1-transitional.bean.com.w3. Crie os arquivos de saída.org/TR/xhtml1/DTD/xhtml1-transitional.Navegação 1 2 3 4 5 6 7 8 9 10 11 @javax.ManagedBean public class ManagedBean { public String proxima(){ if(Math.w3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.faces.5){ return "cara".xhtml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1. } } } 9. Crie uma tela principal com um botão que chama o Managed Bean do exercício anterior para escolher o outcome que deve ser emitido para o JSF. } else { return "coroa".proxima}"/> </h:form> </h:body> </html> 10.w3.random() < 0.org/1999/xhtml" xmlns:h="http://java.sun.xhtml na pasta WebContent do projeto Navegacao.dtd"> <html xmlns="http://www.0 Transitional//EN" "http://www. Para isso.com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>K19 Cara ou Coroa</h1> <h:form> <h:commandButton value="Lançar Moeda" action="#{managedBean.com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Cara!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html> O arquivo coroa.org/1999/xhtml" xmlns:h="http://java.

org/1999/xhtml" xmlns:h="http://java.w3.0 Transitional//EN" "http://www.dtd"> <html xmlns="http://www.com/jsf/html"> <h:head> <title>K19 Cara ou Coroa</title> </h:head> <h:body> <h1>Deu Coroa!</h1> <h:form> <h:commandButton value="voltar" action="cara-ou-coroa"/> </h:form> </h:body> </html> 11. Navegue através dos links e botões da url: http://localhost:8080/Navegacao/cara-ou-coroa.Navegação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.xhtml 83 K19 Treinamentos .sun.w3.org/TR/xhtml1/DTD/xhtml1-transitional.

k19.Navegação www.com.br 84 .

e disparar ações ou eventos. 9. @ManagedBean class MeuManagedBean { } Antes do JSF 2. o registro dos Managed Beans era realizado somente através do arquivo de configurações do JSF. Dizemos. há objetos que oferecem todo o suporte que as telas necessitam. os usuários podem basicamente: enviar dados para o sistema.1 Criando Managed Beans Para criar um Managed Bean. devemos escrever uma classe Java simples sem nenhum vínculo direto com classes ou interfaces do JSF. As classes dos Managed Beans precisam ser registradas no JSF. Nas aplicações web JSF. A simplicidade é a maior vantagem de utilizar POJOs. Processar o tratamentos das ações e eventos disparados pelos usuários. o faces-config.xml. Na versão 2 do JSF. 1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans. visualizar informações da aplicação.MeuManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> 85 . Esses objetos são chamados de Managed Beans. Fornecer dados que serão apresentados aos usuários nas telas 2.Capítulo 9 Managed Beans Através das telas de uma aplicação. 1 2 3 4 5 6 package managedbeans. o registro é feito através da anotação @ManagedBean. Receber os dados enviados pelos usuários através das telas 3. que as classes que implementam os Managed Beans são POJOs (Plain Old Java Object). As responsabilidades principais dos Managed Beans são: 1. Só que as telas não realizam todas essas tarefas sozinhas.

informacao = informacao. public String getInformacao() { return this.2 Disponibilizando dados para as telas Basta criar métodos getters nas classes dos Managed Beans para disponibilizar dados para as telas. } } 9.informacao. public void setInformacao(Strign informacao) { this. @ManagedBean class MeuManagedBean { private String informacao. 9. 1 2 3 4 5 6 7 8 9 10 package managedbeans.br 86 .com. estão disponíveis no JSF 2. basta criar métodos nas classes dos Managed Beans.k19. } } 9. www. 1 2 3 4 5 6 7 8 9 10 package managedbeans.4 Definindo o tratamento das ações Para implementar as lógicas que devem ser executadas assim que o usuário clicar em um botão ou link.3 Recebendo dados das telas Basta criar métodos setters nas classes dos Managed Beans para receber dados das telas. @ManagedBean class MeuManagedBean { private String informacao. anotação ou xml.Managed Beans As duas possibilidades. 1 2 3 4 5 6 @ManagedBean class MeuManagedBean { public void logica() { // implemetação } } Esses métodos podem ser VOID quando desejamos manter os usuários na mesma tela ou devolver S TRING quando desejamos realizar uma navegação entre telas.

1 Nome dos Managed Beans Todo Managed Bean possui um nome único que é utilizado para acessá-lo dentro dos trechos escritos com Expression Language. o JSF assume que o nome do Managed Bean é o nome da classe com a primeira letra minúscula. Essa linguagem é chamada de Expression Language. por padrão. Normalmente. delimitamos os trechos escritos em Expression Language através dos símbolos #{ }. pelo nome. public String getInformacao() { return this. 9.5.6 Binding Os componentes que estão nas telas podem ser “ligados” aos Managed Beans. Há uma linguagem no JSF que podemos utilizar no código das telas que é apropriada para realizar a interação entre as páginas e os Managed Beans. Quando utilizamos a anotação @ManagedBean. Porém podemos alterar o nome acrescentado um argumento na anotação.2 Acessando as propriedades dos Managed Beans As propriedades dos Managed Beans são acessadas tanto para leitura quanto para escrita da maneira mais natural possível. Suponha o seguinte Managed Bean: 1 2 3 4 5 6 7 8 9 10 11 12 @ManagedBean(name="teste") class ManagedBean { private String informacao.5 Expression Language De alguma forma as telas precisam referenciar os Managed Beans com os quais elas desejam interagir. } public void setInformacao(String informacao) { this. Por 87 K19 Treinamentos .informacao} INFORMACAO deve ser acessada da seguinte forma utilizando Expression 9. 1 2 3 4 @ManagedBean(name="teste") class ManagedBean { } 9.informacao = informacao.informacao.5. essa ligação é estabelecida através de algum atributo das tags dos componentes.Managed Beans 9. Dentro do código de uma tela. } } A propriedade Language: 1 #{teste.

O código seria mais ou menos assim: CAO 1 2 3 4 5 6 @ManagedBean class MeuManagedBean { public void logica() { // implemetação } } 1 <h:commandButton action="#{meuManagedBean. se o desenvolvedor não definir nenhum escopo para um determinado Managed Bean o escopo Request será adotado automaticamente. suponha que queremos ligar um campo de texto a uma propriedade de um Managed Bean. O tempo de vida de uma instância afeta principalmente a durabilidade dos dados que ela armazena. podemos deixar explícito a escolha do escopo Request através da anotação @RequestScoped ou da tag managed-bean-scope.informacao}"/> O atributo VALUE do H : INPUT T EXT cria o vínculo entre o input e a propriedade INFORMA do Managed Bean TESTE. precisamos escolher qual escopo queremos utilizar em cada Managed Bean.com. o código seria mais ou menos assim: 1 <h:inputText value="#{teste.7 Escopo Os Managed Beans são instanciados pelo JSF.1 Request No escopo Request. quando o usuário preencher algum valor nesse campo.logica}" value="Executar"/> 9. os desenvolvedores definem as classes e o JSF cuida do “new”.br 88 .7. O JSF utiliza o escopo Request como padrão. Dessa forma. Porém. podemos determinar quando os Managed Beans devem ser criados e descartados. ou seja.k19. Outro exemplo. Dessa forma. as instâncias dos Managed Beans são criadas durante o processamento de uma requisição assim que forem necessárias e descartadas no final desse mesmo processamento. os dados não são mantidos de uma requisição para outra. www.Managed Beans exemplo. 9. esse dado será armazenado no atributo INFORMACAO através do método SET I NFOR MACAO (). Por isso. Ou seja. Mesmo sendo o padrão. suponha que desejamos associar um método do nosso Managed Bean a um botão de uma tela qualquer.

2 Session Certas informações devem ser mantidas entre as requisições de um determinado usuário em um determinado navegador. devemos utilizar a anotação @SessionScoped ou a tag managed-bean-scope. 1 2 3 4 5 6 7 package managedbeans. Um usuário faz diversas requisições para escolher os produtos e colocálos no seu carrinho. Para escolher o escopo Session. Cada usuário possui um espaço na memória do servidor que é chamado de Session. Esse tempo pode ser configurado com o Web Container. é possível existir duas ou mais Sessions de um mesmo usuário. Por exemplo. havia somente a opção da configuração através de xml.Managed Beans 1 2 3 4 5 6 7 package managedbeans. ou seja. As instâncias dos Managed Beans configurados com o escopo Session são criadas quando necessárias durante o processamento de uma requisição e armazenadas na Session do usuário que fez a requisição.7. o usuário fez logout) ou o Web Container decide apagar a Session de um usuário pois este não faz requisições a “muito” tempo. 9. se ele estiver utilizando dois navegadores. Tecnicamente. existe uma Session para cada usuário.MeuManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> Antes do JSF 2. por exemplo.MeuManagedBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> 89 K19 Treinamentos . @ManagedBean @RequestScoped class MeuManagedBean { } 1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans. Daí surge o escopo Session. a aplicação deve manter a informação de quais produtos já foram escolhidos por este usuário. Essas instâncias são eliminadas basicamente em duas situações: a própria aplicação decide por algum motivo específico apagar a Session de um usuário (por exemplo. @ManagedBean @SessionScoped class MeuManagedBean { } 1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans. Durante todo esse tempo. suponha uma aplicação que utiliza a ideia de carrinho de compras.

para escolher o escopo Application. Os dados dessas instâncias podem ser utilizados nas telas de todos os usuários durante toda a execução da aplicação. 1 2 3 4 5 6 7 package managedbeans. 9. a dica é evitar utilizar o escopo Session quando possível. para escolher o escopo View. o escopo Requeste é mais apropriado. @ManagedBean @ViewScoped class MeuManagedBean { } www. Para não consumir excessivamente os recursos de memória do servidor.Managed Beans Antes do JSF 2. @ManagedBean @ApplicationScoped class MeuManagedBean { } 1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans. devemos utilizar a anotação @ViewScoped ou a tag managed-bean-scope. havia somente a opção da configuração através de xml. A ideia é manter determinados dados enquanto o usuário não mudar de tela. devemos utilizar a anotação @ApplicationScoped ou a tag managed-bean-scope.com. As instância dos Managed Beans em escopo View são eliminadas somente quando há uma navegação entre telas. Portanto.MeuManagedBean</managed-bean-class> <managed-bean-scope>application</managed-bean-scope> </managed-bean> Antes do JSF 2. havia somente a opção da configuração através de xml.7. Temos que tomar um cuidado maior ao utilizar o escopo Session pois podemos acabar sobrecarregando o servidor. Analogamente. 1 2 3 4 5 6 7 package managedbeans.7.3 Application As instâncias dos Managed Beans configurados com escopo Application são criadas no primeiro momento em que elas são utilizadas e mantidas até a aplicação ser finalizada.br 90 .4 View O escopo View foi adicionado no JSF 2. 9. Analogamente.k19.

Como a criação e eliminação das instâncias dos Managed Beans são responsabilidade do JSF. 1 2 3 4 @ManagedBean class PrimeiroManagedBean { private SegundoManagedBean segundoManagedBean. suponha dois Managed Beans: 1 2 3 4 @ManagedBean class PrimeiroManagedBean { } 1 2 3 4 @ManagedBean class SegundoManagedBean { } Suponha também que o primeiro precisa chamar o segundo para resolver algum problema. devemos indicar através de anotações ou de xml o vínculo dos dois Managed Beans. Do ponto de vista da Orientação a Objetos.8 Interdependência e Injeção Instâncias de Managed Beans podem “conversar” entre si para dividir o processamento das requisições dos usuários de acordo a especialidade de cada uma delas. como é o JSF que vai administrar as ligações entre os objetos. 9. Como exemplo.Managed Beans 1 2 3 4 5 <managed-bean> <managed-bean-name>meuManagedBean</managed-bean-name> <managed-bean-class>managedbeans. } 91 K19 Treinamentos . o que o desenvolvedor deve fazer é indicar ao JSF quais instâncias devem ser conectadas através de referências. ele é o mais indicado para administrar as referências entre as instâncias do Managed Beans. Para que duas instâncias “conversem”. 1 2 3 4 5 @ManagedBean class PrimeiroManagedBean { @ManagedProperty(value="#{segundoManagedBean}") private SegundoManagedBean segundoManagedBean. Basicamente. bastaria declarar um atributo na classe do primeiro Managed Bean relacionando-o ao segundo. havia somente a opção da configuração através de xml. uma deve possuir a referência da outra. } Porém.MeuManagedBean</managed-bean-class> <managed-bean-scope>view</managed-bean-scope> </managed-bean> Antes do JSF 2.

adicione a seguinte classe: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package managedbeans. www. faça um pacote chamado managedbeans.Managed Beans 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <managed-bean> <managed-bean-name>primeiroManagedBean</managed-bean-name> <managed-bean-class>managedbeans. } // GETTERS AND SETTERS } 4. @ManagedBean(name="impostometro") public class ImpostometroBean { private double total.br 92 . 9.com.SegundoManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean> Quando as instâncias dos Managed Beans são criadas pelo JSF ele resolve todas as dependências conectando os objetos. No pacote managedbeans. private double valor. Crie um projeto do tipo Dynamic Web Project chamado ManagedBean seguindo os passos vistos no exercício do capítulo 5.PrimeiroManagedBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>segundoManagedBean</property-name> <value>#{segundoManagedBean}</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>segundoManagedBean</managed-bean-name> <managed-bean-class>managedbeans. Crie uma tela com o suporte do Managed Bean impostometro.9 Exercícios 1.xhtml.k19.valor.total += this. O arquivo da tela deve se chamar impostometro. 3. public void adicionaImposto() { this. 2. Na pasta src.

ele deve ser relacionado com o Managed Bean do exercício anterior.Managed Beans 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.valor}" /> <h:commandButton value="Adicionar" action="#{impostometro. Para isso. Por quê? 5. Observe que o total não acumula os valores adicionados em requisições anteriores. Crie um Managed Bean para guardar os valores de algumas taxas. 1 2 3 @ManagedBean(name="impostometro") @SessionScoped public class ImpostometroBean { 6.org/TR/xhtml1/DTD/xhtml1-transitional. @ManagedBean(name="taxas") public class TaxasBean { private double selic = 3.total}" /> <h:outputLabel value="Digite o imposto a ser adicionado: " for="campo-imposto" /> <h:inputText id="campo-imposto" value="#{impostometro.w3.0 Transitional//EN" "http://www. 1 2 3 4 5 6 7 8 9 package managedbeans. 93 K19 Treinamentos . Altere o escopo do impostometro para Session. // GETTERS AND SETTERS } 7.org/1999/xhtml" xmlns:h="http://java.adicionaImposto}" /> </h:panelGrid> </h:form> </h:body> </html> Adicione alguns valores através do formulário.sun.w3.dtd"> <html xmlns="http://www. Teste novamente.5.com/jsf/html"> <h:head> <title>Impostometro</title> </h:head> <h:body> <h1>Impostometro</h1> <h:form> <h:panelGrid> <h:outputText value="Total: #{impostometro. Faça um Managed Bean que calcula juros baseado na taxa selic.

br 94 .Managed Beans 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package managedbeans. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.juros}" /> <h:outputLabel value="Digite um montante: " /> <h:inputText value="#{calculadora.selic}" /> <h:outputText value="Juros: #{calculadora. private double juros. } // GETTERS AND SETTERS } 8.taxas.montante}" /> <h:commandButton value="Calcular" action="#{calculadora.juros = this. @ManagedBean(name="calculadora") public class CalculadoraBean { @ManagedProperty(value="#{taxas}") private TaxasBean taxas. public void calculaJuros() { this.w3.getSelic() / 100. Construa uma tela que utilize os Managed Beans criados nos exercícios anteriores.k19.calculaJuros}" /> </h:panelGrid> </h:form> </h:body> </html> www.com.org/TR/xhtml1/DTD/xhtml1-transitional.org/1999/xhtml" xmlns:h="http://java.0 Transitional//EN" "http://www. private double montante.dtd"> <html xmlns="http://www.w3.montante * this.com/jsf/html"> <h:head> <title>Calculadora de Imposto</title> </h:head> <h:body> <h1>Calculadora de Imposto</h1> <h:form> <h:panelGrid> <h:outputText value="Selic: #{taxas.sun.

os dados que chegam para as aplicações não podem ser convertidos pois não estão no formato esperado. se o texto preenchido em um campo numérico possui caracteres não numéricos a conversão falhará. Por exemplo. suponha um formulário que possui um campo para os usuários digitarem a sua idade. protocolo de comunicação utilizado entre os navegadores e as aplicações web.Capítulo 10 Conversão e Validação 10.1 Conversão Quando um usuário preenche um formulário. Por exemplo. o JSF oferece um mecanismo automatizado de conversão de dados. quando uma aplicação recebe valores preenchidos em formulários HTML. Podemos observar o processo de conversão de outro ponto de vista. o JSF define conversores padrões e os aplica de maneira implícita. A informação digitada nesse campo é tratada como texto puro até chegar na aplicação que deve converter esse dado para algum tipo adequado do Java como INT ou LONG. Veremos a seguir o funcionamento desse mecanismo. esses dados não possuem tipagem. Felizmente. Nem sempre o formato das informações que estão em uma aplicação web Java corresponde ao formato que desejamos que seja apresentado para os usuários. Dessa forma. os valores escolhidos são enviados para uma aplicação. ou seja. os dados devem ser convertidos antes de enviados para os navegadores.1 Conversão Padrão Implícita Para os tipos fundamentais da linguagem Java. Eles são tratados como texto puro. ela precisa realizar a conversão dos dados que deseja tratar de forma específica. Novamente. Os tipos fundamentais do Java são: • BigDecimal • BigInteger • Boolean • Byte • Character 95 . não precisamos fazer nada para o processo de conversão acontecer. Eventualmente. De acordo com o HTTP.1. 10.

com. // GETTERS AND SETTERS } 1 2 <!-.br 96 . para trabalhar com valores monetários precisamos de outros conversores.valor}" > <f:convertNumber pattern="#0.valor}" > <f:convertNumber minFractionDigits="2" /> </h:outputText> Defindo a formatação através de expressão regular: 1 2 3 <h:outputText value="#{managedbean. Por isso.000" /> </h:outputText> www.1.Conversão e Validação • Double • Float • Integer • Long • Short 1 2 3 4 5 6 7 @ManagedBean public class MeuManagedBean { private double numero. f:convertNumber A tag f:convertNumber permite que conversões mais sofisticadas sejam feitas em valores numéricos.O valor digitado nesse campo será convertido para double --> <h:inputText value="#{meuManagedBean.k19. o JSF define dois outros conversores padrões para serem aplicados de maneira explícita. Estipulando duas casas decimais no mínimo: 1 2 3 <h:outputText value="#{managedbean. os conversores padrões aplicados implicitamente nos tipos fundamentais do Java não são suficientes. Por exemplo.numero}" /> 10.2 Conversão Padrão Explícita Em alguns casos.

devemos utilizar a componente h:message.2.valor}" > <f:convertNumber type="percent" /> </h:outputText> Utilizando o símbolo do Real para valores monetários: 1 2 3 <h:outputText value="#{managedbean.Conversão e Validação Apresentando os dados em porcentagem: 1 2 3 <h:outputText value="#{managedbean. Depois.Date. geralmente. 10. as informações preenchidas pelos usuários em formulários não são adequadas impedindo a conversão dos dados. 1 2 3 <h:outputText value="#{managedbean.valor}" > <f:convertNumber currencySymbol="R$" type="currency" /> </h:outputText> f:convertDateTime A tag f:convertDateTime permite que conversões de datas sejam realizadas. temos que definir um id para o campo desejado.2 Mensagens de Erro Eventualmente. Nesses casos.date}"> <f:convertDateTime pattern="dd/MM/yyyy" /> </h:outputText> 10. desejamos apresentar para os usuários mensagens relacionadas aos erros no preenchimento das informações. Esse conversor pode ser aplicado em dados do tipo java. Primeiro. 97 K19 Treinamentos .util.1 h:message Para adicionar nas telas erros relacionados a um determinado campo.

queremos colocar todos os erros de todos os campos de um formulário juntos na tela.br 98 . // GETTERS AND SETTERS } 1 2 <h:inputText value="#{meuManagedBean.2. simplesmente.Conversão e Validação associar o h:message a esse id.org/en/jsr/detail?id=314 www. 1 <h:messages/> 10. Em alguns casos. 1 2 3 4 5 6 7 @ManagedBean public class MeuManagedBean { private double numero.com.k19. devemos aplicar a tag h:messages.2 h:messages A tag h:message permite que os erros dos diversos campos de um formulário sejam colocados um a um na tela.2. Inclusive.numero}" id="campo-numero"/> <h:message for="campo-numero"/> 10. Para isso.3 Alterando as Mensagens de Erro O texto de cada mensagem de erro de conversão ou validação está definido na especificação do JSF 2 que pode ser obtida através da url: http://jcp. podemos colocar as mensagens de erro de campo em lugares diferentes na página que será apresentada ao usuário.

properties num pacote chamado resources. Para isso. Para registrá-lo. O maior problema para definir um arquivo de mensagens no JSF é saber quais são as chaves que podemos utilizar.3 Exercícios 1. Registrando um Arquivo de Mensagens Suponha que você tenha criado um arquivo de mensagem chamado Messages.Conversão e Validação Essas mensagens estão definidas em inglês. Registrar o arquivo de mensagens.BooleanConverter.converter. Veja um exemplo de arquivo de mensagens: 1 javax. Criando um Arquivo de Mensagens Um arquivo de mensagens é um conjunto de chaves e valores. Os arquivos de mensagens devem possuir o sufixo properties.faces.xml. 2. Para conhecer as chaves. devemos seguir dois passos: 1. 2.BOOLEAN={1}: ’’{0}’’ must be ’true’ or ’false’. 1 2 3 <application> <message-bundle>resources. devemos consultar a especificação do JSF que pode ser obtida através da url: http://jcp. Normalmente. Acrescente um pacote na pasta src chamado managedbean e adicione a seguinte classe nesse pacote: 99 K19 Treinamentos . Sendo que cada chave se refere a um tipo de erro e está associada a um valor que é o texto que será apresentado nas telas através das tags h:message ou h:messages. você deve acrescentar uma configuração no arquivo faces-config. queremos personalizar essas mensagens.org/en/jsr/detail?id=314. Criar um arquivo de mensagens. Crie um projeto do tipo Dynamic Web Project chamado ConversaoValidacao seguindo os passos vistos no exercício do capítulo 5.Messages</message-bundle> </application> 10.

Faça um pacote chamado resources na pasta src e adicione um arquivo de mensagens nesse pacote chamado Messages. Adicione um arquivo na pasta WebContent chamado cadastro.properties com o seguinte conteúdo. Crie uma tela para cadastrar funcionários.aniversario}"> <f:convertDateTime pattern="dd/MM/yyyy"/> </h:inputText> <h:message for="campo-aniversario"/> <h:commandButton value="Cadastrar"/> </h:panelGrid> <h:messages/> </h:form> </h:body> </html> Preencha o formulário várias vezes com valores errados e observe os erros.salario}"> <!-.k19. 4.sun.com/jsf/html" xmlns:f="http://java. private Date aniversario.w3.com.Conversão e Validação 1 2 3 4 5 6 7 8 9 10 11 @ManagedBean public class FuncionarioBean { private double salario.org/TR/xhtml1/DTD/xhtml1-transitional.0 Transitional//EN" "http://www.codigo}"/> <h:message for="campo-codigo"/> <h:outputLabel value="Data: (dd/MM/yyyy)" for="campo-aniversario"/> <h:inputText id="campo-aniversario" value="#{funcionarioBean. private int codigo.Sistema numérico do Brasil --> <f:convertNumber locale="pt_BR"/> </h:inputText> <h:message for="campo-salario"/> <h:outputLabel value="Código: " for="campo-codigo"/> <h:inputText id="campo-codigo" value="#{funcionarioBean. www. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.w3.br 100 .dtd"> <html xmlns="http://www. // GETTERS AND SETTERS } 3.org/1999/xhtml" xmlns:h="http://java.xhtml.com/jsf/core"> <h:head> <title>Cadastro de Funcionário</title> </h:head> <h:body> <h1>Cadastro de Funcionário</h1> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="Salário: R$ " for="campo-salario"/> <h:inputText id="campo-salario" value="#{funcionarioBean.sun.

4.faces.Conversão e Validação 1 2 3 4 5 6 javax.converter. 1 2 3 <application> <message-bundle>resources. javax. Adicione a configuração necessária no faces-config.converter. Podemos aplicar essa validação utilizando o atributo required dos inputs. javax. suponha um campo para os usuários digitarem uma idade. Essa conversão não verifica se o número obtido é negativo. javax.4. javax.faces. o valor digitado será tratado como texto até chegar na aplicação e lá poderá ser convertido para INT. 1 2 <h:inputText value="#{managedbean. Porém. mais uma etapa deve ser realizada para validar as informações. Preencha o formulário várias vezes com valores errados e observe as novas mensagens.converter.converter. A seguir veremos a aplicação desses validadores: 10. 101 K19 Treinamentos .Messages</message-bundle> </application> Observação: a tag <application> deve ser colocada dentro de faces-config.xml para utilizar o arquivo de mensagens criado no exercício anterior.faces. Dessa forma.4. nesse caso.faces. 10.INTEGER_detail={0} não é um número inteiro.faces. Como visto anteriormente.nome}" id="campo-nome" required="true"/> <h:message for="campo-nome"/> 10. não seria correto obter números negativos pois a idade de uma pessoa é sempre positiva. depois da conversão dos dados. javax.NumberConverter.DATE=A data {0} não está correta. 6.INTEGER=O valor {0} não é adequado.DATE_detail= {0} não parece uma data. apenas a conversão de dados não é suficiente para verificar se uma informação preenchida em um formulário por um usuário está correta. Por exemplo.DateTimeConverter.faces.2 Campo Obrigatório (Required) A validação mais comum de todas é a de verificar se um determinado campo não deixou de ser preenchido.converter. 10.converter.3 f:validateLongRange O validador f:validateLongRange é utilizado para verificar se um valor numérico inteiro pertence a um determinado intervalo de números.NUMBER=O valor {0} não é adequado.DateTimeConverter. 5.IntegerConverter.1 Validação Padrão O JSF também define validadores padrões para serem aplicados nos dados obtidos dos usuários.NumberConverter.NUMBER_detail={0} não é número ou é inadequado.4 Validação Muitas vezes.IntegerConverter.

5 f:validateLength O validador f:validateLength é utilizado para verificar se uma string possui uma quantidade mínima ou máxima de letras. www.org/en/jsr/detail?id=303.nome}" id="campo-nome"> <f:validateRegex pattern="[a-zA-Z]{6. 1 2 3 4 <h:inputText value="#{managedbean. 1 2 3 4 <h:inputText value="#{managedbean.preco}" id="campo-preco"> <f:validateDoubleRange minimum="20. basta adicionar anotações nas classes de modelo. 1 2 3 4 <h:inputText value="#{managedbean.idade}" id="campo-idade"> <f:validateLongRange minimum="10" maximum="130" /> </h:inputText> <h:message for="campo-idade"/> 10.nome}" id="campo-nome"> <f:validateLength minimum = "6" maximum = "20"/> </h:inputText> <h:message for="campo-nome"/> 10. A grande vantagem das validações definidas nas classes de modelo é que elas podem ser utilizadas em diversas partes da aplicação.4.7 Bean Validation Uma nova abordagem para definir as validações foi adicionada no JSF2. Para definir as validações com Bean Validation.20}"/> </h:inputText> <h:message for="campo-nome"/> 10.br 102 .com.57" maximum="200. Esse novo recurso é chamado Bean Validation e foi definido pela especificação JSR 303 que pode ser obtida através da url: http://jcp.4.4.k19. A ideia é declarar as regras de validação nas classes de modelo ao invés de inserí-las nas telas.56" /> </h:inputText> <h:message for="campo-preco"/> 10.Conversão e Validação 1 2 3 4 <h:inputText value="#{managedbean.6 f:validateRegex O validador f:validateRegex é utilizado para verificar se um texto respeita uma determinada expressão regular.4 f:validateDoubleRange O validador f:validateDoubleRange é utilizado para verificar se um valor numérico real pertence a um determinado intervalo de números.4.

.5 Exercícios 7. } 10. Podemos acrescentar mensagens de erro através das anotações. No projeto ConversaoValidacao. O arquivo que você criará deve se chamar cadastra-produto.xhtml. . 103 K19 Treinamentos . } @NotNull: o valor não pode ser nulo. . @Pattern: aplica uma expressão regular na validação. crie uma tela para cadastrar produtos de uma loja virtual. @Size: define um valor mínimo e máximo. 1 2 3 4 5 public class Funcionario { @NotNull(message="O nome não pode ser nulo") private String nome...Conversão e Validação 1 2 3 4 5 6 public class Funcionario { @NotNull private String nome. @Min: define um valor mínimo.. @Max: define um valor máximo.

com. 1 2 3 4 5 6 public class Produto { private String nome.w3.com/jsf/core"> <h:head> <title>Cadastro de Produto</title> </h:head> <h:body> <h:form> <h:panelGrid columns="3"> <h:outputLabel value="Nome: " for="produto-nome"/> <h:inputText id="produto-nome" required="true" value="#{produtoBean.nome}"/> <h:message for="produto-nome" /> <h:outputLabel value="Preço: " for="produto-preco"/> <h:inputText id="produto-preco" required="true" value="#{produtoBean.sun. www. Adicione essa classe dentro de um pacote chamado model.k19. Crie a classe de modelo para definir os produtos.Conversão e Validação 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.w3.sun. Teste o formulário preenchendo diversos valores e observe as mensagens de erro. // GETTERS AND SETTERS } 10.produto.0 Transitional//EN" "http://www. // GETTERS AND SETTERS } 9.org/TR/xhtml1/DTD/xhtml1-transitional.preco}"> <f:validateDoubleRange minimum="0" /> </h:inputText> <h:message for="produto-preco" /> <h:commandButton value="Cadastrar" /> </h:panelGrid> </h:form> </h:body> </html> 8.br 104 .org/1999/xhtml" xmlns:h="http://java. 1 2 3 4 5 6 @ManagedBean public class ProdutoBean { private Produto produto = new Produto().com/jsf/html" xmlns:f="http://java.produto. private double preco. Depois.dtd"> <html xmlns="http://www. Faça a classe ProdutoBean dentro do pacote managedbeans. implemente o Managed Bean que dará suporte à tela de cadastro de produtos.

Acrescente uma validação com as anotações da especificação de Bean Validation na classe P RODUTO. Teste novamente o formulário. 105 K19 Treinamentos . @Min(value = 0) private double preco. 13. Retire a validação realizada com a tag f:validateDoubleRange. (Opcional) Altere as mensagens de erros do formulário de cadastro de produto. // GETTERS AND SETTERS } 12.Conversão e Validação 11. 1 2 3 4 5 6 7 8 public class Produto { private String nome.

br 106 .com.Conversão e Validação www.k19.

nenhuma tecnologia oferece. veremos que ele oferece um mecanismo bem sofisticado para aumentar a interatividade com os usuários.Capítulo 11 Eventos Normalmente. Mas. O nível mais alto de interatividade aconteceria se uma aplicação pudesse perceber e reagir aos pensamentos dos usuários. Consequentemente. Um Action Method deve ser utilizado quando desejamos efetuar uma navegação (mudar de tela) após o tratamento do evento. Os eventos de ciclo de vida correspondem às transições entre as diversas etapas do processamento de uma requisição ou às transições entre os estados dos componentes do JSF ou da própria aplicação. Esse mecanismo é baseado na ideia de eventos. devemos utilizar um Action Listener Method. 11.1 ActionEvent Os ActionEvents são gerados por botões ou links quando esses são pressionados pelos usuários. Caso contrário.1. A interatividade de uma aplicação está diretamente relacionada a sua capacidade de percepção e reação. O JSF suporta dois tipos de eventos de aplicação: ActionEvent e ValueChangeEvent.1 Eventos de Aplicação (Application Events) Como dito anteriormente. No JSF. 11. há duas categorias fundamentais de eventos: eventos de aplicação e eventos de ciclo de vida. O JSF não oferece esse nível de interação. Os eventos de aplicação correspondem às ações dos usuários que são pertinentes às aplicações. Esses métodos são classificados em dois tipos: Action Method ou Action Listener Method. 107 . um usuário pressiona um botão ou altera o valor de preenchido em um campo de um formulário. na verdade. as pessoas preferem utilizar aplicações que ofereçam maior grau de interatividade. as empresas buscam sistemas mais interativos para controlar os seus negócios e serem utilizados pelos seus funcionários. O tratamento dos ActionEvents pode ser definido por métodos dentro dos Managed Beans. os eventos de aplicação correspondem às ações dos usuários que interessam para as aplicações. Por exemplo.

Action Listener Method Um Action Listener Method precisa ser void e aceita um ActionEvent como argumento.salva}" /> 1 2 3 public void salva(ActionEvent event) { // implementação } No h:commandButton definimos qual é o Action Listener Method que queremos associar ao botão através do atributo actionListener. Veja um exemplo de Action Method.1. 11.2 ValueChangeEvent Os ValueChangeEvent são gerados quando os usuários modificam o valor preenchido em um campo de um formulário.com. } No h:commandButton definimos qual é o Action Method que queremos associar ao botão através do atributo action.salva}" /> 1 2 3 4 public String salva() { // implementação return "lista-produtos".mudaPrecoListener}"/> 1 2 3 public void mudaPrecoListener(ValueChangeEvent event) { // implementação } www.br 108 . Um Value Change Listener precisa ser void e aceita um ValueChangeEvent como argumento.Eventos Action Method Um Action Method deve devolver uma String que será utilizada como outcome para processar uma navegação.k19. 1 2 <h:outputLabel value="Preço: "/> <h:inputText valueChangeListener="#{produtoBean. O tratamento desse tipo de evento pode ser realizado por métodos de um Managed Bean. Um ActionEvent contem informações sobre o evento disparado. Um ValueChangeEvent contem informações sobre o evento disparado. 1 <h:commandButton value="Salva" action="#{produtoBean. 1 <h:commandButton value="Salva" actionListener="#{produtoBean. Esses métodos são chamados de Value Change Listeners.

Para criar um Phase Listener.ANY_PHASE. 109 K19 Treinamentos . Crie um projeto do tipo Dynamic Web Project chamado Eventos seguindo os passos vistos no exercício do capítulo 5.2 Eventos de Ciclo de Vida (Lifecycle Events) Os eventos de ciclo de vida são utilizados quando desejamos executar procedimentos antes ou depois de uma determinada etapa do processamento de uma requisição ou a cada mudança de estado de um componente do JSF e da própria aplicação.MeuPhaseListener</phase-listener> </lifecycle> 11. 1 2 3 <lifecycle> <phase-listener>listeners. 1 2 3 4 5 6 7 8 9 10 11 12 13 package listeners. Um Phase Event é tratado por um Phase Listener. Vamos montar um formulário de estados e cidades.3 Exercícios 1. 11. devemos escrever uma classe que implemente a interface PhaseListener. devemos apenas criar um Phase Listener e registrá-lo.Eventos No h:inputText definimos qual é o Value Change Listener queremos associar ao campo através do atributo valueChangeListener. Vamos discutir a respeito dos Phase Events que correspondem às transições entre as etapas do processamento das requisições.xml. crie um pacote chamado model e adicione a seguinte classe para representar os estados. Para isso. 2. Os métodos beforePhase() e afterPhase() são executados respectivamente antes e depois das fases associadas ao listener. Para registrar o nosso Phase Listener devemos acrescentar algumas configurações no facesconfig. } } O método getPhaseID() associa o listener a determinadas fases do processamento de uma requisição. Como o próprio JSF dispara automaticamente os Phase Events. public class MeuPhaseListener implements PhaseListener { public void beforePhase(PhaseEvent pe) { // implementação } public void afterPhase(PhaseEvent pe) { // implementação } public PhaseId getPhaseId() { return PhaseId.

setNome("Rio de Janeiro"). sp. } public void mudaEstado(ValueChangeEvent vce) { this.xhtml na pasta WebContent.k19. public LocalidadeBean() { Estado sp = new Estado(). private String sigla.getCidades(). public class Estado { private String nome.com. private List<Estado> estados = new ArrayList<Estado>().equals(this.setSigla("RJ"). crie um pacote managedbeans e adicione um Managed Bean para manipular os estados.br 110 . private String siglaEstado.getCidades().getNewValue().toString(). Faça a tela de busca de estados e cidade.add(rj).add("Rio de Janeiro").setNome("São Paulo"). this. for(Estado e : this. www. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package managedbeans.siglaEstado)){ this.add("Niterói").getCidades().Eventos 1 2 3 4 5 6 7 8 9 10 11 package model.getCidades(). this. // GETTERS AND SETTERS } 3.estados){ if(e.siglaEstado = vce. rj. rj. Adicione um arquivo chamado busca-localidade. sp. sp. rj. } } } // GETTERS AND SETTERS } 4.getSigla().estados. private Estado estado = new Estado().add("São Paulo"). sp. Estado rj = new Estado(). private List<String> cidades = new ArrayList<String>().setSigla("SP"). @ManagedBean @SessionScoped public class LocalidadeBean { private String cidade.estado = e. Depois. rj.add("Campinas").estados.add(sp).

sun.sigla}" /> </h:selectOneMenu> <h:outputLabel value="Cidade: " for="campo-cidade" /> <h:selectOneMenu id="campo-cidade" value="#{localidadeBean.mudaEstado}" onchange="this.com/jsf/core"> <h:head> <title>Busca Localidade</title> </h:head> <h:body> <h1>Busca Localidade</h1> <h:form> <h:outputLabel value="Estado: " for="campo-estado" /> <h:selectOneMenu id="campo-estado" value="#{localidadeBean.estados}" var="e" itemLabel="#{e.form.submit().sun.org/TR/xhtml1/DTD/xhtml1-transitional.siglaEstado}" valueChangeListener="#{localidadeBean.org/1999/xhtml" xmlns:h="http://java.0 Transitional//EN" "http://www.cidade}"> <f:selectItems value="#{localidadeBean.dtd"> <html xmlns="http://www."> <f:selectItems value="#{localidadeBean.w3.estado.cidades}" /> </h:selectOneMenu> </h:form> </h:body> </html> 111 K19 Treinamentos .Eventos 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.w3.nome}" itemValue="#{e.com/jsf/html" xmlns:f="http://java.

Eventos www.com.br 112 .k19.

. Veremos como utilizar esse suporte. não é interessante recarregar uma página inteira só para modificar um pequeno “pedaço” da tela pois isso deixará os usuários insatisfeitos. Isso porque a tag f:ajax assume o evento padrão do componente associado a ela. 12. suponha uma página de listagem de fotos que possua paginação. a segunda é poder realizar requisições sem pausar a navegação dos usuários. Outro exemplo. oferece suporte nativo a AJAX.. suponha uma aplicação de Instant Message (gtalk. 1 2 3 <h:inputText> <f:ajax/> </h:inputText> No exemplo acima. com o intuito de melhorar a interatividade entre as aplicações e os usuários.). Para fazer isso. O componente h:inputText utiliza por padrão o evento onchange. podemos recarregar apenas os itens na listagem. Aplicando a ideia do AJAX obtemos duas capacidades muito uteis: a primeira é poder fazer requisições sem recarregar as páginas completamente e sim a parte delas que nos interessa. 113 .1 Fazendo requisições AJAX As requisições AJAX são realizadas quando determinados eventos definidos pela linguagem Javascript ocorrem. Quando o usuário pressiona o link para a próxima página. msn. podemos aplicar o conceito do AJAX (Asynchronous Javascript And XML). A versão 2 do JSF. Por exemplo. . não é necessário recarregar todo o conteúdo da tela. devemos utilizar a tag f:ajax (principal tag do suporte nativo do JSF para aplicar o conceito do AJAX). uma requisição AJAX será disparada quando o valor do campo for modificado. Novamente. diferentemente das anteriores. A listagem de contatos pode ser atualizada frequentemente sem os usuários pedirem e sem que eles tenham que para a navegação para essa atualização. Esses eventos estão fortemente relacionados aos componentes visuais colocados nas telas. Precisamos indicar para o JSF quais componentes e eventos devem disparar requisições para o servidor.Capítulo 12 Ajax Quando as aplicações possuem telas complexas com grande quantidade de conteúdo.

podemos explicitar o evento que deve disparar as requisições AJAX deixando o código mais claro através do atributo event. www.2 Recarregando alguns “pedaços” das telas Após realizar uma requisição AJAX.br 114 . 1 2 3 4 5 <f:ajax event="mouseout"> <h:inputText/> <h:inputSecret/> <h:commandButton value="OK"/> <f:ajax> 12. Devemos tomar cuidado pois nem todos os eventos são aceitos por todos os componentes. se não escolhermos explicitamente o evento que vai disparar as requisições o JSF assumirá o padrão de cada componente. podemos agrupá-los através da tag f:ajax. O padrão dos componentes h:inputText e h:inputSecret é onchange.k19. Por exemplo.Ajax Por outra lado. O padrão do componente h:commandButton é onclick. suponha uma listagem paginada de produtos.numero"/> Podemos redesenhar vários componentes. podemos mandar o JSF redesenhar a listagem e apenas a listagem com os dados que acabaram de chegar. A tag f:ajax através do atributo render permite escolher os ids dos componentes que devem ser recarregados após uma requisição AJAX. podemos explicitar o evento que deve disparar as requisições AJAX para um determinado grupo de componentes da mesma forma que fizemos anteriormente. 1 2 3 <h:inputText> <f:ajax event="keyup"/> </h:inputText> Quando temos vários componentes para os quais desejamos oferecer o suporte do AJAX.com. Mas. quando o usuário clica no botão que requisita através de AJAX a próxima página e a resposta chega. 1 2 3 4 <h:commandButton value="Gera Número"> <f:ajax event="click" render="numero"/> <h:commandButton/> <h:outputText id="numero" value="managedBean. 1 2 3 4 5 <f:ajax> <h:inputText/> <h:inputSecret/> <h:commandButton value="OK"/> <f:ajax> Novamente. basta passar uma listagem de ids no valor do atributo render. podemos pedir para o JSF redesenhar alguns “pedaços” da tela que está sendo mostrada para o usuário.

@all : refere-se a todos os componentes da tela. o JSF criou palavras chaves associadas a grupos especiais de componente. Quando escolhemos um componente para ser avaliados os componentes dentro dele também serão. quando enviamos um formulário.3 Processando alguns “pedaços” das telas Quando uma requisição AJAX é feita. provavelmente. podemos determinar quais componentes da tela devem ser avaliados pelo JSF.message}"/> 12. 115 K19 Treinamentos .numero2"/> 12.Ajax 1 2 3 4 5 <h:commandButton value="Gera Números"> <f:ajax event="click" render="numero1 numero2"/> <h:commandButton/> <h:outputText id="numero1" value="managedBean. Dessa forma.numero1"/> <h:outputText id="numero2" value="managedBean. podemos trabalhar sem a necessidade de definir ids em alguns casos.4 Palavras especiais Como podemos passar uma lista de componentes para os atributos render e execute. @nome : refere-se a nenhum componente. Podemos alterar o código do formulário anterior para utilizar a palavra especial @form no lugar do id do formulário. 1 2 3 4 5 6 7 8 9 10 <h:form id="formulario"> <h:inputText/> <h:inputSecret/> <h:commandButton value="Entrar"> <f:ajax event="click" render="message" execute="formulario"/> <h:commandButton/> </h:form> <h:outputText id="message" value="#{loginBean. @form : refere-se aos componentes do formulário que contém o componente que disparou a requisição AJAX. @this : refere-se ao componente que disparou a requisição AJAX. Podemos definir quais componentes devem ser avaliados pelo JSF através do atributo execute passando uma lista de ids. só é necessário avaliar os componentes que estão no próprio formulário. Por exemplo.

Para isso. private List<Automovel> automoveis = new ArrayList<Automovel>(). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package managedbeans.automoveis.automovel = new Automovel().add(this. Faça a tela de listagem e cadastro de automóveis.xhtml na pasta WebContent. 1 2 3 4 5 6 7 8 9 10 package model. Depois. crie um pacote chamado model e adicione a seguinte classe para representar os automóveis.com. } // GETTERS AND SETTERS } 4. @ManagedBean @SessionScoped public class AutomovelBean { private Automovel automovel = new Automovel().message}"/> 12. 2. www. Crie um projeto do tipo Dynamic Web Project chamado Ajax seguindo os passos vistos no exercício do capítulo 5. Vamos montar um formulário de cadastro de automóveis. // GETTERS AND SETTERS } 3.Ajax 1 2 3 4 5 6 7 8 9 10 <h:form> <h:inputText/> <h:inputSecret/> <h:commandButton value="Entrar"> <f:ajax event="click" render="message" execute="@form"/> <h:commandButton/> </h:form> <h:outputText id="message" value="#{loginBean. Adicione um arquivo chamado listacadastro-automovel. crie um pacote managedbeans e adicione um Managed Bean para manipular os automóveis. public void adiciona(){ this. private String marca.5 Exercícios 1. this. public class Automovel { private String nome.automovel).br 116 .k19.

automovel.org/1999/xhtml" xmlns:h="http://java.adiciona}"/> </h:commandButton> </h:panelGrid> <h1>Lista de Automóveis</h1> <h:dataTable id="lista" value="#{automovelBean.w3.w3.com/jsf/core"> <h:head> <title>Automóveis</title> </h:head> <h:body> <h1>Novo Automóvel</h1> <h:form> <h:panelGrid columns="2"> <h:outputLabel value="Nome: " for="campo-nome" /> <h:inputText id="campo-nome" value="#{automovelBean.org/TR/xhtml1/DTD/xhtml1-transitional.automovel.nome}" /> <h:outputLabel value="Marca: " for="campo-marca" /> <h:inputText id="campo-marca" value="#{automovelBean.0 Transitional//EN" "http://www.sun.marca}" /> <h:commandButton value="Cadastrar"> <f:ajax event="click" render="lista" execute="@form" listener="#{automovelBean.automoveis}" var="automovel"> <h:column> <f:facet name="header"> <h:outputText value="Nome" /> </f:facet> #{automovel.Ajax 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.sun.marca} </h:column> </h:dataTable> </h:form> </h:body> </html> 117 K19 Treinamentos .dtd"> <html xmlns="http://www.com/jsf/html" xmlns:f="http://java.nome} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Marca" /> </f:facet> #{automovel.

Ajax www.com.k19.br 118 .

mostraremos alguns padrões e conceitos relacionados ao desenvolvimento de aplicações web. No nosso caso. Devemos estabelecer um relacionamento entre essas entidades já que um jogador atua em uma seleção. 2. 13. // GETTERS AND SETTERS } 119 .Capítulo 13 Projeto Nos capítulos anteriores.2 Exercícios 1. Como exemplo de aplicação desenvolveremos uma aplicação de cadastro de jogadores e seleções de futebol. vimos isoladamente recursos do JSF e do JPA. Agora. 13. 1 2 3 4 5 6 7 8 public class Selecao { private String pais. Além disso. private String tecnico. vamos mostrar em detalhes como esses recursos trabalham juntos e solidificar os conhecimentos obtidos. Faça um pacote chamado modelo e adicione as duas classes principais da nossa aplicação.1 Modelo Por onde começar o desenvolvimento de uma aplicação? Essa é uma questão recorrente. Um ótimo ponto de partida é desenvolver as entidades principais da aplicação. vamos nos restringir às entidades Selecao e Jogador. Crie um projeto do tipo Dynamic Web Project chamado K19-CopaDoMundo seguindo os passos vistos no exercício do capítulo 5.

// GETTERS AND SETTERS } 13. Adicione as anotações do JPA nas classes de modelo. private String tecnico.3 Persistência .Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Jogador { private String nome.Mapeamento Depois de definir algumas entidades podemos começar o processo de implementação da persistência da nossa aplicação. private String pais. private Calendar nascimento = new GregorianCalendar(). 13. private String posicao. // GETTERS AND SETTERS } www.k19. vamos definir o mapeamento das nossas entidades através das anotações adequadas. Inicialmente. Vamos aplicar os recursos do JPA que aprendemos nos primeiros capítulos.com.4 Exercícios 3.br 120 . 1 2 3 4 5 6 7 8 9 10 11 12 @Entity public class Selecao { @Id @GeneratedValue private Long id. private double altura. private Selecao selecao.

devemos adicionar o driver JDBC que desejamos utilizar nas bibliotecas do Glassfish.JAVA -5. Depois disso.CONNECTOR . devemos configurar as propriedades do JPA através do arquivo persistence.13.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Entity public class Jogador { @Id @GeneratedValue private Long id. private double altura. private String posicao. Entre na pasta K19-Arquivos/MySQL-Connector-JDBC da Área de Trabalho e copie o arquivo MYSQL . 13. geralmente.1. 121 K19 Treinamentos . private Calendar nascimento = new GregorianCalendar(). // GETTERS AND SETTERS } A anotação @ManyToOne é utilizada para indicar a cardinalidade do relacionamento entre jogadores e seleções. Adicione uma pasta chamada META-INF na pasta src do projeto K19-CopaDoMundo. Por outro lado. Dessa forma. JAR para pasta glassfishv3/glassfish/lib também da sua Área de Trabalho.Configuração Assim como nos capítulos anteriores. 5.BIN . Os servidores de aplicação Java EE já possuem uma implementação de JPA. Portanto. 6.6 Exercícios 4. Configure o JPA adicionando o arquivo persistence. private String nome.xml na pasta META-INF. 13. as aplicações não precisam se preocupar em obter um provedor de JPA. @ManyToOne private Selecao selecao. implantaremos a nossa aplicação no Glassfish que é um servidor de aplicação Java EE. os servidores de aplicação não são distribuídos com os principais drivers JDBC que normalmente as aplicação desejam utilizar.5 Persistência .xml.

com.com/xml/ns/persistence http://java. entre no cliente do MySQL Server.jdbc. devemos nos preocupar com a criação e destruição das fábricas de entity manager.jdbc.7 13. Além disso. todas as configurações e anotações são processadas e armazenadas na memória.0"> <persistence-unit name="copadomundo" transaction-type="RESOURCE_LOCAL"> <provider>org. www.hibernate.dialect. Para entrar no MySQL Server: mysql -u root -p Para apagar uma base de dados: DROP DATABASE copadomundo.com/xml/← ns/persistence/persistence_1_0. Para criar uma base de dados: CREATE DATABASE copadomundo.persistence.com/xml/ns/persistence" xmlns:xsi="http://www.driver" value="com.hibernate.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java. No contexto de uma aplicação web implementada com JSF.Open Session in View Gerenciando as fábricas de Entity Managers Quando trabalhamos com JPA.mysql.password" value="root" /> <property name="javax. Dessa forma.jdbc.persistence. Ao criar uma fábrica de Entity Manager.user" value="root" /> <property name="javax.jdbc.url" value="jdbc:mysql://← localhost:3306/copadomundo" /> </properties> </persistence-unit> </persistence> 7.auto" value="update" /> <property name="javax.dialect" value="org.sun. Abra um terminal.sun. conseguiremos garantir a existência da fábrica durante todo o período no qual a aplicação receberá requisições.Driver← " /> <property name="javax. podemos criar uma fábrica de entity manager exatamente antes da primeira requisição à servlet do JSF e destruí-la exatamente antes do encerramento da aplicação.ejb.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <persistence xmlns="http://java.HibernatePersistence</provider> <properties> <property name="hibernate. 13.xsd" version="1.jdbc. como esse procedimento pode consumir significativamente os recursos da máquina então realizá-lo duas ou mais vezes na mesma execução seria apenas desperdício.← MySQLInnoDBDialect" /> <property name="hibernate.k19.1 Persistência . só é necessário realizar esse processo uma vez para cada execução.persistence.7. apague se existir a base de dados copadomundo. e crie uma base de dados nova chamada copadomundo.br 122 .persistence.hbm2ddl.w3. De fato.sun.

@Override public void init(FilterConfig filterConfig) throws ServletException { this. a estratégia de gerenciamento de Entity Managers mais simples de entender e manter é adotar o padrão a Open Session in View. O método INIT () é chamado para inicializar o filtro imediatamente antes da primeira requisição ser enviada para a servlet do JSF. Na chegada de uma requisição. } @Override public void doFilter(ServletRequest request. 123 K19 Treinamentos . A ideia é associar o tempo de vida de um Entity Manager à duração do processamento de uma requisição. Dessa forma. 13. Criamos a fábrica de entity manager nesse método. antes da resposta ser enviada ao usuário.Projeto 13.factory = Persistence. O método DESTROY () é chamado para desativar o filtro imediatamente antes do encerramento da aplicação.factory. podemos criar um filtro no Web Container associado à servlet do JSF.3 Gerenciando os Entity Managers Provavelmente. ServletException { // por enquanto vazio } } Um filtro é registrado no Web Container através da anotação @WebFilter. antes da primeira requisição a essa servlet ele será iniciado e imediatamente antes da aplicação encerrar ele será desativado. antes da resposta ser enviada. a execução passa pelo filtro novamente.close(). } @Override public void destroy() { this. criamos um Entity Manager para ser utilizado no tratamento dessa requisição. Além disso. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @WebFilter(servletNames={"Faces Servlet"}) public class JPAFilter implements Filter { private EntityManagerFactory factory. FilterChain chain) throws IOException.createEntityManagerFactory("copadomundo"). fechamos o Entity Manager. quando esse processamento terminar. Ou seja. devemos criar um Entity Manager e adicioná-lo na requisição para que ele possa ser acessado pela aplicação durante o processamento dessa requisição. Para implementar o padrão Open Session in View. Imediatamente. quando uma requisição é realizada.7. ServletResponse response.2 Filtros Para implementar essa abordagem. Através dessa anotação definimos qual servlet está associada ao nosso filtro pelo nome da servlet. podemos utilizar o mesmo filtro que gerencia a criação e o fechamento das fábricas de Entity Manager pois as requisições passam por esse filtro antes de chegar até a servlet do JSF. devemos abrir e confirmar uma transação no Entity Manager para que as alterações decorrentes ao processamento da requisição sejam refletidas no banco de dados. Fechamos a fábrica de entity manager nesse método.7.

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

doFilter(request. chain. a tela de resposta já teria sido montada pelo Facelets com os dados do banco de dados sem a nova seleção. } @Override public void destroy() { this.commit(). cada repositório terá um construtor para receber um Entity Manager como parâmetro.Repositórios Vamos deixar os repositórios para acessar as entidades da nossa aplicação preparados. Mas.rollback().factory. Para resolver este problema. 125 K19 Treinamentos . FilterChain chain) throws IOException. } } 13. } finally { entityManager.getTransaction(). } } @Override public void init(FilterConfig filterConfig) throws ServletException { this. request.9 Persistência .getTransaction(). try { entityManager.createEntityManagerFactory("copadomundo").close(). Em outras palavras.getTransaction(). Os repositórios precisam de Entity Managers para realizar as operações de persistência. essa tela de listagem de seleções mostrará inclusive a nova seleção. A implementação desse repositório deve utilizar o método flush() que envia imediatamente para o banco de dados as alterações realizadas dentro da transação corrente sem confirmá-las (a confirmação só ocorre na chamada do método commit()). ServletResponse response.setAttribute("entityManager". Então. ServletException { EntityManager entityManager = this. response).close(). } catch (Exception e) { entityManager.createEntityManager(). o usuário veria uma listagem sem a seleção que ele acabou de cadastrar.factory = Persistence. o gerenciamento das transações não é uma tarefa dos repositórios. Dessa forma. entityManager). @Override public void doFilter(ServletRequest request. Como o padrão Open Session in View foi adotado na nossa aplicação.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @WebFilter(servletNames={"Faces Servlet"}) public class JPAFilter implements Filter { private EntityManagerFactory factory. o repositório de seleções pode enviar a nova seleção imediatamente para o banco de dados bem antes da montagem da tela de resposta. Nesse momento. Se um usuário faz uma requisição para cadastrar uma seleção ela só existirá no banco de dados quando o processamento voltar para o filtro que gerencia as transações.factory. entityManager.begin(). o funcionamento deles ainda é afetado pelo controle de transações.

www.entityManager . Faça um pacote chamado repositorios e adicione nele uma classe chamada SelecaoRepository. public SelecaoRepository(EntityManager entityManager) { this.entityManager.getResultList().entityManager.flush(). return query.createQuery("select s from Selecao as s").br 126 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class JogadorRepository { private EntityManager entityManager.flush().entityManager. } public List<Jogador> getJogadores() { Query query = this.10 Exercícios 9. this.createQuery("select j from Jogador as j"). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class SelecaoRepository { private EntityManager entityManager.entityManager. Veja como deve ficar o método doFilter(). Altere o filtro de gerenciamento de transações.persist(selecao). } } 10.entityManager = entityManager. Os outros repositórios podem adotar a mesma estratégia para garantir que os usuários vejam dados atualizados.Projeto Para que esse processo funcione.entityManager = entityManager. Abra uma transação na chegada de uma requisição.entityManager . } public void adiciona(Jogador jogador) { this. } public List<Selecao> getSelecoes() { Query query = this. } public void adiciona(Selecao selecao) { this.com. Caso contrário. o método flush() não funcionará no repositório de seleções. Analogamente crie um repositório de jogadores.k19.persist(jogador). devemos alterar o nosso filtro de gerenciamento transacional para que ele abra uma transação na chegada de uma nova requisição. return query. public JogadorRepository(EntityManager entityManager) { this. 13. } } 11. this.getResultList().

Na pasta WebContent.Template Vamos definir um template para as telas da nossa aplicação utilizando os recursos do Facelets.getTransaction().11 Apresentação .getTransaction().12 Exercícios 12. } 13. entityManager).createEntityManager(). } catch (Exception e) { entityManager. chain. entityManager. request.factory. crie um arquivo com algumas regras CSS chamado style.css. try { entityManager. Aplicaremos algumas regras CSS para melhorar a parte visual das telas.doFilter(request.setAttribute("entityManager".close(). 13. } finally { entityManager.getTransaction(). response).commit().Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 EntityManager entityManager = this.begin().rollback(). 127 K19 Treinamentos .

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

com/jsf/html"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style. 1 2 3 4 5 6 7 8 9 <html xmlns="http://www. Adicione duas telas.com/jsf/facelets" xmlns:h="http://java. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.sun.xhtml e jogadores. Essas duas telas devem utilizar o template criado no exercício anterior. Agora implemente um template utilizando Facelets.org/TR/xhtml1/DTD/xhtml1-transitional. Todos os direitos reservados.sun. Os arquivos devem se chamar: selecoes.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.org/1999/xhtml" xmlns:ui="http://java.com/jsf/facelets" xmlns:h="http://java. 2010 K19.Projeto 14.xhtml">Jogadores</← h:outputLink> <hr/> </div> <ui:insert name="conteudo"> Espaço para o conteúdo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy. </div> </h:body> </html> 15.0 Transitional//EN" "http://www.sun.w3.png" /> <h:outputLink styleClass="botao" value="selecoes.dtd"> <html xmlns="http://www.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.sun. uma para seleções e outra para jogadores.org/1999/xhtml" xmlns:ui="http://java. Acesse as duas telas criadas anteriormente. Crie um arquivo chamado template. Aplicaremos regras de validação específicas para garantir que nenhum dado incorreto seja armazenado no banco de dados. utilizaremos os recursos nativos do JSF 2 para aplicar as técnicas de AJAX.xhtml"> </ui:composition> </html> 16. Além disso.xhtml na pasta WebContent.com/jsf/html" xmlns:f="http://java.com/jsf/core"> <ui:composition template="template.13 Cadastrando e Listando Seleções Na tela de seleções.w3.sun. 13.w3.xhtml e ambos devem possuir o seguinte conteúdo. 129 K19 Treinamentos . vamos adicionar um formulário para cadastrar novas seleções e uma tabela para apresentar as já cadastradas.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <html xmlns="http://www.selecao. www.xhtml na pasta WebContent com o seguinte conteúdo.sun.com/jsf/html" xmlns:f="http://java. Adicione o arquivo cadastro-selecao. Para garantir uma melhor legibilidade da nossa aplicação.sun.14 Exercícios 17.selecao.tecnico}"> <f:validateLength minimum="6" /> </h:inputText> <h:message for="selecao-tecnico" styleClass="mensagem-erro" /> <h:commandButton value="Cadastrar" styleClass="botao-formulario"> <f:ajax event="click" execute="@form" listener="#{selecaoBean.k19.pais}"> <f:validateLength minimum="3" /> </h:inputText> <h:message for="selecao-pais" styleClass="mensagem-erro" /> <h:outputLabel value="Técnico: " for="selecao-tecnico" /> <h:inputText id="selecao-tecnico" required="true" value="#{selecaoBean. criaremos uma tela parcial com os campos e o botão referentes ao cadastramento de seleções.w3. Analogamente ao exercício anterior.com/jsf/facelets" xmlns:h="http://java.sun.xhtml na pasta WebContent com o seguinte conteúdo.com/jsf/core"> <fieldset> <legend>Nova Seleção</legend> <h:panelGrid columns="3"> <h:outputLabel value="País: " for="selecao-pais" /> <h:inputText id="selecao-pais" required="true" value="#{selecaoBean. vamos criar uma tela parcial para apresentar as seleções dentro de uma tabela. Adicione o arquivo listagem-selecoes.adiciona}" render="@form" /> </h:commandButton> </h:panelGrid> </fieldset> </html> 18.org/1999/xhtml" xmlns:ui="http://java.Projeto 13.com.br 130 .

xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <ui:include src="/cadastro-selecao.sun.xhtml"/> <ui:include src="/listagem-selecoes.xhtml.com/jsf/core"> <h3 class="titulo">Listagem de Seleções</h3> <h:dataTable id="tabela" value="#{selecaoBean.org/1999/xhtml" xmlns:ui="http://java.sun. O próximo passo é montar a tela principal de seleções agrupando as telas parciais criadas anteriormente. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <html xmlns="http://www.org/1999/xhtml" xmlns:ui="http://java.w3.com/jsf/html" xmlns:f="http://java.pais} </h:column> <h:column> <f:facet name="header"> <h:outputText value="Técnico" /> </f:facet> #{selecao. 131 K19 Treinamentos . Veja como deve ficar o arquivo selecoes.sun.sun.com/jsf/html" xmlns:f="http://java.xhtml"/> </h:form> </ui:define> </ui:composition> </html> 20.com/jsf/core"> <ui:composition template="/template.sun. Adicione um pacote chamado managedbeans.com/jsf/facelets" xmlns:h="http://java.id} </h:column> <h:column> <f:facet name="header"> <h:outputText value="País" /> </f:facet> #{selecao.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <html xmlns="http://www.w3.sun.com/jsf/facelets" xmlns:h="http://java. Implemente um Managed Bean para dar suporte às funcionalidades da tela de seleções.selecoes}" var="selecao" styleClass="tabela"> <h:column> <f:facet name="header"> <h:outputText value="Id" /> </f:facet> #{selecao.tecnico} </h:column> </h:dataTable> </html> 19.

} // GETTERS AND SETTERS } OBS: O Filtro que implementa o padrão Open Session in View armazena os Entity Managers em escopo de requisição.properties com o seguinte conteúdo: 1 2 javax.REQUIRED = Campo obrigatório javax. Adicione o seguinte trecho no arquivo faces-config.← getApplication(). Devemos registrar esse arquivo no faces-config. private Selecao selecao = new Selecao().br 132 .xml: www. Crie um pacote na pasta src chamado resources. } public List<Selecao> getSelecoes() { SelecaoRepository repository = new SelecaoRepository(this. this.component.k19.getSelecoes().selecao = new Selecao(). 13.entityManager).16 Exercícios 21.15 Mensagens de Erro Vamos personalizar as mensagens de erro criando um arquivo de mensagens em português.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @ManagedBean public class SelecaoBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager. return repository.com.selecao).MINIMUM = O número mínimo de caracteres é "{0}". Dessa forma podemos injetá-los nos Managed Beans com o mesmo escopo através da anotação @ManagedProperty.getCurrentInstance(). repository.LengthValidator. Adicione nesse pacote um arquivo chamadao Messages. 13. null. os Managed Beans com escopos maiores devem utilizar o seguinte código para acessar os Entity Managers. 1 2 ELContext elContext = FacesContext.validator.xml. EntityManager entityManager = (EntityManager) FacesContext. public void adiciona() { SelecaoRepository repository = new SelecaoRepository(this.UIInput.adiciona(this. "entityManager").getValue(elContext.getELContext(). Por outro lado.faces. 22.faces.entityManager).getELResolver().getCurrentInstance().

Implemente um método para remover seleções no repositório de seleções.entityManager).remove(selecao).17 Removendo Seleções Vamos acrescentar a funcionalidade de remover seleções utilizando o suporte de AJAX do JSF 2. Por exemplo. 13.19 Otimizando o número de consultas Os getters dos Managed Beans são chamados diversas vezes pelo JSF durante o processamento de uma requisição.Messages</message-bundle> </application> 13.remove(selecao)}"> <h:commandLink>Remover</h:commandLink> </f:ajax> </h:column> 24. o método getSelecoes() da classe SelecaoBean é 133 K19 Treinamentos .entityManager.remove(selecao). this. Adicione um método para remover seleções no Managed Bean SelecaoBean. 1 2 3 4 5 6 7 8 9 10 11 <h:column> <f:facet name="header"> <h:outputText value="Remover" /> </f:facet> <f:ajax event="click" render="@form" listener="#{selecaoBean.flush().18 Exercícios 23. Acrescente uma coluna na tabela que apresenta das seleções alterando o arquivo listagemselecoes.entityManager. } 25.Projeto 1 2 3 <application> <message-bundle>resources. 1 2 3 4 public void remove(Selecao selecao) { SelecaoRepository repository = new SelecaoRepository(this. SelecaoRepository. repository. } 13.xhtml. 1 2 3 4 public void remove(Selecao selecao) { this.

Altere a classe SelecaoBean para esse Managed Bean guardar os resultados das consultas feitas nos repositórios. www.br 134 . 13.xhtml. ou seja.entityManager).k19.println("CHAMANDO O REPOSITORIO").com. quando uma seleção for adicionada ou removida devemos descartar qualquer resultado armazenado no Managed Bean SelecaoBean. são realizadas cerca de nove consultas iguais para gerar a tela principal de seleções.getSelecoes(). Apenas devemos tomar cuidado para não manter informações desatualizadas nos Managed Beans.Projeto chamado cerca de nove vezes durante o processamento da requisição à página principal de seleções.out. Imprima uma mensagem no método getSelecoes() do Managed Bean SelecaoBean para verificar a quantidade de vezes que ele é chamado quando o usuário acessa a url: http://localhost:8080/K19-CopaDoMundo/selecoes. Verifique quantas vezes a mensagem é impressa no console do eclipse acessando a url: http://localhost:8080/K19-CopaDoMundo/selecoes. 1 2 3 4 5 public List<Selecao> getSelecoes() { System. SelecaoRepository repository = new SelecaoRepository(this.20 Exercícios 26. Podemos diminuir o número de consultas fazendo os Managed Beans armazenarem o resultado de uma consulta para utilizá-lo o maior número possível de vezes. Por exemplo. return repository. Esse método chama o getSelecoes() do repositório que por sua vez faz uma consulta no banco de dados. } 27.xhtml 28.

this. } // GETTERS AND SETTERS } 29. private Selecao selecao = new Selecao(). utilizaremos os recursos nativos do JSF 2 para aplicar as técnicas de AJAX.entityManager).adiciona(this.selecoes = repository. SelecaoRepository repository = new SelecaoRepository( this. } return this. this. repository.selecao = new Selecao(). Listando e Removendo Jogadores Na tela de jogadores. criaremos uma tela parcial com os campos e o botão referentes ao cadastramento de jogadores. Além disso. this. } public void remove(Selecao selecao) { SelecaoRepository repository = new SelecaoRepository(this. private List<Selecao> selecoes. } public List<Selecao> getSelecoes() { if (this.22 Exercícios 30.entityManager). Verifique quantas vezes a mensagem é impressa acessando novamente a url: http://localhost:8080/K19-CopaDoMundo/selecoes.entityManager).selecao). repository. vamos adicionar um formulário para cadastrar novos jogadores e uma tabela para apresentar os já cadastrados.selecoes = null. 135 K19 Treinamentos .xhtml na pasta WebContent com o seguinte conteúdo.selecoes.remove(selecao). this.out. Para garantir uma melhor legibilidade da nossa aplicação. 13. Aplicaremos regras de validação específicas para garantir que nenhum dado incorreto seja armazenado no banco de dados.selecoes == null) { System.21 Cadastrando. public void adiciona() { SelecaoRepository repository = new SelecaoRepository(this.selecoes = null.println("CHAMANDO O REPOSITORIO").getSelecoes().Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 @ManagedBean public class SelecaoBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager.xhtml 13. Adicione o arquivo cadastro-jogador.

selecoes}" var="selecao" itemLabel="#{selecao.com.br 136 .Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 <html xmlns="http://www.com/jsf/facelets" xmlns:h="http://java.adiciona}" render="@form" /> </h:commandButton> </h:panelGrid> </fieldset> </html> 31.k19. Analogamente ao exercício anterior.time}"> <f:convertDateTime pattern="dd/MM/yyyy" /> </h:inputText> <h:message for="jogador-nascimento" styleClass="mensagem-erro" /> <h:outputLabel value="Altura (m): " for="jogador-altura" /> <h:inputText id="jogador-altura" required="true" value="#{jogadorBean. www.sun. vamos criar uma tela parcial para apresentar os jogadores dentro de uma tabela.id}" /> </h:selectOneMenu> <h:message for="jogador-selecao" styleClass="mensagem-erro" /> <h:commandButton value="Cadastrar" styleClass="botao-formulario"> <f:ajax event="click" execute="@form" listener="#{jogadorBean.org/1999/xhtml" xmlns:ui="http://java.sun.jogador. Adicione o arquivo listagem-jogadores.posicao}"> </h:inputText> <h:message for="jogador-posicao" styleClass="mensagem-erro" /> <h:outputLabel value="Data de Nascimento: " for="jogador-nascimento" /> <h:inputText id="jogador-nascimento" required="true" value="#{jogadorBean.sun.jogador.com/jsf/html" xmlns:f="http://java.w3.jogador.nome}"> <f:validateLength minimum="6" /> </h:inputText> <h:message for="jogador-nome" styleClass="mensagem-erro" /> <h:outputLabel value="Posição: " for="jogador-posicao" /> <h:inputText id="jogador-posicao" required="true" value="#{jogadorBean.pais}" itemValue="#{selecao.selecaoID}"> <f:selectItems value="#{selecaoBean.xhtml na pasta WebContent com o seguinte conteúdo.altura}"> </h:inputText> <h:message for="jogador-altura" styleClass="mensagem-erro" /> <h:outputLabel value="Seleção: " for="jogador-selecao" /> <h:selectOneMenu id="jogador-selecao" value="#{jogadorBean.com/jsf/core"> <fieldset> <legend>Novo Jogador</legend> <h:panelGrid columns="3"> <h:outputLabel value="Nome: " for="jogador-nome" /> <h:inputText id="jogador-nome" required="true" value="#{jogadorBean.jogador.nascimento.

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

com/jsf/html" xmlns:f="http://java.entityManager.remove(jogador).class.org/1999/xhtml" xmlns:ui="http://java.entityManager. Crie um Managed Bean para trabalhar com a tela de jogadores.br 138 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <html xmlns="http://www.com.xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <ui:include src="/cadastro-jogador. O próximo passo é montar a tela principal de jogadores agrupando as telas parciais criadas anteriormente.find(Selecao.xhtml. Veja como deve ficar o arquivo jogadores.entityManager. this. 1 2 3 4 public void remove(Jogador jogador) { this.sun. Adicione um método no repositório de seleções para buscar por id.Projeto 32. www.com/jsf/facelets" xmlns:h="http://java.flush(). 1 2 3 public Selecao procura(Lond id) { return this. JogadorRepository.sun.xhtml"/> <ui:include src="/listagem-jogadores.com/jsf/core"> <ui:composition template="/template.w3. Implemente um método para remover jogadores no repositório de jogadores. } 34. } 35.xhtml"/> </h:form> </ui:define> </ui:composition> </html> 33. id).k19.sun.

jogadorRepository. } public void remove(Jogador jogador) { JogadorRepository repository = new JogadorRepository(this. teríamos jogadores vinculados com seleções que já teriam sido removidas. Outra possibilidade é remover a seleção e os jogadores quando o usuário clicar no link para remover uma seleção.selecaoID). Selecao selecao = selecaoRepository. 139 K19 Treinamentos .jogadores. private Jogador jogador = new Jogador().jogador. uma possibilidade é informar ao usuário que ele só pode remover seleções sem jogadores.jogador = new Jogador(). Tente remover pela interface web uma seleção que possua jogadores. Em outras palavras.getJogadores(). Devemos alterar o repositório de seleções para aplicar essa regra.jogadores = null. 13.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @ManagedBean public class JogadorBean { @ManagedProperty(value = "#{entityManager}") private EntityManager entityManager.23 Removendo Seleções com Jogadores Se uma seleção possui jogadores ela não poderá ser removida pois teríamos dados inconsistentes no banco de dados.jogadores = null. Nesse caso.adiciona(this.entityManager).24 Exercícios 36. } return this. private Long selecaoID. this.setSelecao(selecao). this. this.jogadores == null) { System. a maneira de proceder depende das regras da aplicação. this. } public List<Jogador> getJogadores() { if (this.remove(jogador).entityManager). repository.entityManager). public void adiciona() { SelecaoRepository selecaoRepository = new SelecaoRepository(this. } // GETTERS AND SETTERS } 13. private List<Jogador> jogadores. Vamos supor que a regra da nossa aplicação é remover tanto a seleção quanto os jogadores.out. Na verdade. this. JogadorRepository jogadorRepository = new JogadorRepository(this.println("CHAMANDO O REPOSITORIO").jogadores = repository.entityManager).jogador).procura(this. JogadorRepository repository = new JogadorRepository( this.

remove(selecao). selecao).br 140 . A função do filtro é verificar se o usuário está logado ou não. } 13.k19. List<Jogador> jogadores = query. Se estiver logado o filtro autoriza o acesso. Altere a classe SelecaoRepository para que na remoção de seleções os jogadores correspondentes também sejam removidos. As requisições feitas pelos usuários passarão por esse filtro antes de chegar ao controle do JSF.getResultList().entityManager.26 Exercícios 38. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void remove(Selecao selecao) { this. } this. o filtro redirecionará o usuário para a tela de login.flush(). for (Jogador jogador : jogadores) { this.selecao = :selecao"). Caso contrário. Adicione no pacote filtros a seguinte classe: www.entityManager.entityManager .25 Controle de Acesso Na maioria dos casos.setParameter("selecao".remove(jogador). as aplicações devem controlar o acesso dos usuários. A modificação deve ser feita no método remove(). Vamos implementar um mecanismo de autenticação na nossa aplicação utilizando filtro. query.Projeto 37.com.entityManager.createQuery("select j from Jogador as j where j. 13. Query query = this.

com/jsf/facelets" xmlns:h="http://java.getAttribute("autenticado") != null || req.entrar}"/> </h:form> </ui:define> </ui:composition> </html> 40. 141 K19 Treinamentos .senha}"/> <h:commandButton value="Entrar" action="#{loginBean.com/jsf/core"> <ui:composition template="/template.xhtml"). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <html xmlns="http://www.xhtml")) { chain.usuario}" /> <h:outputLabel value="Senha: " for="senha"/> <h:inputSecret id="senha" value="#{loginBean. ServletException { HttpServletRequest req = (HttpServletRequest) request.doFilter(request.xhtml"> <ui:define name="conteudo"> <h:form styleClass="formulario"> <h:outputLabel value="Usuário: " for="usuario"/> <h:inputText id="usuario" value="#{loginBean. HttpSession session = req.com/jsf/html" xmlns:f="http://java.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @WebFilter(servletNames = { "Faces Servlet" }) public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest request. response). if (session. Adicione uma classe no pacote managedbeans chamada LoginBean.getRequestURI().sun.sendRedirect("login.getSession().w3. } else { HttpServletResponse res = (HttpServletResponse) response.xhtml na pasta WebContent. Crie a tela de login adicionando um arquivo chamado login. Implemente o Managed Bean que autentica os usuários.org/1999/xhtml" xmlns:ui="http://java. ServletResponse response.endsWith("login. } } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } } 39.sun. res. FilterChain chain) throws IOException.sun.

session. session.com.xhtml"> <ui:define name="conteudo"> <h3 class="titulo" >Até Logo</h3> </ui:define> </ui:composition> </html> 42.setAttribute("autenticado".getSession(false).sun. } // GETTERS AND SETTERS } 41.org/1999/xhtml" xmlns:ui="http://java.equals(this. www.xhtml na pasta WebContent.removeAttribute("autenticado").getCurrentInstance().getCurrentInstance() . true). Adicione um arquivo chamado ate-logo.com/jsf/core"> <ui:composition template="/template. } } public String sair() { HttpSession session = (HttpSession) FacesContext.Projeto 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @ManagedBean public class LoginBean { private String usuario. Modifique o template das telas para acrescentar um botão de sair.sun.senha)) { HttpSession session = (HttpSession) FacesContext . return "/selecoes". Crie uma tela de despedida que será utilizada quando um usuário sair da aplicação.usuario) && "k19".w3.k19.com/jsf/facelets" xmlns:h="http://java.com/jsf/html" xmlns:f="http://java.sun. public String entrar() { if ("k19".getExternalContext().getExternalContext() .equals(this.br 142 . return "/ate-logo".getSession(false). private String senha. 1 2 3 4 5 6 7 8 9 10 11 <html xmlns="http://www. } else { return "/login".

Projeto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.png" /> <h:outputLink styleClass="botao" value="selecoes.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.xhtml">Jogadores</← h:outputLink> <h:form style="display: inline;"> <h:commandLink styleClass="botao" action="#{loginBean.sair}">Sair</← h:commandLink> </h:form> <hr/> </div> <ui:insert name="conteudo"> Espaço para o conteúdo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy; 2010 K19. Todos os direitos reservados. </div> </h:body> </html>

13.27

Ordem dos filtros

Em alguns casos a ordem de execução dos filtros afeta o funcionamento da aplicação. No caso da nossa aplicação, a ordem correta de execução dos filtros é primeiro o filtro de autenticação e depois o de controle transacional. Não podemos definir a ordem de execução de uma conjunto de filtros através de anotações. Podemos determinar essa sequência se os filtros forem registrados no arquivo de configurações do Web Container, web.xml. A ordem de execução do filtros é a ordem na qual eles aparecem no arquivo de configuração.

13.28

Exercícios

43. Remova a anotação @WebFilter das classes JPAFilter e LoginFilter que estão no pacote filtros.

44. Adicione o seguinte trecho de configuração no arquivo web.xml. 143 K19 Treinamentos

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

13.29

Controle de Erro

Quando uma exception ocorre durante o processamento de uma requisição, o filtro de controle transacional dispara um rollback para desfazer o que já havia sido alterado no banco de dados. Porém, o usuário não é informado sobre o problema. Podemos configurar uma página de erro padrão para ser utilizada toda vez que um erro ocorrer. O filtro de controle transacional deve lançar uma ServletException após disparar o rollback para informar o Web Container que houve uma falha no processamento da requisição. Depois, devemos configurar uma página de erro padrão no Web Container.

13.30

Exercícios

45. Modifique o filtro de controle transacional para que ele informe o Web Container através de uma exception que houve um problema no processamento de uma requisição. www.k19.com.br 144

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

46. Configure a página de erro no arquivo web.xml. Acrescente o seguinte trecho.
1 2 3 4 <error-page> <exception-type>java.lang.Exception</exception-type> <location>/erro.xhtml</location> </error-page>

47. Crie a página de erro adicionando um arquivo chamado erro.xhtml na pasta WebContent com o seguinte conteúdo.
1 2 3 4 5 6 7 8 9 10 11 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <ui:composition template="/template.xhtml"> <ui:define name="conteudo"> <h3 class="titulo" >Erro Interno</h3> </ui:define> </ui:composition> </html>

145

K19 Treinamentos

br 146 .com/jsf/html"> <h:head> <title>Copa do Mundo</title> <link rel="stylesheet" href="style."> <h:commandLink styleClass="botao" action="#{loginBean.png" /> <h:outputLink styleClass="botao" value="selecoes. Devemos utilizar a especificação JavaMail para que a nossa aplicação JSF tenha a capacidade de enviar mensagems por email. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.Projeto 48. podemos permitir que o usuário envie uma email para os administradores do sistema.31 Enviando email Quando um erro ocorre na nossa aplicação. www.xhtml">Selecoes</h:outputLink> <h:outputLink styleClass="botao" value="jogadores.w3.org/TR/xhtml1/DTD/xhtml1-transitional.sun.dtd"> <html xmlns="http://www.erro}">Erro</← h:commandLink> </h:form> <hr/> </div> <ui:insert name="conteudo"> Espaço para o conteúdo da tela </ui:insert> <div id="footer" style="text-align: center"> <hr /> &copy. Vamos criar um Managed Bean que sempre gera um problema para testar a página de erro. 1 2 3 4 5 6 @ManagedBean public class ErroBean { public void erro(){ throw new NullPointerException().com/jsf/facelets" xmlns:h="http://java.org/1999/xhtml" xmlns:ui="http://java. } } 49. 2010 K19. </div> </h:body> </html> 13.sun.w3. Todos os direitos reservados.css" type="text/css"/> </h:head> <h:body> <div id="header"> <img class="logo" src="k19-logo.xhtml">Jogadores</← h:outputLink> <h:form style="display: inline. Modifique o template para adicionar um botão que dispara o Managed Bean que sempre gera um erro.k19.sair}">Sair</← h:commandLink> <h:commandLink styleClass="botao" action="#{erroBean.com. Adicione a classe ErroBean no pacote managedbeans com o seguinte conteúdo.0 Transitional//EN" "http://www.

32 Exercícios 50.envia}" /> </h:panelGrid> </h:form> </ui:define> </ui:composition> </html> 51. Altere a tela de erro adicionando um formulário para o usuário escrever uma mensagem para os administradores da aplicação. Crie um Managed Bean que envie as mensagens por email utilizando a especificação JavaMail. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <html xmlns="http://www.xhtml"> <ui:define name="conteudo"> <h3 class="titulo">Erro Interno</h3> <p>Envie uma mensagem para os administradores do sistema.sun.w3.mensagem}" required="true" rows="10" cols="30"/> <h:message for="campo-mensagem" /> <h:commandButton value="Enviar" action="#{emailBean.sun. Observação.</p> <h:form styleClass="formulario"> <h:panelGrid columns="3"> <h:outputLabel value="Mensagem: " for="campo-mensagem" /> <h:inputTextarea id="campo-mensagem" value="#{emailBean. utilize usuários.sun. 147 K19 Treinamentos .com/jsf/html" xmlns:f="http://java. senhas e emails válidos do gmail para este exercício.com/jsf/facelets" xmlns:h="http://java.com/jsf/core"> <ui:composition template="/template.org/1999/xhtml" xmlns:ui="http://java.Projeto 13.

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

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->