Como crear componentes en NetbeansDescripción completa
Descripción completa
Descripción: s
Descripción completa
termodinamica
belajar dasar java netbeansFull description
Deskripsi lengkap
Full description
XDDescripción completa
Atajos para usar JavaDescripción completa
Descripción completa
Descripción: en este documento se encuentra una serie de programas utilizando las sentencias if, else if, en if simples y anidados con codigo, algoritmo, y prueba de datos.
Descripción completa
NetbeansDescripción completa
Acceso a MySQL Acceso a Bases de Datos. Antes de abrir NetBeans, primero abriremos la interfaz gráfica de MySQL, para crear la base de datos y la tabla en la que vamos a almacenar todos lo…Full description
Desenvolvendo Aplicações Web com NetBeans IDE 6 Conteúdo
TRABALHANDO COM TOMCAT 5.5 ........................................................ ............................................................................ .................................. .............. 9 Adicionando na IDE o Tomcat 5.5 ........................................................ ............................................................................. ....................................... .................. 9 Acessando o administrador na IDE........................................... ................................................................. ........................................... ......................... 10 Configurando Pool de Conexões no Tomcat 5.5 pelo Admin............................................ ............................................... ... 14 Utilizando JNDI no arquivo persistence.xml............................................ ................................................................... ............................. ...... 15 Listagem 1. Alteração do arquivo persistence.xml .................................................... ............................................................... ........... 15 Listagem 2. A classe JPAToplinkSessionCustomizationU JPAToplinkSessionCustomizationUtil til ............................................... ............................................... 16 APLICAÇÕES WEB COM ACESSO A DADOS SEM PADRÃO.......................................... ............................................. ... 17 Desenvolvendo via JDBC sem padrões ...................................................... ............................................................................ ................................ .......... 17 Criando o projeto ................................ ...................................................... ............................................. ............................................. ........................................ .................. 17 Conectando sua página JSP ao banco de dados .......................................... ................................................................. .......................... ... 20 Listagem 1. Alterações na página index.jsp............................................. ................................................................... .............................. ........ 20 Listagem 2. Alterações na página formInserindoDados.jsp ................................................ ................................................ 22 Listagem 3. Alterações na página inserindoDados.jsp inser indoDados.jsp ..................................... ......................................................... .................... 23 Entendendo os principais Statements .................................................................. .................................................................................... .................. 25 Explorando a interface PreparedStatement ................................... ......................................................... ....................................... ................. 25 A biblioteca de tags SQL do JSTL ............................................ .................................................................. ............................................. ....................... 25 Listagem 4. Alterações na página inserindoDados.jsp inser indoDados.jsp ..................................... ......................................................... .................... 27 STRUTS FRAMEWORK .......................................... ................................................................ ............................................. ............................................. .......................... 29 A origem do Struts Framework ............................................. .................................................................... .............................................. .............................. ....... 29 Seu primeiro projeto com Struts ....................................................... .............................................................................. ..................................... .............. 29 As camadas de Struts ................................. ....................................................... ............................................ ............................................. .................................. ........... 31 Listagem 1. Alterações na classe NomeForm .......................................... ................................................................. .............................. ....... 33 Listagem 2. Alterações na classe c lasse ControleAction ..................................................... ................................................................. ............ 37 Listagem 3. Alterações na classe c lasse MeuBeanModelo.................................... MeuBeanModelo........................................................... ........................... .... 40 Listagem 4. Alterações na classe Constante..................... Constante ............................................ ............................................. ............................... ......... 41 Listagem 5. Alterações na página welcomeStruts ........................................... ................................................................. ...................... 41 Listagem 6. Alterações na página sucesso.jsp............................................................. sucesso.jsp........................................................................ ........... 42 As tags do Struts............................................. ................................................................... ............................................. ............................................. ............................. ....... 43 Utilizando Struts para acessar banco de dados............................................. ..................................................................... ........................ 48 Listagem 7. O JavaBean Autor ........................ ............................................... ............................................. ............................................ .......................... .... 48 Listagem 8. A classe ConnectionFactory ......................................... ............................................................... ...................................... ................ 49 Listagem 9. A interface DAO ............................... .................................................... ........................................... ............................................ .......................... 50 Listagem 10. A classe c lasse implementada AutorDAOImp ............................................ .......................................................... .............. 50 Listagem 11. A classe AutoresActionForm ........................................... ................................................................. ................................. ........... 54 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
2
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 12. A classe AutoresAction ................................................... ......................................................................... .................................. ............ 55 Listagem 13. O resultado result ado final configurado em struts-config.xml ................................ ...................................... ...... 56 Listagem 14. A página welcomeStruts.jsp ............................................ ................................................................... ................................. .......... 57 Listagem 15. A página index.jsp ......................... ................................................ ............................................. ............................................ ........................ 58 Listagem 16. A classe EditarAutoresForm ............................................. ................................................................... ............................... ......... 58 Listagem 17. A classe EditarAutoresAction ....................................... .............................................................. ................................... ............ 59 Listagem 18. Alterações no arquivo struts-config.xml ............................................ ......................................................... ............. 63 Listagem 19. Alterações no arquivo struts-config.xml ............................................ ......................................................... ............. 64 Listagem 20. Alterações no arquivo struts-config.xml ............................................ ......................................................... ............. 65 Listagem 21. A página welcomeStruts.jsp ............................................ ................................................................... ................................. .......... 66 DESENVOLVENDO RELATÓRIOS COM NETBEANS IDE I DE ................................ .................................................. .................. 68 O JasperReports.................................................. ......................................................................... ............................................. ........................................... ............................ ....... 68 O iReport para o NetBeans .............................................. ..................................................................... .............................................. .................................... ............. 68 Desenvolvendo relatórios com NetBeans ........................................................... ............................................................................... .................... 68 Listagem 1 – Trecho do Servlet Relatorio contendo a chamada ao arquivo JasperReports ............................................ .................................................................. ............................................. ............................................. ............................................ ..................................... ............... 86 Listagem 2 – Alteração do arquivo index.jsp ...................................................... ........................................................................ .................. 88 Listagem 3 – Alteração da query usada no relatório .......................... ................................................. .................................. ........... 90 Listagem 4 – O Servlet Relatorio ........................................... .................................................................. .............................................. .......................... ... 91 Listagem 5 – Chamando o Servlet por mostrarAutoresCads.jsp ........................................ ........................................ 92 ESTUDO DE CASO COMPLETO COM VISUAL WEB JSF ..................................... ................................................... .............. 94 Adicionando novas características ao administrador............................................. ............................................................... .................. 94 As entidades e seus relacionamentos .................................. ........................................................ ............................................ .............................. ........ 94 Listagem 1. Script para criação das tabelas do projeto....................................................... projeto....................................................... 95 Adicionando novas páginas do administrador ................................... ......................................................... ................................... ............. 96 Listagem 2. O bean Editora ............................................................... ...................................................................................... ..................................... .............. 97 Listagem 3. O código do link Excluir do componente Table da página.............................. .............................. 98 Listagem 4. O código do link Atualizar do componente Table da página .......................... .......................... 98 Listagem 5. O código do botão Salvar do formulário da página ......................................... ......................................... 99 Listagem 6. O código do método Callback prerender() da página ...................................... ...................................... 99 A página de criar publicações ............................. ................................................... ........................................... ........................................... ........................ 100 Listagem 7. O código do botão btPublicar do formulário da página ................................ ................................ 102 Listagem 8. Alterações do código da página............................................ .................................................................. ............................ ...... 103 Listagem 9. Alteração em faces-config.xml para a página Publicar ................................. ................................. 107 A página de publicações ............................................ .................................................................. ............................................ ...................................... ................ 108 Vinculando o livro a seus autores ................................. ........................................................ ............................................. ................................. ........... 109 Listagem 10. Alteração na classe RequestBean1 ........................................... ................................................................. ...................... 109 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
3
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 11. Código do link Adicionar.......................................... ................................................................ ...................................... ................ 110 Listagem 12. Código do botão Adicionar ao Livro ................................................. ............................................................. ............ 112 A página de autores publicados ................................... ......................................................... ............................................. ................................... ............ 113 Listagem 13. Navegação da página LivroAutor para AutoresPublicados........................ ........................ 114 Alterando o menu .................................. ......................................................... ............................................. ............................................ .................................... .............. 115 Criando o relacionamento entre as páginas .................................................... ........................................................................ .................... 115 Listagem 13. Arquivo faces-config.xml .................................. ........................................................ ............................................. ......................... 115 ESTUDO DE CASO COMPLETO COM VISUAL WEB JSF, SPRING E HIBERNATE UTILIZANDO JPA ............................................ ................................................................... .............................................. ............................................. ............................. ....... 121 As características da aplicação ....................................................... ............................................................................. .......................................... .................... 121 O Projeto ........................................... ................................................................. ............................................. ............................................. ......................................... ...................121 As entidades e seus relacionamentos .................................. ........................................................ ............................................ ............................ ...... 121 As entidades POJO ........................................... .................................................................. ............................................. ............................................. ......................... 122 Listagem 1. O código da entidade Usuario ...................................... .............................................................. .................................... ............ 124 Listagem 2. O código da entidade Livro ....................................... .............................................................. ....................................... ................ 125 Listagem 3. O código da entidade Autor........................................... Autor.................................................................. ................................... ............ 125 Listagem 4. O código da entidade Editora........................................... .................................................................. ................................ ......... 126 Listagem 5. O código da entidade Publicacao ........................... .................................................. .......................................... ................... 126 Utilizando o DAO genérico para criar outros .................................... ............................................................ ................................. ......... 128 Listagem 6. A interface BaseDao alterada........................................... ................................................................ ................................ ........... 128 Listagem 7. A classe BaseDaoImp alterada alte rada ............................................ .................................................................. ............................. ....... 128 Listagem 8. A interface EditoraDao ........................................... .................................................................. .......................................... ................... 128 Listagem 9. A classe EditoraDaoImp ......................... ............................................... ............................................. .................................... ............. 128 Listagem 10. A interface LivroDao ...................................................... ............................................................................ ................................ .......... 129 Listagem 11. A classe LivroDaoImp............................................ ................................................................... ......................................... .................. 129 Listagem 12. A interface PublicacaoDao .......................................... ................................................................. ................................... ............ 129 Listagem 13. A classe PublicacaoDaoImp............................. PublicacaoDaoImp................................................... ............................................. ........................... 129 Listagem 14. A interface UsuarioDao ........................................................ .............................................................................. .......................... .... 129 Listagem 15. A classe UsuarioDaoImp............................................ .................................................................. ..................................... ............... 129 Listagem 16. A classe AutorDao ................................. ....................................................... ............................................ .................................... .............. 129 Listagem 17. A classe AutorDaoImp ............................................ .................................................................. ........................................ .................. 130 Configurando o Spring ..................................................... ........................................................................... ............................................ ............................... ......... 130 Listagem 18. Configuração do arquivo applicationContext.xml....................................... ...................................... 131 Listagem 19. Configurando o Spring Framework em e m web.xml......................................... ........................................ 132 Criando um teste unitário ......................................................... ............................................................................... ........................................... ....................... 132 Listagem 20. Teste unitário usando o Spring Framework .............................................. ................................................. ... 133 Controlando o acesso ............................................. ................................................................... ............................................ .......................................... .................... 134 134 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
4
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 21. Métodos adicionais da classe AutorController ............................................ 135 Listagem 22. O código da classe UsuarioController .......................................................... 135 Listagem 23. O código da classe EditoraController............................................................ 136 Listagem 24. O código da classe LivroController ............................................................... 136 Listagem 25. O código da classe PublicacaoController ...................................................... 137 Integrando o Visual Web JSF ao Spring ............................................................................. 138 Listagem 26. Alterações no arquivo faces-config.xml......................................................... 138 Acessando o Facade pelo Visual Web JSF........................................................................... 139 Listagem 27. Alterações na classe SessionBean1 ................................................................. 139 Os arquivos persistence.xml e log4j.properties ................................................................... 140 As páginas da aplicação ......................................................................................................... 140 Montando sua aplicação para utilizar Spring e Hibernate com JPA................................ 140 A criação do cadastro de livros ............................................................................................. 142 Listagem 28. Criação do método getLivroController() ...................................................... 143 Listagem 29. Alterações no método prerender() ................................................................. 143 Listagem 30. Alterações no método do link Excluir ........................................................... 144 Listagem 31. Alterações no método do link Editar ............................................................. 144 Listagem 32. Alterações no método do botão Salvar .......................................................... 144 As demais páginas administrativas de cadastro simples .................................................... 146 Acessando a área administrativa .......................................................................................... 147 Listagem 33. Criação do método getUsuarioController() .................................................. 148 Listagem 34. Alterações no método prerender() ................................................................. 148 Listagem 35. Alterações no método do botão Logar ........................................................... 149 A página de publicação .......................................................................................................... 150 Listagem 36. Alterações no método init() da classe SessionBean1 .................................... 150 Listagem 37. O código do botão btPublicar do formulário da página .............................. 153 Listagem 38. Alterações do código da página...................................................................... 153 Listagem 39. Alteração em faces-config.xml para a página Publicar ............................... 155 A página de publicações ........................................................................................................ 155 Listagem 40. O bean PublicacoesBean ................................................................................. 156 Listagem 41. Alterações na classe SessionBean1 ................................................................. 157 Listagem 42. Alterações do método prerender() ................................................................. 158 Listagem 43. Alterações em Publicacoes.java ..................................................................... 159 Adicionando autores a livros................................................................................................. 160 Listagem 44. Alteração na classe SessionBean1 .................................................................. 161 Listagem 45. Alterações no método prerender() ................................................................. 161 Listagem 46. Declaração do atributo autorOptions............................................................ 161 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
5
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 47. Chamando a classe AutorController ............................................................. 161 Listagem 48. Código do link Adicionar............................................................................... 163 Listagem 49. Código do botão Adicionar ao Livro ............................................................. 164 Listagem 50. Código de getLivroController() .................................................................... 164 A página de autores publicados ............................................................................................ 165 Listagem 51. Código de AutoresLivroBean ......................................................................... 166 Listagem 52. Trecho do código de SessionBean1 ................................................................ 167 Listagem 53. Alterações do método prerender() ................................................................. 168 Pesquisando livros na página principal ............................................................................... 169 Listagem 54. Alterações na classe SessionBean1 ................................................................. 169 Listagem 55. Código no botão Buscar de topo.jspf ............................................................. 169 Listagem 56 – Chamada de LivroController na classe Pesquisado .................................. 170 Listagem 57 – Código do método prerender() na classe Pesquisado................................. 170 Listagem 58 – Criação do array livros na classe Pesquisado ............................................ 170 Listagem 59 – Criação do array livros na classe Pesquisado ............................................ 171 A página de contato................................................................................................................ 171 A navegação de páginas ......................................................................................................... 172 Listagem 60 – Navegação das páginas em faces-config.xml ............................................... 174 Alterando os menus ................................................................................................................ 177 Listagem 61. Os métodos dos links do menu Principal ...................................................... 177 Listagem 62. Os métodos dos links do menu Administrativo ............................................ 177 Configurando um Pool para a conexão................................................................................ 178 Trabalhando com cache de objetos ...................................................................................... 179 Listagem 63. O arquivo persistence.xml .............................................................................. 179 Listagem 64. O arquivo persistence.xml completo.............................................................. 180 Listagem 65. O arquivo ehcache.xml completo ................................................................... 182 Listagem 66. A entidade Autor ............................................................................................. 183 Listagem 67. A entidade Livro .............................................................................................. 184 Listagem 68. A entidade Editora .......................................................................................... 184 Listagem 69. A entidade Publicacao..................................................................................... 184 Listagem 70. A entidade Usuario .......................................................................................... 185 O MYSQL....................................................................................................................................... 186 O que é um banco de dados relacional? ................................................................................... 186 Instalando o banco de dados ................................................................................................. 186 Instalando no Windows ......................................................................................................... 186 Instalando o MySQL no Linux ............................................................................................. 187 Acessando o banco de dados MySQL................................................................................... 187 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
6
Desenvolvendo Aplicações Web com NetBeans IDE 6 Comandos essenciais para o uso do MySQL ....................................................................... 188 Alterando tabelas existentes .................................................................................................. 189 Utilizando índices .......................................................................................................................190 Tipos de tabelas .......................................................................................................................... 191 Tipo de dados .............................................................................................................................. 193 Modificadores AUTO_INCREMENT, UNSIGNED e ZEROFILL ...................................... 194 Tipos de caractere ou de dados de string ................................................................................. 195 Tipos variados ............................................................................................................................ 195 Tipos de data e hora (DATE/TIME) ........................................................................................ 196 Modificadores adicionais de coluna ......................................................................................... 196 Sintaxe básica da SQL ............................................................................................................... 197 Funções que trabalham com a instrução SELECT................................................................. 198 Comando UPDATE ..................................................................................................................... 200 Comando DELETE ..................................................................................................................... 200 Trabalhando com Junções ........................................................................................................ 200 Criando uma junção com INNER JOIN ................................................................................... 200 Chaves variadas do MySQL ..................................................................................................... 200 O que é uma chave? .................................................................................................................... 200 Como as chaves funcionam ........................................................................................................ 200 Benefícios de usar uma chave .................................................................................................... 201 Suporte de chaves do MySQL ..................................................................................................... 201 Chaves primárias (Primary Key) ................................................................................................ 201 Chaves estrangeiras (Foreign Key) ............................................................................................ 202 Excluindo uma chave estrangeira .............................................................................................. 202 Administrando o MySQL .......................................................................................................... 202 Entendendo o sistema de privilégios do MySQL ........................................................................ 202 Configurando usuários ............................................................................................................... 202 Confirmando o novo usuário ...................................................................................................... 203 Revogando privilégios ................................................................................................................. 203 Obtendo informações com SHOW .............................................................................................203
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
7
Desenvolvendo Aplicações Web com NetBeans IDE 6
Sobre o conteúdo destes Capítulos Embora o livro aborde uma boa parte da técnica necessária para o desenvolvimento com aplicações Web envolvendo o NetBeans IDE, alguns iniciantes sentirão necessidade de um conteúdo mais aprofundado, com exemplos mais complexos e completos, finalizando assim seus estudos. Esta é a idéia destes capítulos extras, que juntos formam um novo livro, mas com seu conteúdo atrelado ao livro impresso. Isso significa, em prática, que parte do abordado aqui, possui suas explicações técnicas no livro impresso. Em outras partes, códigos são apresentados apenas com pequenos trechos, necessitando do livro para completá-los e conseqüentemente entendê-los. Com tudo isso, quem ganha é você, caro leitor, que possui em suas mãos um poderoso brinde, que está sendo dado para melhorar e ampliar seus exemplos, sem custo a mais por isso. Espero que goste deste brinde e que seja muito útil no seu desenvolvimento sobre aplicações escritas em Java para a Web.
Bons códigos,
Edson Gonçalves Autor do livro Desenvolvendo Aplicações Web com NetBeans IDE 6
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
8
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 1 Trabalhando com Tomcat 5.5 Este capítulo foi escrito para os usuários que utilizam o Tomcat na versão 5.5. Será detalhado desde como inserir o servidor até como utilizar o Administration Tool. Adicionando na IDE o Tomcat 5.5
Para adicionar o Tomcat 5.5 no NetBeans IDE, clique com o direito do mouse sobre o item Servers na janela Services. Selecione no menu de contexto o item Add Server. Na caixa de diálogo Add Server Instance selecione em Server o Tomcat 5.5. Se preferir alterar o nome contido no campo Name, basta digitar. Clique no botão Next para prosseguir.
Figura 1– Adição do Servlet Container Tomcat 5.5
Na segunda etapa, no campo Catalina Home, clique no botão Browse e selecione o local de instalação do Tomcat 5.5. Digite o nome de usuário no campo Username e a senha em Password. Confirme no botão Finish.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
9
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 2 – Configuração do local de instalação e informações da conta administradora
Atenção: Uma adição como esta não habilita automaticamente a opção do Monitor HTTP. Será necessário ir até as propriedades e marcar Enable HTTP Monitor .
Figura 3 – Tomcat 5.5 adicionado no NetBeans
Acessando o administrador na IDE Para acessar o administrador do Tomcat, a aplicação batizada de Admin, clique novamente com o direito do mouse sobre o servidor e selecione no menu de contexto o item View Admin Console . Uma janela do browser se abrirá e você terá uma tela similar a Figura 4:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
10
Desenvolvendo Aplicações Web com NetBeans IDE 6 Observação: O Administration Tool não vem instalado por padrão no Tomcat 5.5. Será necessário baixá-lo e instalá-lo para então utilizar. 1
Figura 4 – Tela inicial de login do Tomcat Web Server Administration Tool
O login e a senha desta aplicação estão em um arquivo chamado de tomcat-users.xml. Este arquivo está no diretório da sua instalação, em: conf . Ao abrir o arquivo, um simples XML, você encontrará a seguinte linha:
Caso desejar, pode alterar a senha, que está no atributo password. O usuário se encontra em username. Após alterar, você precisará informar a IDE o novo login e senha. Para isso, clique com o direito do mouse novamente sobre o Tomcat, na janela Services. Selecione no menu de contexto o item Properties. Na caixa de diálogo Servers você seleciona o Tomcat 5.5, caso não esteja selecionado em Servers e em Username você adiciona o novo usuário e a senha em Password. Perceba também que é neste local em que você pode alterar as portas do Tomcat. O padrão de uma instalação do Tomcat, fora da IDE é 8080. Após alterar basta clicar no botão Close para confirmar a caixa de diálogo.
1
Recomendo a leitura do livro Tomcat – Guia Rápido do Administrador – Ciência Moderna - 2006
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
11
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 5 – Caixa de diálogo Servers com o Tomcat 5.5 selecionado
Existem casos em que você precisará fazer o undeploy diretamente pelo administrador. Isso geralmente ocorre quando a IDE não consegue fazê-lo. Para fazer no Tomcat, na aplicação Admin, expanda o nó de Service e clique em Host (localhost).
Figura 6 – Selecionando Host Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
12
Desenvolvendo Aplicações Web com NetBeans IDE 6 No Frame direito, você verá uma caixa de seleção em Host Actions. Clique em Available Actions e selecione Delete Existing Contexts .
Figura 7 – Excluindo um contexto existente
O frame exibirá Delete This Context. Selecione o contexto que deseja excluir, em Delete, simplesmente checando o item e clique no botão Save .
Figura 8 – Selecionando o contexto que será removido
Para refletir as alterações feitas no Tomcat, através do NetBeans, volte a janela Services e com o direito do mouse sobre o Tomcat 5.5 selecione o item Refresh no menu de contexto. Você também pode clicar com o direito do mouse sobre Web Applications onde apenas um item, o Refresh, aparecerá.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
13
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 9 – Refletindo as alterações no NetBeans
Configurando Pool de Conexões no Tomcat 5.5 pelo Admin Na janela Services, com o Container Servlet Tomcat 5.5 em execução, clique com o direito do mouse e selecione o item View Admin Console . Entre com seu login e senha na área administrativa. Dentro do administrador, no frame esquerdo, expanda o nó Resources e clique em Data Sources . Em Data Source Actions , no menu drop down, selecione Create New Data Source .
Figura 10 – Criando um novo Data Source pelo Admin do Tomcat 5.5
Preencha os campos de Data Source como mostrado na Figura 11 a seguir seguir e salve as as alterações alterações clicando no botão Save.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
14
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 11 – Data Source configurado
Utilizando JNDI no arquivo persistence.xml Para trabalhar com JPA, aqui há os passos de como utilizar o JNDI em seu arquivo de persistência. No NetBeans abra o arquivo persistence.xml, no seu projeto que utiliza o Tomcat, e coloque em XML. Altere o XML do arquivo para o mostrado na Listagem 1 a seguir: Listagem 1. Alteração do arquivo persistence.xml ... > java:comp/env/jdbc/livraria br.com.integrator.Autorbr.com.integrator.Autor br.com.integrator.Livro br.com.integrator.Livro /> /> ...
Um típico caso de uma transação JTA, utilize um elemento chamado de no qual você especifica o JNDI do acesso ao banco de dados. Similarmente em uma transação do tipo resource-local , na unidade de persistência o elemento é usado.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
15
Desenvolvendo Aplicações Web com NetBeans IDE 6
java:comp/env/jdbc/livraria
Nos elemento você tem dois elementos , onde um contém uma chamada a uma classe que persistirá a sessão. Dentro do pacote br.com.integrator.util , crie uma classe, que se chamará de JPAToplinkSessionCustomizationUtil. Adicione o código da Listagem 2 a seguir nesta classe: Listagem 2. A classe JPAToplinkSessionCustomizationUtil
...
public class JPAToplinkSessionCustomizationUtil implements implements SessionCustomizer SessionCustomizer { public void customize(Session void customize(Session session) throws throws Exception{ Exception{ JNDIConnector connector = (JNDIConnector)session.getLogin( ).getConnector( ); connector.setLookupType(JNDIConnector.STRING_LOOKUP); }
}
Fixe as importações com Ctrl + Shift + I . Não se esqueça de adicionar o Resource References do seu JNDI no deployment descriptor.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
16
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 2 Aplicações Web com acesso a dados sem padrão Este capítulo foi escrito para desenvolvedores iniciantes que estão começando com aplicações Web em Java e desejam aprender o básico antes de iniciar o trabalho com padrões de desenvolvimento como MVC e DAO. Desenvolvendo via JDBC sem padrões
Para começar, uma breve revisão de como adicionar uma biblioteca JDBC, caso você não tenha a do banco de dados que vai utilizar. Para o exemplo, será utilizado o MySQL, por estar sendo abordado ao longo do livro.
Criando o projeto Crie um novo projeto no NetBeans e o chame de TrabComJDBCeMySQL . No seu projeto gerado, clique com o direito do mouse sobre o item Libraries. No menu de contexto, você possui as opções para escolher: 1. Add Library - Adiciona uma biblioteca configurada no NetBeans IDE. 2. Add JAR/Folder - Adicione um JAR ou Diretório em apenas um projeto da IDE. 3. Add Project – Adiciona um projeto e conseqüentemente suas dependências.
Figura 1 – Adicionando uma nova biblioteca
Selecione a opção Add Library no menu de contexto. Na caixa de diálogo Add Library clique no botão Manage Libraries.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
17
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 2 – Adicionando uma nova biblioteca
Na caixa de diálogo Library Manager clique no botão New Library. Digite MySQL em Library Name, na caixa de diálogo New Library. Selecione Class Libraries, em Library Type , caso não esteja selecionado e clique no botão OK para confirmar.
Figura 3 – Criando uma nova biblioteca no NetBeans
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
18
Desenvolvendo Aplicações Web com NetBeans IDE 6 Voltando a caixa de diálogo Library Manager, com a biblioteca MySQL criada, selecionada em Libraries, clique no botão Add JAR/Folder e selecione a biblioteca JDBC do MySQL e depois confirme a caixa de diálogo.
Figura 4 – Adição do arquivo JAR
Selecione em Add Library a biblioteca MySQL adicionada e clique no botão Add Library.
Figura 5 – Adicionando a biblioteca ao projeto
Voltando em seu projeto, você deverá ver a biblioteca MySQL adicionada em seu projeto.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
19
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 6 – Biblioteca JDBC do MySQL adicionada ao projeto
Conectando sua página JSP ao banco de dados Para que você entenda como funciona a conexão e a leitura de dados de um banco de dados, altere a página index.jsp adicionando os códigos da Listagem 1 a seguir, para trabalhar com o MySQL. Listagem 1. Alterações na página index.jsp <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1" import="java.sql.*" %> Conectando sua aplicação JSP ao MySQL via JDBC
st = conn.createStatement( ); rs = st.executeQuery("select id, titulo from livros"); %>
while(rs.next( )) {
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
20
Desenvolvendo Aplicações Web com NetBeans IDE 6
<%= rs.getString("id") %>
<%= rs.getString("titulo") %>
<% } //end while } catch (Exception ex) { ex.printStackTrace( ); } finally { if (rs != null) rs.close( ); if (st != null) st.close( ); if (conn != null) conn.close( ); } %>
Dentro do bloco try...catch você define o trabalho com o banco de dados para se conectar e executar a instrução SQL. Ao importar o pacote java.sql.*, através da diretiva page, você tem acesso às classes e interfaces para manipular os bancos de dados relacionais em Java. O driver de banco de dados deve ser empregado antes do programa se conectar ao banco de dados. A linha anterior utiliza o método static forName da classe Class (pacote java.lang) para carregar a definição de classe para o driver de banco de dados. Se a classe não for localizada, ele dispara uma exceção: java.lang.ClassNotFoundException . Um objeto Connection gerencia a conexão entre o programa Java e o banco de dados. Ele também fornece suporte ao programa para executar instruções SQL. Através do método static getConnection, a classe DriverManager tenta uma conexão com o banco de dados especificado pela string: jdbc:mysql://localhost/livraria. Os argumentos seguintes são o nome de usuário e a senha, demonstrados pela String edson e integrator respectivamente. Caso a classe DriverManager não conseguir se conectar ao banco de dados, o método getConnection dispara uma exceção: A responsabilidade principal da interface Statement é executar sentenças SQL no banco de dados. Com o método público createStatement você cria um objeto Statement para enviar declarações SQL ao banco de dados. Se houver um erro, dispara também a exceção java.sql.SQLException. Com o método executeQuery, você tem o retorno de um objeto que implementa ResultSet e que contém os resultados da consulta. Através de um loop while você varre os resultados encontrados, onde o método next( ), de ResultSet, retorna um valor booleano true, quando o resultado das linhas pesquisadas na query forem exauridas. O método getString( ), de ResultSet, traz o valor da coluna designada na fila atual deste ResultSet como uma String na linguagem Java. Depois de consumidos, os recursos devem ser retornados ao servidor, utilizando o método close( ). Nesse caso a cláusula usada é finally, que liberará os recursos, caso os resultados sejam bem sucedidos ou não.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
21
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 7 – Exibição dos livros cadastrados Inserindo dados
O exemplo que será feito irá ilustrar a inserção de dados no banco de dados. Você terá em uma página JSP, um formulário HTML comum, sem código dinâmico, contendo os campos necessários para inserir. Esse formulário irá enviar os dados, via método POST, para outra página JSP, que recuperará essas informações e as enviará para o banco de dados MySQL. Crie uma nova página JSP e a chame de formInserindoDados.jsp. Altere-a como mostra a Listagem 2 a seguir. Listagem 2. Alterações na página formInserindoDados.jsp <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Inserindo Dados
Como essa é uma página simples com um formulário básico contendo apenas conteúdo HTML, não haverá comentários sobre o mesmo.
Figura 8 – Formulário de cadastro
A página JSP que irá receber esses valores será chamada de inserindoDados.jsp e é mostrada a na Listagem 3 a seguir: Listagem 3. Alterações na página inserindoDados.jsp <%@ page language="java" contentType="text/html;" pageEncoding="ISO-8859-1" import="java.sql.*" %> <% String titulo = request.getParameter("titulo"); String edicao = request.getParameter("edicao"); String publicacao = request.getParameter("publicacao"); String descricao = request.getParameter("descricao"); Connection conn = null; PreparedStatement pst = null; try { Class.forName("com.mysql.jdbc.Driver").newInstance( ); conn = DriverManager.getConnection("jdbc:mysql://localhost/livraria", "edson","integrator"); String SQL = "INSERT INTO livros (titulo, edicao, " + "publicacao, descricao) " + "values (?, ?, ?, ?)"; pst = conn.prepareStatement(SQL); pst.setString(1, titulo); pst.setInt(2, Integer.parseInt(edicao)); pst.setString(3, publicacao); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
23
Desenvolvendo Aplicações Web com NetBeans IDE 6 pst.setString(4, descricao); pst.executeUpdate( ); pst.clearParameters( ); }
catch (Exception ex) { ex.printStackTrace( );
}
finally { if (pst != null) pst.close( ); if (conn != null) conn.close( );
} %> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Inserindo Dados
O Livro <%=titulo %> foi inserido com sucesso!
Figura 9 – Cadastro inserido
A interface PreparedStatement tem um papel semelhante à interface Statement , o que nos permite executar sentenças SQL sobre uma conexão estabelecida com um banco de dados. Porém, neste caso, você utiliza sentenças mais especializadas, como a de inserir dados, onde você pode receber vários parâmetros como entrada. Um parâmetro de entrada é aquele cujo valor não se especifica quando a sentença é criada. No seu lugar a sentença recebe um sinal de interrogação ( ?) para cada parâmetro de entrada. Antes de executar a sentença, você deve especificar um valor para cada parâmetro, através dos métodos set apropriados. Para criar um objeto PreparedStatement você deve lançar um método prepareStatement(String s) da interface Connection sobre o objeto que representa a conexão estabelecida com o banco de dados. Através do método setString(int i, String s) , você prepara os dados que estão vindo dos campos do seu aplicativo para inserir no banco de dados. Como você mesmo já concluiu, o tipo string foi utilizado graças ao tipo existente no banco de dados. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
24
Desenvolvendo Aplicações Web com NetBeans IDE 6 O método setInt(int i, int i) faz o mesmo que o anterior, mas exige um valor inteiro. Com o método executeUpdate( ) você executa a sentença SQL para o tipo, que no caso é de inserção (INSERT). Esse método também serve para os atualizações (UPDATE) e exclusões (DELETE). Após utilizar os métodos setter, você pode limpá-los usando o método clearParameters( ) .
Entendendo os principais Statements Como você viu, Statements são essenciais para se comunicar com uma base de dados que usa a linguagem SQL. Há três principais tipos de Statements. O primeiro é a interface Statement. Quando são criados objetos pela implementação da interface Statements , estes são geralmente usados para executar declarações SQL genéricas que não levam qualquer parâmetro. O segundo tipo é o PreparedStatement que herda da interface Statement. Objetos PreparedStatement são úteis quando você precisar criar e compilar declarações SQL antes do tempo. Objetos PreparedStatement também aceitam parâmetros IN. O tipo final de statement é o CallableStatement. O CallableStatement herda de PreparedStatement e aceita parâmetros IN e OUT. Seu propósito principal é executar procedimentos armazenados de banco de dados.
Explorando a interface PreparedStatement Se você precisar executar declarações SQL muitas vezes, o PreparedStatement é a escolha perfeita para essa tarefa, isso porque aumenta a eficiência e desempenho do programa. O PreparedStatement é a escolha lógica do nome para a interface porque contém uma declaração SQL que previamente foi compilada e enviada ao DBMS de sua escolha, por isso o termo prepared . O PreparedStatement dá o desenvolvedor que a habilidade de embutir parâmetros na declaração SQL contidos no objeto PreparedStatement. Estes parâmetros IN (de entrada) são denotados na declaração SQL pelo símbolo de interrogação (?). A Tabela 1 mostra os métodos setters que indicam os tipos para PreparedStatement: Tabela 1 – Métodos setters para PreparedStatement
Método void setBoolean(int paramIndex, boolean b) setDate(int paramIndex, Date d) setDouble(int paramIndex, double d) setFloat(int paramIndex, float f) setInt(int paramIndex, int i) setLong(int paramIndex, long l) setString(int paramIndex, String s) clearParameters( )
Descrição Parâmetro de entrada com valor booleano. Parâmetro de data de entrada. Deve ser um valor java.sql.Date. Parâmetro de entrada com valor double. Parâmetro de entrada com valor float. Parâmetro de entrada com valor int. Parâmetro de entrada com valor long. Parâmetro de entrada com valor String. Limpa os parâmetros enviados pelos métodos setters.
A biblioteca de tags SQL do JSTL Embora seja desencorajado o uso de tags SQL da biblioteca JSTL em aplicações de páginas JSP, você apenas conhecerá um exemplo de seu uso. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
25
Desenvolvendo Aplicações Web com NetBeans IDE 6 Crie um novo projeto e adicione a biblioteca JSTL junto a biblioteca MySQL. A action
As ações fornecidas pela tag da biblioteca SQL operam em uma fonte de dados definida pela classe java.sql.DataSource. A action configura uma fonte de dados e transmite essa informação através do atributo var, em uma fonte de dados criada no escopo da página ou em dataSource para uma fonte de dados física. A fonte de dados configurada é usada pelas actions restantes da biblioteca SQL que pode executar as instruções já conhecidas. Você pode configurar o data source da seguinte forma: Tabela 2 – Atributos e descrição da action
Atributo
Descrição
driver
O nome da classe JDBC que será usada.
scope
A variável de escopo definida pelo atributo var. Por padrão esse atributo é page.
url
O URL do data source.
user
O usuário para acessar o banco de dados configurado no atributo url .
password A senha para acessar o banco de dados configurado no atributo url . var
A variável de escopo criada para acessar o data source em outras actions.
O data source também pode ser definido como:
Como você pode ver, é possível fornecer um caminho relativo a um recurso Java Naming and Directory Interface (JNDI) pelo atributo opcional dataSource. Se você tiver um nome JNDI para o dataSource, então o atributo dataSource acessará pela página JSP a fonte de dados JNDI. Neste caso, você não precisa fornecer quaisquer um dos demais atributos, porque eles já são fornecidos como parte do recurso acessado pelo JNDI. A action
A action fornece a funcionalidade de executar queries do tipo SELECT: SELECT * FROM livros Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
26
Desenvolvendo Aplicações Web com NetBeans IDE 6
O exemplo da Listagem 4 demonstra o uso da conexão e da execução de uma query com as tags SQL do JSTL: Listagem 4. Alterações na página inserindoDados.jsp <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%> Usando instruções SQL com JSTL SELECT * FROM livros
ID
Título
Os cabeçalhos são definidos na diretiva taglib, como já vista anteriormente. A URI do primeiro cabeçalho chama as tags CORE e o segundo cabeçalho são as tags de SQL. O prefixo usado é a letra "sql", que é um padrão definido pela Sun. <%@taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
O data source é definido nesse caso com a conexão feita diretamente na página. Não se esqueça de que é necessário colocar o .jar da ponte JDBC do MySQL no diretório lib de WEB-INF.
driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/livraria" user="edson" password="integrator" />
A query é criada, nesse caso selecionando todos os registros encontrados na tabela livros. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
27
Desenvolvendo Aplicações Web com NetBeans IDE 6 SELECT * FROM livros
Com a action você tem uma varredura dos resultados encontrados dentro da tabela livros, resultantes da SELECT. Dentro do atributo items você determina a variável livros usando a EL e separando por um "." ponto seguido da palavra rows.
Os resultados são exibidos utilizando-se a EL contendo a variável determinada no atributo var existente na action , separado por ponto “.” e o nome da coluna a ser exibida.
O resultado é similar ao exibido no exemplo dado com a página JSP.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
28
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 3 Struts Framework Este capítulo extra o instruirá no desenvolvimento com Struts Framework utilizando o NetBeans IDE 6. O Struts se encontra atualmente na versão 2, que até o momento em que este livro é escrito, não há um suporte direto pela IDE. A versão que suportada pelo NetBeans, do Struts, é 1.2.9, a que será tratada neste capítulo. A origem do Struts Framework
Jakarta Struts é um framework open source, escrito em Java, de desenvolvimento Web, mantido pela Apache Software Foundation (ASF). O framework Struts foi criado por Craig R. McClanaham e doado para a ASF no ano 2000. Como implementação do paradigma MVC (Model-View-Controller), utilizando um padrão similar ao Model 2, esse framework é um dos mais populares entre os desenvolvedores.
Seu primeiro projeto com Struts Seguindo um padrão tradicional da IDE, o suporte a Struts é pouco visual, ou seja, existem poucos assistentes que o auxiliarão no trabalho com este Framework. Partindo deste princípio, o primeiro exemplo será pequeno para que você compreenda as principais características do desenvolvimento de Struts com o NetBeans IDE. Comece criando uma aplicação Web comum. Digite o nome do seu projeto, que no caso do livro será PrimProjStruts e selecione como Server o Tomcat. Clique no botão Next.
Figura 1 – Criando um projeto com Struts
Na última etapa do assistente, não utilizada até o momento no livro, no desenvolvimento de aplicações web, você encontra os dois frameworks padrão existentes no NetBeans IDE. Selecione o Framework Struts, marcando a opção Struts 1.2.9. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
29
Desenvolvendo Aplicações Web com NetBeans IDE 6 Observe que o campo Action Servlet Name já contém uma configuração que não pode ser alterada. Em Action URL Pattern você percebe a extensão criada, que no caso seguiremos o padrão *.do. Application Resource para Altere o pacote já preenchido no campo br.com.integrator.struts.ApplicationResource (ou o nome do pacote que desejar .struts.ApplicationResource ) e clique no botão Finish.
Figura 2 – Seleção e configuração em web.xml do framework Struts na terceira etapa
Ao concluir o projeto, você perceberá que o NetBeans IDE criou em Web Pages duas páginas: index.jsp (o padrão até o momento) e welcomeStruts.jsp. Ao expandir o nó de Libraries, você notará que existem as bibliotecas necessárias para o desenvolvimento de Struts em suas páginas.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
30
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 3 – Bibliotecas do Struts sendo exibida em Libraries
Para uma aplicação que utilize o framework Struts, o NetBeans IDE adiciona oito arquivos do tipo JAR:
Em um ambiente de produção, estas bibliotecas devem estar disponíveis em sua aplicação no diretório lib, encontrado em WEB-INF.
As camadas de Struts Uma vez que o Struts trabalha dentro do paradigma MVC, você vai analisar cada camada em um pequeno exemplo para entendê-lo melhor. Esta aplicação será uma classe que receberá um nome vindo de um formulário. A camada Modelo
Crie um novo arquivo no NetBeans IDE, selecione na caixa de diálogo em Categories o item Struts e em File Types o item Struts ActionForm Bean. Clique no botão Next para prosseguir.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
31
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 4 – Seleção do tipo de arquivo Struts ActionForm Bean
Na segunda e última etapa, coloque NomeForm em Class Name e em Package escreva o nome do seu pacote (seguindo o livro: br.com.integrator). Clique no botão Finish para concluir.
Figura 5 – Nome da classe ActionForm e do pacote Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
32
Desenvolvendo Aplicações Web com NetBeans IDE 6 A classe gerada pelo NetBeans IDE contém uma pré-configuração que o ajudará a desenvolver o exemplo. Nesta classe, altere o atributo name criado, utilizando refactor. Clique com o direito do mouse sobre este atributo e selecione no menu de contexto o item Refactor e clique em Rename. Na caixa de diálogo Rename Field digite nome em New Name. Desmarque a opção Preview All Changes (caso esteja marcada) e clique no botão Next para concluir.
Figura 6 – Refatorando o atributo name
Apague os métodos acessores do anterior e refaça novamente (get e set do atributo nome). Altere o método validate(), como mostrado a seguir, em destaque, na Listagem 1 do código da classe NomeForm : Listagem 1. Alterações na classe NomeForm package br.com.integrator; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; public class NomeForm extends org.apache.struts.action.ActionForm { private String nome; public String getNome() { return nome; } public void setNome(String string) { nome = string; } public NomeForm () { super(); } //método que retorna um erro de validação caso nome não seja preenchido no formulário
}
public ActionErrors validate (ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); if (getNome () == null || getNome ().length() < 1) { errors.add("nome", new ActionMessage("errors.required")); } return errors; }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
33
Desenvolvendo Aplicações Web com NetBeans IDE 6 A classe NomeForm estende org.apache.struts.action.ActionForm, no qual trata eventos de formulário. Para cada campo em um formulário HTML, há uma variável com métodos getters e setters no bean Form para capturá-lo. O controller Struts popula o formulário HTML chamando os métodos getters no bean Form. Quando o usuário submete o formulário, o controller Struts injeta informações no bean Form com dados vindos deste formulário HTML, chamando métodos setters na instância do bean Form. Com o método validate( ) você retorna um objeto ActionErrors . A classe ActionErrors encapsula um ou mais erros que são encontrados pela aplicação. Os problemas encontrados são representados pela instância de org.apache.struts.action.ActionError . Para mostrar a mensagem ao usuário, uma classe é chamada para isso. A classe org.apache.struts.action.ActionMessage opera da mesma maneira que a classe ActionError . Na realidade, a classe ActionMessage foi acrescida como superclasse à ActionError . As mensagens enviadas ao usuário
Na janela Projects expandas os nós de Source Packages e do pacote br.com.integrator.struts. No arquivo ApplicationResource.properties clique com o direito do mouse e selecione o item Open no menu de contexto. Remova os key-values existentes mantendo apenas os mostrados na Figura 7 a seguir:
Figura 7 – Alterações no arquivo ApplicationResource.properties
Em Value da Key errors.required altere para “O Campo Nome é obrigatório ”. Salve e feche o arquivo. Estes textos alterados, encontrados no arquivo ApplicationResource.properties , são usados pela tag Struts , na página que ainda será desenvolvida. São textos que podem ser personalizados e, portanto, poderá conter as informações que desejar. Você também pode adicionar tags HTML se preferir dar um formato melhor nos textos de saída gerados pelas páginas Struts, como feito em errors.header , errors.prefix , errors.suffix e errors.footer .
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
34
Desenvolvendo Aplicações Web com NetBeans IDE 6 Criando a ação em Struts
A ação em Struts será a responsável pela recuperação do nome digitado pelo usuário e a interação com a camada Modelo. Sua responsabilidade é dar navegação e Controle para a camada Apresentação. Crie um novo arquivo onde, na caixa de diálogo, em Struts, selecione Struts Action em File Types e prossiga.
Figura 8 – Criando um novo arquivo do tipo Struts Action
Na segunda etapa, digite ControleAction no campo Class Name. O pacote será br.com.integrator (ou o que está usando). Em Action Path digite /NomeForm e clique no botão Next.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
35
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 9 – Criando a classe ControleAction
Na última etapa defina no campo Input Resource, clicando no botão Browse, a seleção da página welcomeStruts.jsp. Em Scope selecione o botão de rádio Request. Termine o assistente clicando no botão Finish.
Figura 10 – Configuração para o bean ActionForm
Na classe ControleAction gerada, e deixe seu código similar ao mostrado na Listagem 2 a seguir.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
36
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 2. Alterações na classe ControleAction package br.com.integrator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; public class ControleAction extends org.apache.struts.action.Action { /* forward name="success" path="" */ private final static String SUCCESS =
"success";
/** * This is the action called from the Struts framework. * @param mapping The ActionMapping used to select this instance. * @param form The optional ActionForm bean for this request. * @param request The HTTP Request we are processing. * @param response The HTTP Response we are processing. * @throws java.lang.Exception * @return */
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String nome = (String) PropertyUtils.getSimpleProperty(form, "nome"); MeuBeanModelo mb = new MeuBeanModelo(); mb.setNome(nome); request.setAttribute(Constante.NOME_KEY , mb); return mapping.findForward(SUCCESS);
}
}
Fixe as importações. Existem dois pontos nesta classe que não poderão ser fixados: uma é o MeuBeanModelo, um Bean que ainda não foi feito e o outro é a constante Constante.NOME_KEY , que está na mesma situação. Não se preocupe que você os fará logo a seguir. Uma classe org.apache.struts.action.Action no framework Struts é uma extensão do componente controller. A classe Action pega o pedido do cliente para o modelo de negócios. Esta mesma classe também pode executar outras funções, como autorização, login e validação de sessão antes de invocar a operação de negócios. A Action Struts contém diversos métodos, mas o mais importante é o execute(). Esse método contém a seguinte assinatura: public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception
O método execute() é chamado pelo controlador quando um pedido é recebido de um cliente. O controlador cria uma instância da classe Action se ainda não existir. O framework Struts cria somente uma instância de cada classe Action em sua aplicação. Como pode haver muitos usuários, você tem que assegurar que todas suas classes Action operem corretamente em um ambiente de multithreaded , da mesma maneira que faria ao desenvolver um Servlet. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
37
Desenvolvendo Aplicações Web com NetBeans IDE 6 O mapeamento Action é parte da informação da configuração do Struts, encontrado em um arquivo XML especial. Esta informação configurada é carregada na memória, durante a inicialização, e disponibilizada para o framework em tempo de execução. Este elemento é representado na memória por uma instância da classe org.apache.struts.action.ActionMapping . O objeto ActionMapping contém o atributo path, que é encontrado no arquivo XML da configuração do framework, em contraste a uma porção de URI de pedido entrante. Observe a seguir o trecho listado do arquivo de configuração struts-config.xml da sua aplicação:
Para que seja determinada para onde serão enviados os dados, você precisa utilizar o método findForward(). Na assinatura do método execute() da classe Action , você deve ter notado que o tipo de retorno para o método é uma classe org.apache.struts.action.ActionForward . A classe ActionForward representa um destino para o qual o controlador pode retornar uma vez que a Action foi completa. A action forward é especificada no arquivo de configuração XML do framework Struts ( strutsconfig.xml ), similar a action mapping. Embora o NetBeans IDE já tenha configurado boa parte das informações contidas no arquivo strutsconfig.xml , você precisará mapear para onde será enviado os dados preenchidos no formulário caso seja bem sucedido. Com o direito do mouse sobre o trecho mostrado anteriormente, em detalhes na Figura 11, entre os elementos , de struts-config.xml , selecione Struts e clique no item Add Forward.
Figura 11 – Adicionando o elemento ao arquivo struts-config.xml
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
38
Desenvolvendo Aplicações Web com NetBeans IDE 6 Na caixa de diálogo Add Forward digite, no campo Forward Name, a palavra success, que como você deve lembrar, é retornado pelo método findForward() da classe ControleAction . No campo Resource File, será colocada a página que receberá os dados enviados pela Action , no qual será chamada de sucesso.jsp . Esta página ainda não foi criada, portanto não será possível selecioná-la (apenas digite seu nome neste campo). A Figura 12 a seguir demonstra o resultado final de sua caixa de diálogo.
Figura 12 – Configuração do elemento através do diálogo Add Forward
Ao clicar no botão Add para confirmar, perceba que o elemento é adicionado ao arquivo struts-config.xml . Os atributos name e path foram adicionados com as informações transmitidas pela caixa de diálogo.
Figura 13 – Situação final dos elementos encontrados em
Para transmitir o nome digitado para a outra página, o método getSimpleProperty() da classe PropertyUtils recebe do formulário o conteúdo do campo nome, como você o adicionou na classe ControleAction : String nome = (String) PropertyUtils.getSimpleProperty (form, "nome");
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
39
Desenvolvendo Aplicações Web com NetBeans IDE 6 Para que se possa recuperar a informação enviada pelo formulário, um bean será criado para persistir a informação passada para outra página. O bean será chamado de MeuBeanModelo e conterá apenas a possibilidade de captar e transmitir o nome digitado no formulário que será criado na página JSP utilizando Struts. Crie uma classe chamada de MeuBeanModelo e a coloque dentro do pacote br.com.integrator (ou o principal que estiver utilizando em seu projeto).
Figura 14 – Criação do bean MeuBeanModelo
O bean que criado é apenas para dar o acesso ao atributo nome, no qual será enviado pela Action e recuperada pela página sucesso.jsp , exibindo assim os dados encontrados. Altere a classe MeuBeanModelo como mostrado na Listagem 3 a seguir: Listagem 3. Alterações na classe MeuBeanModelo package br.com.integrator; public class MeuBeanModelo { private String nome; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public MeuBeanModelo () { } }
Passando dados para a camada de apresentação
Como já dito, a classe ControleAction passa o valor recebido pelo campo nome, do formulário, para a próxima página, que ainda será criada, através do método setAttribute().
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
40
Desenvolvendo Aplicações Web com NetBeans IDE 6 , mb); request.setAttribute (Constante.NOME_KEY
Quando se passa um objeto de ActionClass para o componente encontrado na View (uma página JSP) usando request.setAttribute(), você precisa fornecer um nome, ou identificador String que o arquivo JSP possa usar para recuperar o objeto. Para isso, crie uma classe Java, chamada de Constante, coloque-a no pacote principal ( br.com.integrator ) e a transforme em uma constante como mostrado na Listagem 4 a seguir: Listagem 4. Alterações na classe Constante package br.com.integrator; public final class Constante { public static final String NOME_KEY = "integrator"; }
O formulário que enviará o nome
Como o NetBeans IDE tem o costume de iniciar um projeto com arquivos já pré-configurados, entre no arquivo welcomeStruts.jsp e altere o conteúdo como mostrado na Listagem 5 a seguir: Listagem 5. Alterações na página welcomeStruts <%@ page contentType="text/html"%> <%@ page pageEncoding="UTF-8"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> Minha primeira página usando Struts Nome:
Assim como ocorre com outras bibliotecas de tags, o Struts é configurado em sua página através da diretiva taglib , onde existem as bibliotecas que manipulam o HTML e outras. No caso, apenas a biblioteca de HTML será necessária. <%@taglib uri="http://jakarta.apache.org/struts/tags-html"
prefix="html" %>
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
41
Desenvolvendo Aplicações Web com NetBeans IDE 6 Dentre as tags Struts adicionadas na página, uma em especial, a tag , cria um formulário para envio de dados pelo framework. No atributo action você configura para onde o formulário será enviado, que no caso será NomeForm.do . Lembre-se de que o elemento , em struts-config.xml , no sub-elemento , foi configurado esse caminho para o envio de dados (veja Figura 13). A tag Struts é a responsável pela geração da caixa de texto que receberá o nome a ser digitado. Através do atributo property você determina o nome da caixa de texto. Com a tag Struts você cria o botão de envio e seu tipo é determinado pelo atributo property. O atributo value indica o rótulo do botão, como ocorre no HTML comum. Por fim, a tag Struts que resulta na mensagem de erro trazida pela classe NomeForm .
A página que resulta no sucesso do envio
Para finalizar, crie uma nova página JSP chamada de sucesso. Altere-a como mostra a Listagem 6 a seguir: Listagem 6. Alterações na página sucesso.jsp <%@ page contentType="text/html"%> <%@ page pageEncoding="UTF-8"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%> Seja bem vindo
Na página que receberá o resultado enviado pelo formulário, você determina se existe uma informação enviada através da tag , que utiliza seu atributo name para verificar se há a chave integrator. Caso não se lembre, a palavra integrator é a chave transmitida pela constante. public static final String NOME_KEY = "integrator";
Utilizando request.setAtt ribu te( Constante.NOME_KEY, mb) da classe ControleAction . Caso exista, a tag recupera o valor enviado e o imprime na tela. O resultado de todos esses passos é um pequeno formulário contendo um campo e um botão. Caso não seja digitado nada Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
42
Desenvolvendo Aplicações Web com NetBeans IDE 6 e enviado, o erro aparece logo abaixo do botão, devido ao posicionamento da tag Struts . Caso contrário, seu nome será enviado com sucesso e exibido na página sucesso.jsp .
Figura 15 – Resultado da página sem o campo preenchido
As tags do Struts As tags do Struts são divididas em cinco bibliotecas: html: permite a criação e manipulação de tags HTML com o Struts, principalmente formulários; logic: permite a criação de estruturas de condição e repetição, além da administração do fluxo da aplicação; bean: permite a criação e manipulação de JavaBeans dentro da página; nested: permite a definição de modelos de objetos aninhados e a capacidade de representálos e administrá-los; template: permite a criação de modelos dinâmicos de páginas JSP que compartilham de um formato comum. •
•
•
•
•
Destas cinco bibliotecas, aqui você aprenderá mais detalhadamente as três primeiras. As tags HTML do Struts
A biblioteca de tags HTML do Struts contém tags para renderizar o HTML, como o conhecemos. Algumas tags foram apresentadas nas páginas mostradas com exemplo anterior, mas com pouca informação técnica. Agora, para uma melhor compreensão das tags Struts, você terá uma descrição mais detalhada. Estas tags são personalizadas pela biblioteca e facilitam a comunicação com as configurações geradas pelas classes desenvolvidas para esse fim. Essas tags podem ser chamadas através da diretiva taglib existente em uma página JSP: <%@taglib uri="http://jakarta.apache.org/struts/tags-html"
prefix="html"%>
Como pode notar, a biblioteca HTML do Struts é chamada pela URI:
http://jakarta.apache.org/struts/tags-html E que contém o prefixo padrão html. A Tabela 1 a seguir demonstra as tags HTML do Struts framework: Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
43
Desenvolvendo Aplicações Web com NetBeans IDE 6
Tabela 1 - Tags HTML do Struts
Nome da Tag base button cancel checkbox errors file form frame hidden html image img javascript link messages multibox option options optionsCollection password radio reset rewrite select submit text textarea
Descrição Cria um elemento HTML base Cria um botão com a tag input Cria um botão cancel Cria uma caixa de checagem (input checkbox) Renderiza mensagens de erros enviados Cria um campo HTML file Define um elemento (tag) HTML form Cria um elemento HTML frame Cria um campo HTML hidden Cria um elemento HTML html Renderiza uma tag input do tipo "image" Cria uma tag HTML img Renderiza uma validação JavaScript baseada na validação carregada pelo ValidatorPlugIn Cria uma tag HTML anchor ou hyperlink Condicionalmente mostra as mensagens transmitidas pela classe Cria múltiplos campos caixa de checagem (input checkbox) Cria a tag select option Cria uma coleção de tags select options Cria uma coleção de tags select options Cria um campo input password Cria um botão de radio (input radio) Cria um botão reset Renderiza uma URI Renderiza uma tag select Renderiza um botão submit Cria uma tag input field do tipo "text" Cria uma tag textarea
A tag form
A tag Struts form é uma das mais importantes tags encontradas na biblioteca de tags HTML. É com esta tag que é renderizado a tag padrão form do HTML e, em conjunto, criado um direcionamento com a ActionForm configurada para a aplicação. Como a tag , o Struts controla aspectos importantes de uma página. A Tabela 2, a seguir, contém os elementos nela existentes:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
44
Desenvolvendo Aplicações Web com NetBeans IDE 6 Tabela 2 - Os atributos da tag Struts
Nome do atributo action enctype focus method name onreset onsubmit scope style styleClass styleId target type
Descrição A URL para o qual o formulário será submetido O content encoding para o qual será usado na submissão do formulário. O nome do campo no qual haverá um foco inicial. O método HTTP no qual será usado para submeter os dados. O nome da ActionForm do qual as propriedades serão usadas para popular os valores dos campos input. Tratador de evento JavaScript executado se o formulário é reiniciado. Tratador de evento JavaScript executado se o formulário for submetido. O escopo da ActionForm para este formulário. Os estilos CSS para ser aplicado nas tags HTML desse elemento. Classe CSS para ser aplicado neste elemento HTML. O identificados para a assinatura deste elemento HTML. O alvo para acessar um determinado frame quando o formulário for submetido. O nome de classe completamente qualificado de ActionForm para esta página.
Detalhando um pouco do atributo action
O valor para o atributo action da tag Struts é usado para selecionar ActionMapping , onde é assumido o nome suposto da página que processará o pedido, do qual você pode identificar o ActionForm apropriado e a extensão. Se a extensão mapeada em uso for “ *.do ” (padrão do Struts), o valor do atributo action deverá ser igual ao valor do atributo path correspondente para esse elemento, opcionalmente seguido pelo sufixo de extensão correto:
Ou: As Tags Logic de Struts
A biblioteca de tags Logic contém tags utilizadas para o gerenciamento condicional, resultando na saída de texto, loop sobre coleções de objetos ( geração repetitiva de saída de texto) e administração de fluxo da aplicação. Estas tags podem ser chamadas através da diretiva taglib existente em uma página JSP: <%@taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic"%>
Como pode notar, a biblioteca Logic do Struts é chamada pela URI:
http://jakarta.apache.org/struts/tags-logic E que contém o prefixo padrão logic. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
45
Desenvolvendo Aplicações Web com NetBeans IDE 6 A Tabela 3 a seguir demonstra as tags Logic do Struts: Tabela 3 - Tags Logic do Struts
Nome da Tag empty equal forward
Descrição Avalia o conteúdo do corpo aninhado desta tag e se a variável pedida for um null ou uma string vazia. Avalia se o conteúdo existente no corpo aninhado desta tag é uma variável igual ao valor especificado. Despacha o controle para a página especificada pela entrada ActionForward.
greaterEqual
Avalia o conteúdo no corpo desta tag no qual a variável pedida contém um valor maior que ou igual ao valor especificado.
greaterThan
Avalie o conteúdo do corpo desta tag se a variável pedida for maior que o valor especificado.
iterate
Repita o conteúdo de corpo desta tag sobre uma coleção especificada.
Avalia o conteúdo de corpo desta tag se a variável pedida for menor que ou igual ao valor especificado. Avalia o conteúdo de corpo desta tag se a variável pedida for menor que o lessThan valor especificado. Avalia o conteúdo de corpo desta tag se o valor especificado for uma match substring apropriada para a variável pedida. Gera o conteúdo do corpo desta tag se a mensagem especificada não messagesNotPresent estiver presente neste pedido. Gera o conteúdo do corpo desta tag se a mensagem especificada estiver messagesPresent presente neste pedido. Avalia o conteúdo do corpo desta tag se a variável pedida não for null notEmpty nem uma String vazia. Avalia o conteúdo do corpo desta tag se a variável pedida não for igual ao notEqual valor especificado. Avalia o conteúdo do corpo desta tag se o valor especificado não for uma notMatch substring apropriada para a variável pedida. Gera o conteúdo do corpo desta tag se o valor especificado não estiver notPresent presente neste pedido. Gera o conteúdo do corpo desta tag se o valor especificado estiver present presente neste pedido. redirect Renderiza um redirecionamento HTTP. lessEqual
Seu uso pode ser visto na página sucesso.jsp, visto na Listagem 6:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
46
Desenvolvendo Aplicações Web com NetBeans IDE 6 AS Tags Bean de Struts
As tags que fazem parte da biblioteca de tags Bean são usadas para acessar JavaBeans, e outras propriedades associadas, como também definir novos beans que serão acessíveis para o resto da página, através de variáveis scripting e atributos de escopo de página. Estas tags possuem os mecanismos necessários para criar um novo bean, baseado nos valores de pedidos através de cookies, cabeçalhos e parâmetros que são fornecidos. Essas tags podem ser chamadas através da diretiva taglib existente em uma página JSP: <%@taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
Como pode notar, a biblioteca Bean do Struts é chamada pela URI:
http://jakarta.apache.org/struts/tags-bean E que contém o prefixo padrão bean. A Tabela 4 a seguir demonstra as tags Bean do Struts: Tabela 4 - As tags Bean do Struts
Nome da tag
Descrição
cookie
Define uma variável baseada no(s) valore(s) especificados no cookie pedido.
define
Define uma variável baseada no(s) valore(s) especificados na propriedade bean.
header
Define uma variável baseada no(s) valore(s) especificados no pedido header.
include
Carrega a resposta para uma aplicação dinâmica pedida e a torna disponível como um bean.
message
Renderiza uma mensagem string internacionalizada para a resposta.
page
Expõe um item especificado do contexto da página como um bean.
parameter
Define uma variável baseada no(s) valore(s) especificados no parâmetro pedido.
resource
Carrega um recurso da aplicação web e a torna disponível como um bean.
size
Define um bean contendo o número de elementos em um Collection ou Map.
struts
Expõe para um Struts nomeado um objeto de configuração interno como um bean.
write
Renderiza o valor de uma propriedade bean específica.
Você utilizou a tag Struts para imprimir o nome transmitido pelo formulário na página sucesso.jsp : Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
47
Desenvolvendo Aplicações Web com NetBeans IDE 6 < bean:write name="integrator" property="nome" />
Utilizando Struts para acessar banco de dados Para compreender um pouco mais sobre Struts, você vai criar um CRUD de exemplo, utilizando banco de dados e o padrão DAO. Crie um novo projeto utilizando o framework Struts. Se desejar, chame-o de UtilStrutsComDAO. Adicione a biblioteca JDBC do MySQL ao projeto. Criando o JavaBean Autor
Para o exemplo, será utilizado a manipulação da tabela autores no banco de dados. Para iniciar, crie uma classe chamada Autor , que será nosso JavaBean. Altere-a como na Listagem 7 a seguir. Listagem 7. O JavaBean Autor package br.com.integrator; import java.util.Date; public class Autor { private Integer id; private String nome; private String email; private Date nascimento; public Autor() { } public Autor(Integer id, String nome, String email, Date nascimento) { this.id = id; this.nome = nome; this.email = email; this.nascimento = nascimento; } public Integer getId () { return id; } public void setId (Integer id) { this.id = id; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getEmail () { return email; } public void setEmail (String email) { this.email = email; } public Date getNascimento () { return nascimento; }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
48
Desenvolvendo Aplicações Web com NetBeans IDE 6 public void setNascimento (Date nascimento) { this.nascimento = nascimento; } }
A fábrica de conexão
No pacote br.com.integrator.util, será criada a classe ConnectionFactory, que será sua fábrica de conexões. A Listagem 8 exibe a classe. Listagem 8. A classe ConnectionFactory package br.com.integrator.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class ConnectionFactory { public static Connection getConnection () throws Exception { try { Class.forName("com.mysql.jdbc.Driver"); return DriverManager.getConnection( "jdbc:mysql://localhost/livraria", "edson", "integrator"); } catch (Exception e) { throw new Exception(e.getMessage()); } } public static void closeConnection (Connection conn, Statement stmt, ResultSet rs) throws Exception { close(conn, stmt, rs); } public static void closeConnection (Connection conn, Statement stmt) throws Exception { close(conn, stmt, null); } public static void closeConnection (Connection conn) throws Exception { close(conn, null, null); } private static void close(Connection conn, Statement stmt, ResultSet rs) throws Exception { try { if (rs != null) rs.close(); if (stmt != null)stmt.close(); if (conn != null)conn.close(); } catch (Exception e) { throw new Exception(e.getMessage()); } } }
Criando o DAO
Como agora possuímos a fábrica de conexões, que servirá o acesso ao banco de dados e nosso JavaBean, será criada a camada de manipulação ao banco de dados. No pacote br.com.integrator.dao , será criada a interface DAO e sua implementação AutorDAOImp . As Listagens 9 e 10 exibe DAO e AutorDAOImp respectivamente. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
49
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 9. A interface DAO package br.com.integrator.dao; import br.com.integrator.Autor; import java.util.List; public interface DAO { void atualizar (Autor autor) throws Exception; void excluir (Autor autor) throws Exception; Autor procurarAutor (Integer id) throws Exception; void salvar (Autor autor) throws Exception; List todosAutores () throws Exception; }
Listagem 10. A classe implementada AutorDAOImp package br.com.integrator.dao; import br.com.integrator.Autor; import br.com.integrator.util.ConnectionFactory; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * A classe AutorDAOImp cria o CRUD necessário para * manipular a tabela autores e implementa DAO * @author Edson Gonçalves * @since 22-12-2007 * @version 1.0 */
public class AutorDAOImp implements DAO { private Connection conn; /** * Método construtor que se conecta ao banco de dados * @throws java.lang.Exception se não houver conexão */
public AutorDAOImp( ) throws Exception{ try { this.conn = ConnectionFactory.getConnection( ); } catch( Exception e ) { throw new Exception( "Erro: " + e.getMessage( ) ); } } /** * Método que insere dados na tabela Autores * @param autor - recebe o objeto Autor * @throws java.lang.Exception se não conseguir inserir */
@Override public void salvar(Autor autor) throws Exception{ PreparedStatement ps = null; Connection conn = null; if (autor == null) throw new Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
50
Desenvolvendo Aplicações Web com NetBeans IDE 6
Exception("O valor passado não pode ser nulo"); try { String SQL = "INSERT INTO autores (nome, email, nascimento) "+ "values (?, ?, ?)"; conn = this.conn; ps = conn.prepareStatement(SQL); ps.setString(1, autor.getNome( )); ps.setString(2, autor.getEmail( )); ps.setDate(3, new java.sql.Date(autor.getNascimento( ).getTime())); ps.executeUpdate( ); } catch (SQLException sqle) { throw new Exception("Erro ao inserir dados " + sqle); } finally { ConnectionFactory.closeConnection(conn, ps); } } /** * Método que exclui uma linha na tabela aAutores * @param autor - recebe o objeto Autor * @throws se não for possível excluir o autor */
@Override public void excluir(Autor autor) throws Exception { PreparedStatement ps = null; Connection conn = null; if (autor == null) throw new Exception("O valor passado não pode ser nulo"); try { conn = this.conn; ps = conn.prepareStatement("delete from autores where id=?"); ps.setInt(1, autor.getId( )); ps.executeUpdate( ); } catch (SQLException sqle) { throw new Exception("Erro ao excluir dados:" + sqle); } finally { ConnectionFactory.closeConnection(conn, ps); } } /** * Método que atualiza os dados na tabela autores * @param autor - recebe o objeto Autor * @throws java.lang.Exception se não for possível atualizar */
if (autor == null) throw new Exception("O valor passado não pode ser nulo"); try { String SQL = "UPDATE autores SET nome=?, " + " email=?, " + "nascimento=? " + "where id=?"; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
51
Desenvolvendo Aplicações Web com NetBeans IDE 6 conn = this.conn; ps = conn.prepareStatement(SQL); ps.setString(1, autor.getNome( )); ps.setString(2, autor.getEmail( )); ps.setDate(3, new java.sql.Date(autor.getNascimento( ps.setInt(4, autor.getId( ));
).getTime()) );
ps.executeUpdate( ); } catch (SQLException sqle) { throw new Exception("Erro ao atualizar dados: " + sqle); } finally { ConnectionFactory.closeConnection(conn, ps); } } /** * Método que retorna todos os autores * @return objeto List * @throws java.lang.Exception se não for possível retornar o objeto List */
public List todosAutores () throws Exception{ PreparedStatement ps = null; Connection conn = null; ResultSet rs = null; try { conn = this.conn; ps = conn.prepareStatement("select * from autores"); rs = ps.executeQuery( ); List list = new ArrayList( ); while( rs.next( ) ) { Integer autorId = rs.getInt( 1 ); String nome = rs.getString( 2 ); String email = rs.getString( 3 ); Date nascimento = rs.getDate( 4 ); list.add( new Autor(autorId,nome,email,nascimento) ); } return list; } catch (SQLException sqle) { throw new Exception(sqle); } finally { ConnectionFactory.closeConnection(conn, ps, rs); } } /** * Método responsável por pesquisar um autor * @param id - recebe um Inteiro como parâmetro para pesquisar * pelo campo id * @return objeto Autor * @throws java.lang.Exception se não for possível retornar o objeto Autor */
public Autor procurarAutor (Integer id) throws
Exception {
PreparedStatement ps = null; Connection conn = null; ResultSet rs = null; try { conn = this.conn; ps = conn.prepareStatement("select * from autores where id=?"); ps.setInt(1, id); rs = ps.executeQuery( ); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
52
Desenvolvendo Aplicações Web com NetBeans IDE 6 if( !rs.next( ) ) { throw new Exception( "Não foi encontrado nenhum registro com o ID: " + id ); } String nome = rs.getString( 2 ); String email = rs.getString( 3 ); Date nascimento = rs.getDate( 4 );
O DAO criado é similar ao do livro, no Capítulo 4. Caso tenha alguma dúvida, recorra a ele para obter detalhes com explicações para sua maior compreensão. Gerando as classes Struts
Crie um novo arquivo. Selecione em Categories o item Struts e clique em Struts ActionForm Bean em File Types. Dê o nome de AutoresActionForm em Class Name e selecione em Package o pacote br.com.integrator.struts . Clique no botão Finish para confirmar.
Figura 16 – Criação do ActionForm AutoresActionForm
Na Listagem 11 a seguir há a classe para que você a altere. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
53
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 11. A classe AutoresActionForm package br.com.integrator.struts; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionMapping; public class AutoresActionForm extends org.apache.struts.action.ActionForm { private ArrayList autor = new ArrayList(); public ArrayList getAutor () { return autor; } public void setAutor (ArrayList autor) { this.autor = autor; } public AutoresActionForm () { super(); } public void reset(ActionMapping mapping, HttpServletRequest request) { autor = new ArrayList(); } }
Neste ActionForm foi criado um java.util.ArrayList que trará os dados encontrados na tabela para serem acessíveis pela página na camada apresentação (View), que exibirá uma tabela de dados. O próximo passo é desenvolver a action que se responsabilizará pela comunicação com os dados. Crie um novo arquivo do tipo Struts Action na categoria Struts. Chame de AutoresAction e coloque no pacote br.com.integrator.struts . No campo Action Path digite / AutoresActionForm . Clique no botão Next para prosseguir.
Figura 17 – Geração do Struts Action AutoresAction
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
54
Desenvolvendo Aplicações Web com NetBeans IDE 6 Na terceira e última etapa do assistente, em Input Resource selecione o arquivo welcomeStruts.jsp clicando no botão Browse. Marque a opção Request e clique no botão Finish para completar.
Figura 18 – Configurando o ActionForm
Altere seu código como o mostrado na Listagem 12 a seguir. Listagem 12. A classe AutoresAction package br.com.integrator.struts; import br.com.integrator.dao.AutorDAOImp; import br.com.integrator.dao.DAO; import java.util.ArrayList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; public class AutoresAction extends Action { /* forward name="success" path="" */ private final static String SUCCESS =
"success";
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AutoresActionForm autoresForm = (AutoresActionForm) form; DAO dao = new AutorDAOImp(); autoresForm.setAutor((ArrayList) dao.todosAutores()); return mapping.findForward(SUCCESS); }
}
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
55
Desenvolvendo Aplicações Web com NetBeans IDE 6 Perceba que você irá chamar AutoresActionForm e o DAO para trazer os autores. Através do método setAutor(), criado na classe AutoresActionForm , você irá recuperar todos os dados existentes na tabela do MySQL autores, encontrada no banco de dados livraria, através do método gerado na classe AutorDAOImp , chamado de todosAutores() . Como o método todosAutores() retorna um java.util.List , uma coerção para java.util.ArrayList é necessária, uma vez que o método setAutor() utiliza este objeto como tipo. Configurando o arquivo struts-config.xml
No arquivo struts-config.xml , vá por entre os elementos e clique com o direito do mouse. Selecione no menu de contexto o item Add Forward em Struts. Na caixa de diálogo, digite success em Forward Name e selecione em Resource File welcomeStruts.jsp. Clique no botão Add para confirmar.
Figura 19 – Geração do elemento em struts-config.xml
Seu arquivo struts-config.xml deverá estar com o trecho semelhante ao mostrado na Listagem 13 seguir: Listagem 13. O resultado final configurado em struts-config.xml
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
56
Desenvolvendo Aplicações Web com NetBeans IDE 6 Exibindo os dados da tabela
A página welcomeStruts.jsp será utilizada para a exibição dos autores cadastrados em formato tabular, encontrado na tabela autores do banco de dados livraria. A página welcomeStruts.jsp é mostrada na íntegra na Listagem 14 a seguir. Listagem 14. A página welcomeStruts.jsp <%@page contentType="text/html"%> <%@page pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> Autores Cadastrados
ID
Nome
E-mail
Nascimento
< bean:write name="autor" property="id" />
< bean:write name="autor" property="nome" />
< bean:write name="autor" property="email" />
Nenhum autor encontrado.
A criação desta página é bem simples, o Struts irá gerar uma tabela através de um loop, utilizando a tag , que percorrerá os dados encontrados na propriedade autor, do ArrayList existente na classe AutoresActionForm . Depois transmitirá pelo id os resultados, que serão, um a um, impressos pela tag , através do atributo property. Observe que para a data de nascimento do autor, existe o atributo format que define o padrão a ser usado neste caso.Se não houver dados, a tag apresentará uma mensagem ao usuário. Por fim, para chamar esta página, altere a página index.jsp . O link desta página deverá chamar AutoresActionForm , para que todo o processo seja iniciado. A Listagem 15 exibe as alterações propostas para a página.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
57
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 15. A página index.jsp <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> Pagina Inicial
Autores Cadastrados
Mostrar Autores
O link é criado pela tag Struts , chamando pelo atributo action a página mapeada por AutoresActionForm .
Figura 20 – Resultado da página que será exibida Adicionando, Editando e Excluindo autores
Crie um novo arquivo. Selecione em Categories o item Struts e clique em Struts ActionForm Bean em File Types. Dê o nome de EditarAutoresForm em Class Name e selecione em Package o pacote br.com.integrator.struts . Clique no botão Finish para confirmar. Listagem 16. A classe EditarAutoresForm package br.com.integrator.struts; public class EditarAutoresForm extends org.apache.struts.action.ActionForm { private Integer id; private String nome; private String email; private String nascimento; public Integer getId () { return id; } public void setId (Integer id) { this.id = id; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
58
Desenvolvendo Aplicações Web com NetBeans IDE 6 } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getEmail () { return email; } public void setEmail (String email) { this.email = email; } public String getNascimento () { return nascimento; } public void setNascimento (String nascimento) { this.nascimento = nascimento; } }
Neste ActionForm foi criado os campos que irão compor os formulários de inserir e atualizar. Crie um novo arquivo do tipo Struts Action na categoria Struts. Chame de EditarAutoresAction e coloque no pacote br.com.integrator.struts . No campo Action Path digite / Operacao . Clique no botão Next para prosseguir. Na terceira e última etapa do assistente, em Input Resource selecione o arquivo welcomeStruts.jsp clicando no botão Browse. Marque a opção Request e clique no botão Finish para completar. Altere seu código como o mostrado na Listagem 17 a seguir. Listagem 17. A classe EditarAutoresAction package br.com.integrator.struts; import br.com.integrator.Autor; import br.com.integrator.dao.AutorDAOImp; import br.com.integrator.dao.DAO; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.actions.DispatchAction; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; public class EditarAutoresAction extends DispatchAction { public ActionForward editAutor ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EditarAutoresForm editarAutoresForm = (EditarAutoresForm) form; Integer id = Integer.parseInt(request.getParameter("id")); DAO dao = new AutorDAOImp(); Autor autor = dao.procurarAutor(id); editarAutoresForm.setId(autor.getId()); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
Perceba que você irá chamar EditarAutoresActionForm e o DAO para trabalhar com os autores. Cada um dos métodos cria uma ação para atualizar, excluir ou inserir novos autores. Para editar um autor, por exemplo, chamamos o método editAutor(). Cada campo do formulário é alimentado com os dados encontrados na tabela, pesquisado através do parâmetro id transmitido com o número do autor que será atualizado. Para alimentar os campos, no DAO, chamamos o método procurarAutor() . A string retornada para redirecionar a página é showEdit . public ActionForward editAutor ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EditarAutoresForm editarAutoresForm = (EditarAutoresForm) form; Integer id = Integer.parseInt(request.getParameter( "id"));
DAO
dao = new AutorDAOImp();
Autor autor = dao.procurarAutor(id) ; editarAutoresForm.setId(autor.getId()); editarAutoresForm.setNome(autor.getNome()); editarAutoresForm.setEmail(autor.getEmail()); editarAutoresForm.setNascimento(dateToString(autor.getNascimento())); return mapping.findForward ("showEdit"); }
O método de exclusão segue a mesma lógica, capturando o id do autor e removendo-o através do método excluir() de DAO. O resultado desta ação é uma string success. public ActionForward deleteAutor ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EditarAutoresForm editarAutoresForm = (EditarAutoresForm) form; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
61
Desenvolvendo Aplicações Web com NetBeans IDE 6 Integer id = Integer.parseInt(request.getParameter( "id"));
DAO dao = new AutorDAOImp(); Autor autor = new Autor(); autor.setId(id); dao.excluir(autor);
return mapping.findForward("success"); }
Para adicionar um novo autor, o método addAutor() é chamado, onde retorna a string mapeada showAdd para redirecionar o usuário. public ActionForward addAutor ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { EditarAutoresForm editarAutoresForm = (EditarAutoresForm) form; return mapping.findForward( "showAdd");
}
Na hora de salvar o autor, seja após uma atualização ou inserção de dados, será chamado o método saveAutor() . Neste caso, os dados recuperados do formulário são transmitidos para o objeto Autor . Para salvar, se o id de autor for null, significa que é um novo cadastro, chamando o método DAO salvar(). Do contrário, é uma atualização, chamando atualizar(). public ActionForward saveAutor ( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { EditarAutoresForm editarAutoresForm = (EditarAutoresForm) form; DAO dao = new AutorDAOImp(); Autor autor = new Autor(); autor.setId(editarAutoresForm.getId()); autor.setNome(editarAutoresForm.getNome()); autor.setEmail(editarAutoresForm.getEmail()); autor.setNascimento(strToDate(editarAutoresForm.getNascimento())); if(autor.getId()== null) dao.salvar(autor); else dao.atualizar(autor); return mapping.findForward( "success");
}
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
62
Desenvolvendo Aplicações Web com NetBeans IDE 6 Configurando o arquivo struts-config.xml
No arquivo struts-config.xml , vá por entre os elementos de editarAutoresForm e altere como na Listagem 18. Listagem 18. Alterações no arquivo struts-config.xml
Observe que temos os casos retornados pela classe EditarAutoresActionForm definindo suas respectivas páginas. As páginas para editar e inserir dados
Para editar os dados, haverá uma chamada a página editAutor.jsp . Para adicionar os dados, uma página chamada addAutor.jsp . Estas páginas serão criadas dentro do diretório jsp. Veja na Figura 21 as duas páginas JSP que serão criadas no seu projeto.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
63
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 21 - Os arquivos encontrados dentro do diretório jsp
Crie a página addAutor.jsp , em jsp, e altere como na Listagem 19 exibida a seguir: Listagem 19. Alterações no arquivo struts-config.xml <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Adicionar Autor <%-- cria um form html --%>
<%-- cria a tabela com os campos --%>
Nome:
E-mail:
Nascimento:
Cadastrar
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
64
Desenvolvendo Aplicações Web com NetBeans IDE 6
<%-- o parametro necessario para chamar o metodo saveAutor() --%>
Figura 22 – A página de inserção de autores em ação
A página addAutor.jsp utiliza a tag Struts para criar os campos do HTML do tipo text. Cada campo é amarrado a classe EditarAutoresForm através do atributo property. Para criar o botão de envio, foi utilizada a tag Struts . Observe que no fim da página, há um campo oculto do Struts, , ao qual possui dois atributos: property – o parâmetro a ser transmitido value – o nome do método que sera chamado • •
Crie a página editAutor.jsp , em jsp, e altere como na Listagem 20 exibida a seguir: Listagem 20. Alterações no arquivo struts-config.xml <%@ page contentType="text/html"%> <%@ page pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Editar Autor <%-- cria o formulario html --%>
<%-- imprime os dados encontrados do autor nos campos --%>
Nome:
E-mail:
Nascimento:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
65
Desenvolvendo Aplicações Web com NetBeans IDE 6
Atualizar
<%-- cria um campo oculto contendo o ID do autor --%>
<%-- envia para o metodo saveAutor() --%>
A página para editar autores é similar a de cadastro, com a diferença de ter um campo oculto que receberá o id do autor que será atualizado.
Figura 23 – A página de edição de autores em ação Alterando a página que exibe todos os autores
Para finalizar, iremos alterar a página welcomeStruts.jsp para executarmos as ações de inserir, atualizar e excluir o autor. A Listagem 21 mostra na íntegra as alterações criadas na página. Listagem 21. A página welcomeStruts.jsp <%@page contentType="text/html"%> <%@page pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> Autores Cadastrados
ID
Nome
E-mail
Nascimento
Ações
< bean:write name="autor" property="id" />
< bean:write name="autor" property="nome" />
< bean:write name="autor" property="email" />
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
66
Desenvolvendo Aplicações Web com NetBeans IDE 6
property="nascimento" format="dd/MM/yyyy"/>
Editar
Excluir
Nenhum autor encontrado.
Adicionar novo Autor
Figura 24 – A página que exibe todos os autores com as alterações
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
67
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 4 Desenvolvendo Relatórios com NetBeans IDE Este capítulo extra o instruirá no desenvolvimento de relatórios JasperReports básicos utilizando o novo plugin iReport for NetBeans, que o NetBeans IDE 6 agora possui. No momento em que este livro é escrito, sua versão ainda não é final. O JasperReports
O JasperReports nasceu em 2001, criado por Teodor Danciu, quando este teve a tarefa de avaliar ferramentas de relatórios para um projeto em que estava trabalhando. As soluções existentes eram muito caras para o orçamento do projeto e, em uma situação comum no mundo do desenvolvimento, ele decidiu escrever sua própria ferramenta de relatórios, que ao liberá-la para a comunidade, ficou imensamente popular em pouco tempo. JasperReports é uma biblioteca escrita em Java, de código fonte open source, projetada para ajudar o desenvolvedor com a tarefa de criar relatórios para aplicações, tanto Desktop como Web, fornecendo uma API que facilita sua geração. Embora seja simples, ainda exige que o desenvolvedor conheça seu formato XML utilizado para criar os relatórios, o que torna dispendioso o tempo de um iniciante. O iReport para o NetBeans
O iReport é um programa Open Source, criado em 2002 por Giulio Toffoli, capaz de criar visualmente os mais complexos relatórios para aplicações Java no formato da biblioteca JasperReports. Sua versão atual é escrito em 100% Java, e seus códigos fontes são distribuídos gratuitamente de acordo com a GNU (General Public License). Em 2005, com a popularidade do iReport, a JasperSoft (mantenedora do JasperReports) tornou esta ferramenta oficial na construção de relatórios para o JasperReports. Recentemente seu criador começou a portar a ferramenta para a plataforma do NetBeans, criando duas versões: um plugin que pode ser instalado na IDE ou standalone. Através de uma interface gráfica intuitiva, o desenvolvedor é capaz de criar qualquer tipo de relatório de forma simples e rápida. Mesmo sabendo que o iReport desenvolve um formato XML usado pelo JasperReports, o que não é difícil de manipular, há uma vantagem em usar esta ferramenta. Se o desenvolvedor é um usuário iniciante no formato XML do JasperReports, o iReport supre suas necessidades evitando que seja necessário fazer modificações no código fonte. Caso seja experiente neste formato, o iReport minimiza o tempo na criação dos mais complexos relatórios.
Desenvolvendo relatórios com NetBeans O iReport é um bem-sucedido programa Open Source, capaz de criar visualmente os mais complexos relatórios para aplicações Java no formato da biblioteca JasperReports. Atualmente, além de ser um programa gráfico independente, há também uma versão disponível que se integra ao NetBeans IDE 6.0. Através de uma interface gráfica e intuitiva, o desenvolvedor é capaz de criar qualquer tipo de relatório de forma simples e rápida. O iReport para NetBeans desenvolve um formato XML usado pelo JasperReports, evitando naturalmente a edição no código. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
68
Desenvolvendo Aplicações Web com NetBeans IDE 6 Neste capítulo você aprenderá onde obter, como instalar, criar seu relatório e integrá-lo a suas aplicações Web conhecendo algumas características do iReport. Obtendo e instalando o iReport para NetBeans
Para obter o iReport para NetBeans, primeiramente você precisará baixar o plugin. Para isso, o endereço oficial para baixá-lo é: http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=4424. Clique no botão Download. Você obterá o arquivo .nbm para instalação.
Atenção: No momento em que este livro está sendo escrito, este plugin ainda se encontra em versão BETA, sem algumas funcionalidades encontradas no iReport. Vá ao menu Tools e clique no item Plugins. Na caixa de diálogo Plugins, vá à guia Downloaded e clique no botão Add Plugins, selecionando, através da caixa de diálogo o arquivo de extensão .nbm pertencente ao iReport para NetBeans. Ao fazê-lo, clique no botão Install.
Figura 1 – Adição do plugin ireport-designer
Ao clicar no botão Install, a caixa de diálogo NetBeans IDE Installer surgirá. Clique no botão Next para prosseguir com a instalação.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
69
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 2 – Início da instalação do plugin ireport-designer
Na etapa seguinte, você deverá aceitar os termos de licença. Clique na opção I accept the terms in all of the license agreements e clique no botão Install. A caixa de diálogo Validation Waring surgirá, dizendo que o plugin a ser instalado não foi assinado e que é potencialmente inseguro. Clique em Continue.
Figura 3 – Validação do plugin
Ao terminar a instalação, clique no botão Finish. Retornando a caixa de diálogo Plugins, observe, na guia Installed, que o plugin ireport-designer está instalado. Clique no botão Close para fechar a janela.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
70
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 4 – Plugin instalado Criando um relatório para trabalhar com Servlets
Crie um projeto Web chamado de RelatoriosComServlet. Em Web Pages crie um diretório chamado relatorios. Clique com o direito neste diretório e no menu de contexto selecione New e clique em Other. Na caixa de diálogo New File selecione JrxmlTemplate.jrxml, em Reports. Em alternativa, caso esteja aparecendo a opção JrxmlTemplate.jrxml no menu New, selecione-a. Na segunda etapa, digite o nome do seu relatório. Se preferir seguir o livro, chame-o de relatório e conclua o assistente.
Figura 5 – Criando um documento JasperReports Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
71
Desenvolvendo Aplicações Web com NetBeans IDE 6 A estrutura e propriedades de um relatório JasperReports
Ao finalizar o assistente, o Designer do iReport para NetBeans surgirá. Além do Design, você possui a possibilidade de visualizar em formato XML e fazer um Preview. Um relatório no JasperReports possui diversas seções, separadas por linhas horizontais ao qual são chamadas de Bands (bandas) . O comportamento de cada Band depende da funcionalidade para a qual está preparada. Quando o relatório junta aos dados para fazer a impressão, estas seções são impressas na tela de diferentes maneiras com diferentes tempos. Por exemplo, o cabeçalho da página ( pageHeader) é repetido em todas as páginas, uma vez em cada página, enquanto que os detalhes onde serão exibidos os dados (detail) é gerado em uma seqüência elaborada de acordo com os dados existentes ( query ou datasource), repetindo-se uma vez para cada registro, incorporando-se ao desenho do relatório. As bands de um relatório JasperReports é dividido em dez seções pré-definidas para que novos grupos possam ser adicionados. Embora as bands já estejam adicionadas e com espaçamentos pré-definidos inicialmente, você pode com o cursor, entre cada uma delas, nas linhas horizontais que as separam, e movê-las. Ao arrastar, você percebe que a altura de cada band se expande, empurrando as demais, após a alterada, para baixo ou vice-versa. Embora o desenvolvedor possa alterar a sua altura, em casos como a band detail, sua alteração implica na visibilidade e espaçamento dos elementos impressos na geração do relatório. Porém, nem todas as bands são organizadas dinamicamente pelo conteúdo, como é o caso de Column Footer, Page Footer e Last Page Footer .
Figura 6 – Estrutura do relatório JasperReports
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
72
Desenvolvendo Aplicações Web com NetBeans IDE 6 Na janela Outline Window, você encontra os parâmetros (Parameters), campos da tabela da sua query (Fields), variáveis pré-definidas e criadas (Variables) e as bands do relatório. Por padrão, algumas bands estão desativadas ou com sua altura no valor zero, o que a torna invisível no design (como a band background).
Figura 7 – A janela Outline e os componentes do relatório
Na janela Palette você encontra os elementos de um relatório.
Figura 8 – A janela Palette e os ReportElements
Seguindo a imagem da Figura 8 você tem as seguintes ferramentas: Chart – Gera um gráfico através de valores determinados transmitidos. Mais adiante haverá um capítulo exclusivamente para gráficos. Image – Utilizado para exibir imagens em seu relatório. Podem ser imagens dinâmicas (preenchidas por um banco de dados, por exemplo) ou estáticas. Rectangle – Usado para desenhar retângulos ao redor de outros elementos, criando destaques como uma formatação de parágrafo de um programa de edição de textos, este elemento pode também conter retângulos com cantos arredondados. •
•
•
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
73
Desenvolvendo Aplicações Web com NetBeans IDE 6 •
• •
•
Text Field – Utilizado para criar os campos dinâmicos dos relatórios. É neste elemento que você se conecta a um determinado campo do banco de dados para exibir suas informações, por exemplo. Ellipse – Desenha elipses no relatório. Line – Em um relatório JasperReports uma linha é definida por um elemento retangular com uma linha diagonal. A linha pode ser desenhada em uma reta perfeita, na horizontal, vertical ou em ângulo se pressionada a tecla antes de arrastar. A linha segue o grid. Static Text – Utilizado para criar rótulos de relatórios.
Na parte inferior, da janela Palette se encontra as Properties. Quando um elemento é selecionado aparece nesta janela suas propriedades para serem alteradas.
Figura 9 – A janela Properties do relatório
Nas propriedades do relatório, você possui o grupo Page size. Neste grupo você pode definir a largura da página ( Page width) e a altura da página ( Page height ), bem como a Orientação (Orientation). Em Orientation, temos Portrait (Retrato) ou Landscape (Paisagem). Embora as dimensões sejam as mais importantes para a construção de um relatório, a unidade de medidas usada pelo iReport e JasperReports é em pixels (com uma resolução de 75 dpi). Para que você possa se orientar em um arquivo JRXML do JasperReports, a seguir a Tabela 1 mostra o padrão da página e seu valor em pixels. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
74
Desenvolvendo Aplicações Web com NetBeans IDE 6 Tabela 1 – Dimensões em pixels das páginas padronizadas
Dimensão em Pixels 612 x 792 540 x 720 612 x 1008 2380 x 3368 1684 x 2380 1190 x 1684 842 x 1190 595 x 842 421 x 595 297 x 421 210 x 297 148 x 210 105 x 148 74 x 105 2836 x 4008 2004 x 2836 1418 x 2004 1002 x 1418 709 x 1002 501 x 709 2592 x 3456 1728 x 2592 1296 x 1728 864 x 1296 648 x 864 612 x 936 612 x 936 396 x 612 792 x 1224 1224 x 792
No grupo Columns você pode definir quantas colunas seu relatório possuirá em uma página, no item Columns. Column Width automaticamente se altera quando você adiciona mais de uma coluna, dividindo sem o valor em partes iguais. Column Spacing determina o espaçamento entre colunas, que também influi em Column Width automaticamente. No grupo “More...” é possível especificar instruções para a impressão do relatório. Nele se encontram: Scriptlet Class - Onde você define um scriptlet, que nada mais é que uma classe Java cujos métodos são executados conforme são especificados os eventos durante a criação do relatório, como o início de uma nova página ou o fim de um grupo. Resource Bundle - É o nome do pacote de recursos usado para internacionalizar um relatório. É o Resource Bundle do Java, onde você define em um arquivo os textos traduzidos como rótulos. Cada linguagem corresponde a um arquivo específico. When Resource Missing Type – Se um pacote de recurso (Resource Bundle) não está disponível, você escolhe uma das opções na caixa de combinação. Representa o atributo whenResourceMissingType no JasperReports. Neste caso, você tem as seguintes opções: •
•
•
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
75
Desenvolvendo Aplicações Web com NetBeans IDE 6 1. Type Null (Nulo) – Imprime a string “ Null ”. Esta é a opção padrão. 2. Type Empty (Vazio) – Não imprime nada. Recebe como valor Empty no atributo whenResourceMissingType de JasperReports. 3. Type the Key (Chave) – Imprime o nome chave que falta. Recebe como valor Key no atributo whenResourceMissingType de JasperReports. 4. Rise an Error (Erro) – Lança uma exceção parando o processo. Recebe como valor Error no atributo whenResourceMissingType de JasperReports. • •
• •
•
•
•
•
•
•
Query Text – Determina a query criada para o relatório. Query Language – Determina a linguagem utilizada para a instrução. Pode ser: SQL, HQL(Hibernate Query Language) , XPath, EJBQL, MDX e XMLA-MDX. Properties – Determina as propriedades para o objeto selecionado. Title on a new page - Quando ativa, especifica se a banda title será impressa e em seguida criada uma nova página, gerando uma “quebra de página”. Summary on a new page - Esta opção é similar a anterior ( Title on a new page ), mas com a diferença de ser a banda summary que será impressa como a última página. Floating column footer - As bandas columnFooter são impressas por padrão no fim das páginas. Se na impressão do relatório não houver dados suficientes para preencher uma página, um espaço em branco aparecerá entre a coluna e o rodapé da coluna (columnFooter). Se você quer que o texto encontrado na banda columnFooter seja impresso logo após a impressão da coluna, marque a opção Floating column footer . Esta opção permite forçar a impressão da banda columnFooter imediatamente após a última interação da banda detail e não do término de todas as colunas. Esta opção é geralmente usada quando você quer criar tabelas usando os elementos de relatórios. Ignore pagination - Ignora a paginação ao preencher o relatório, impossibilitando a visualização das demais páginas caso haja mais que uma. Quando ativa, esta opção implica até mesmo na visualização correta dos dados caso haja mais de uma coluna. Print Order - A ordem de impressão (Print Order) determina como os dados impressos na página serão organizados em mais de uma coluna. O padrão para a ordem de impressão é Vertical. Com a ordem Vertical, primeiro os dados são impressos um embaixo do outro, passando para uma nova coluna somente quando a coluna está totalmente preenchida no final da página. Na ordem Horizontal os dados são preenchidos em linha. Os dados passam por todas as colunas, adicionando uma nova linha somente quando a última coluna da página foi preenchida naquela determinada linha. When no data - Quando o número de dados para a impressão é vazio (query SQL sem dados, por exemplo), o relatório pode ter comportamentos diferentes para apresentar a página ao usuário. Neste caso existem quatro opções, listadas a seguir: 1. Type No Pages (Sem Páginas)– O padrão. O resultado final é um buffer vazio. 2. Type a Blank Page (Páginas em branco) – Exibe uma página em branco caso não haja dados. 3. Type All Sections, No Detail (Todas as seções, nenhum detalhe) – Mostra todas as seções existentes no relatório, menos os detalhes da banda detail. 4. Type “No Data” section – Seção sem dados. Utiliza a band noData, ou seja, você adiciona um conteúdo estático (ou dinâmico sem usar o banco de dados) neste local. Caso não haja dados em uma determinada pesquisa ou sem conexão com o banco de dados, esta seção será exibida. Language – Determina a linguagem a ser utilizada no relatório. Neste caso, somente as duas linguagens oficiais do JVM são possíveis, por enquanto: Java ou Groovy.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
76
Desenvolvendo Aplicações Web com NetBeans IDE 6 •
Format Factory Class - Recebe uma string com o nome da classe de formatos, habilitando o uso de datas personalizadas e formatos de números. Representa o atributo formatFactoryClass de JasperReports e implementa a interface net.sf.jasperreports.engine.
Exibindo o Grid
Você pode exibir o Grid para desenhar o relatório, vá ao menu Designer e clique em Show Grid. Também é possível alinhar os elementos dentro do relatório se selecionar a opção Snap To Grid .
Figura 10 – Exibindo o Grid no Design Adicionando uma conexão a um relatório em branco
Para a construção deste relatório, vamos utilizar o banco de dados livraria. Vá ao menu Data e clique em Connections/Data Sources , ou na barra de ferramentas Designer.
Figura 11 – Connections / Datasources no menu Data e ferramentas Designer
Na caixa de diálogo Connections / Datasources , clique no botão New. Em Datasource selecione o item NetBeans Database JDBC connection e clique no botão Next.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
77
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 12 – Seleção do datasource NetBeans Database JDBC connection
Na segunda etapa, selecione em Connection a conexão livraria usada neste livro e digite livraria em Name. Clique no botão Test. Se a caixa de diálogo “ Connection test successful!” surgir, confirme e clique no botão Save .
Figura 13 – Configurando a conexão livraria
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
78
Desenvolvendo Aplicações Web com NetBeans IDE 6 Para uma modificação da conexão, na caixa de diálogo Connections / Datasources temos o botão Modify. Basta selecionar a linha da sua conexão que deseja alterar e clicar neste botão. A caixa de diálogo de propriedades da conexão reabre. Basta alterar e salvar (Save). Em mais de uma conexão, você tem o botão Set as default. Basta selecionar a conexão que deseja tornar padrão (Default) e clicar neste botão. Observe que na caixa de diálogo a coluna Default apresenta a conexão padrão com uma caixa de checagem ativa. Caso você precise levar as configurações da sua conexão para outra máquina, ou quer guardá-la para uma futura reutilização, clique no botão Export. A caixa de diálogo para salvar a conexão aparecerá. Basta selecionar o local e dar o nome. Caso tenha mais de uma conexão, todas serão exportadas. Se precisar importar uma conexão do próprio iReport, basta clicar no botão Import. Depois de configurado, basta fechar a caixa de diálogo.
Figura 14 – Conexão criada e disponível Criando a query do relatório
Para criar a query do relatório, vá ao menu File e clique no item Report query. Alternativamente você pode ir ao ícone Report query, acima do design do relatório.
Figura 15 – Abrindo o Report query
Ao abrir a caixa de diálogo Report Query, clique no botão Query designer. Outra caixa de diálogo surgirá, chamada de SQL Query Designer , mas desta vez para a criação da instrução SQL visual. Observe que há três quadros na janela. O primeiro, à esquerda, define a exibição da query de forma visual, separando os elementos padronizados de uma seleção de dados (SELECT, FROM, WHERE e etc.). A cada coluna de sua tabela selecionada, automaticamente a query adicionará na parte superior, em SELECT, o campo e um alias. Em FROM surgirá a, ou, as tabelas que estão relacionadas para tal seleção.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
79
Desenvolvendo Aplicações Web com NetBeans IDE 6 Você vai selecionar, através do segundo quadro a esquerda, a tabela autores, dando um duplo clique sobre seu respectivo nome. Esta seleção pode ser através do arrastar para o quadro da direita também, caso ache mais prático. Existem duas formas de você selecionar todos os campos de uma tabela, no Query designer. A primeira é ir até a tabela (no caso autores) e clicar no menu de mesmo nome, selecionando a opção select all. A segunda forma é clicando com o direito do mouse e selecionando a opção add expression, no quadro da esquerda, em SELECT.
Figura 16 – Adicionando uma expressão
Neste caso, você digita o que deseja fazer, na caixa de diálogo expression.edit. Para o caso, digite “*” e confirme. Ao final, você possuirá uma configuração da sua query SELECT similar ao mostrado na Figura 17 a seguir:
Figura 17 – Query desenhada na caixa de diálogo SQL Query Designer
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
80
Desenvolvendo Aplicações Web com NetBeans IDE 6 Se você clicar em SQL, a guia abaixo, ao lado de Builder (a atual), você verá a query construída. Confirme no botão OK. Retornando a caixa de diálogo Report query, você ainda pode fazer alterações na query criada. Na parte superior da janela, existe o botão Save query, caso deseje armazenar a consulta construída para uso posterior em outro relatório. Se esse for o caso, o carregamento de uma consulta armazenada pode ser feito através do botão Load query. Como a opção Automatically Retrieve Fields está selecionada, na parte inferior aparece cada campo selecionado, em uma tabela, com seus respectivos nomes e o tipo de dados em Java de cada um. É importante manter selecionada esta opção, uma vez que na digitação ou alteração de uma query, possíveis erros podem ser encontrados graças à exibição dos campos nesta tabela. Caso esta opção não esteja selecionada, qualquer alteração na query SQL não reflete automaticamente abaixo, o que necessitará clicar no botão Read Fields. Confirme logo após no botão OK.
Figura 18 – Query final gerada pela caixa de diálogo SQL Query Designer Desenhando o relatório
O desenho do relatório será uma etapa importante para a sua compreensão prática dos elementos existentes para se criar um e também sobre as bands (bandas) em sua geração. Para começar na criação do desenho do relatório, você vai configurar inicialmente as bands que não serão exibidas. Com o cursor entre uma band e outra, você deve arrastar para cima, até que ela se encontre com a superior. Isso diminui a sua altura até zero, o que é exatamente o valor necessário para esta desaparecer. As alturas de cada band para a criação do relatório é exibida conforme a Tabela 2 mostrada a seguir: Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
81
Desenvolvendo Aplicações Web com NetBeans IDE 6 Tabela 2 – Alturas das bands utilizadas na construção do relatório
Band title pageHeader columnHeader detail columnFooter pageFooter summary
Altura da Banda 0 Mantenha como está Mantenha como está Mantenha como está 0 Mantenha como está Mantenha como está
Atenção: Você pode configurar as propriedades de cada band selecionando-a através da janela Outline Window e alterando em Properties, no campo Band height . Neste caso, a alteração não precisa ser aplicada (alterou o valor da propriedade, confirmou com a tecla ENTER, mudou). Adicionando os textos estáticos
Antes de iniciar a criação do desenho, você tem na Figura 19 como será o resultado final. Veja no quadro “Construindo o design do relatório ” para criá-lo.
Figura 19 – Aparência final do relatório no Designer
Construindo o design do relatório Para criar a aparência vista na Figura 19, os seguintes passos serão feitos: 1. Na janela Palette, arraste o elemento Static Text (Label) e o dimensione a um tamanho qualquer na band pageHeader. Dê um duplo clique neste elemento desenhado e digite: Autores Cadastrados . Na janela Properties altere em Font Size para 24 e clique no botão Bold. Mude também para Center em Horizontal Alignment e para Middle em Vertical Alignment. 2. Na categoria Box properties, na janela Properties, com o label Autores Cadastrados selecionado, altere Border para 1 Point e coloque None em Left Border e Right Border . 3. Adicione um elemento Rectangle na band columnHeader e altere a cor em Background a sua escolha, na janela Properties.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
82
Desenvolvendo Aplicações Web com NetBeans IDE 6 4. Adicione quatro elementos Static Text sobre o elemento Rectangle adicionado. Digite ID, Nome, E-mail e Nascimento respectivamente (ver Figura 19). Altere seu tamanho a sua escolha e coloque em Bold. Para alinhar, o editor visual do iReport para NetBeans possui linhas auxiliares para o alinhamento, herdado do Sun's Visual Library API do NetBeans. 5. Na janela Outline, expanda Fields e arraste cada campo para a band detail, no Design. Olhe a posição conforme a Figura 19 apresenta. Dimensione a largura de cada componente a gosto. Observe os campos arrastados são Text Fields.
Figura 20 – Fields criados a partir da instrução SQL gerada
6. Selecione, no Design, o Text Field que representa o campo nascimento. Na janela Properties, vá até o item Pattern e de um clique no botão com três pontos ou em sua seleção, pressione Ctrl+Space. Na caixa de diálogo Text field – Pattern, selecione Date em Category e em Type selecione o formato de data usado no Brasil. Observe na parte inferior, em Pattern, o formato dd/MM/yyyy.
Figura 21 – Seleção do pattern para o formato de data Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
83
Desenvolvendo Aplicações Web com NetBeans IDE 6 7. Expanda Variables, na janela Outline, e arraste para a band pageFooter e o posicione no canto direito.
Figura 22 – A variável PAGE_NUMBER selecionada
8. Para finalizar, adicione um Static Text ao lado desta variável PAGE_NUMBER e digite Página:. Clique em Preview para visualizar o relatório. Observe que os dados encontrados na band detail serão repetidos até o seu fim, criando uma nova página sucessivamente até a última linha encontrada em sua tabela. Na parte inferior você vê o número da página.
Figura 23 – Preview do relatório criado
Em caso de erro, observe a saída encontrada na parte inferior, na janela iReport output.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
84
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 24 – Saída executada pelo iReport para NetBeans na compilação e exibição do relatório
Configurando o NetBeans IDE 6.0 para executar seu relatório
A primeira providência a fazer é configurar as bibliotecas para gerar os relatórios no NetBeans IDE 6.0. Para compilar sua aplicação, você vai precisar de sete arquivos JARs, para este caso, listados a seguir:
Como o iReport para NetBeans necessita de tais bibliotecas para executar, você pode encontrá-las no CD-ROM anexo ao livro, compactado no diretório de jasperreports, em lib. Vá ao menu Tools e clique no item Libraries.
Figura 25 – Selecionando Libraries pelo menu Tools
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
85
Desenvolvendo Aplicações Web com NetBeans IDE 6 Na caixa de diálogo Library Manager, clique no botão New Library. Na caixa de diálogo New Library digite JasperReports (se desejar colocar a versão também, é interessante) no campo Library Name e clique no botão OK para confirmar. Retornando a caixa de diálogo Library Manager, clique no botão Add JAR/Folder . Selecione os arquivos .jar citados do JasperReports anteriormente e confirme. Retornando, você terá os arquivos configurados no campo Library Classpath da guia Classpath.
Figura 26 – Bibliotecas do JasperReports Adicionando as bibliotecas para rodar o relatório
Na janela Projects, clique com o direito do mouse sobre Libraries, com seu projeto expandido, e selecione Add Library no menu de contexto. Na caixa de diálogo Add Library, selecione com JasperReports (a biblioteca criada anteriormente) e MySQL, com o Ctrl pressionado. Confirme clicando no botão Add Library. Criando o Servlet que chamará o relatório
Sobre o projeto, clique com o direito do mouse, em Projects, e selecione o item New, clicando em Servlet. Na caixa de diálogo New Servlet, digite Relatorio em Class Name. Adicione um pacote em Package (no caso do livro, seria br.com.integrator). Clique no botão Finish para completar. Adicione no Servlet o código mostrado na Listagem 1 a seguir e salve. Listagem 1 – Trecho do Servlet Relatorio contendo a chamada ao arquivo JasperReports //... omitido por não haver alterações
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletOutputStream servletOutputStream = response.getOutputStream(); String caminho = "/relatorio/"; String relatorio = caminho+"relatorio.jasper"; InputStream reportStream = Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
86
Desenvolvendo Aplicações Web com NetBeans IDE 6
getServletConfig().getServletContext().getResourceAsStream(relatorio); Connection connection = null; try { //cria a conexão com o banco de dados
Class.forName("com.mysql.jdbc.Driver"); String db = "jdbc:mysql://localhost:3306/livraria"; connection = (Connection) DriverManager.getConnection(db,"edson","integrator"); // envia o relatório em formato PDF para o browser
response.setContentType("application/pdf"); //para gerar o relatório no formato PDF // o método runReportToPdfStream foi usado
Para as importações dos objetos encontrados, utilize o atalho Ctrl + Shift + I (Fix All Imports).
Figura 27 – Importação com Fix All Imports
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
87
Desenvolvendo Aplicações Web com NetBeans IDE 6 Toda a lógica necessária para a criação do relatório está no método protegido processRequest(). Este método, configurado para ser chamado tanto via método POST e GET, utiliza o método runReportToPdfStream() . Este método, de JasperRunManager, cria uma instância de java.io.OutputStream() para escrever o relatório compilado e possui os seguintes parâmetros: (java.io.InputStream inputStream, runReportToPdfStream
Para exibir o relatório no browser, você precisa passar o relatório criado para um stream de dados. É exatamente isso que ocorre no primeiro parâmetro deste método. O relatório é pego em uma String e depois convertido em um InputStream, no seguinte trecho: String caminho = "/relatorio/"; String relatorio = caminho + "relatorio.jasper"; InputStream reportStream = getServletConfig(). getServletContext(). getResourceAsStream(relatorio);
O segundo parâmetro é a resposta, que é definida em um ServletOutputStream , através do seguinte trecho: ServletOutputStream servletOutputStream = response.getOutputStream();
O terceiro parâmetro é o HashMap necessário para transmitir algum parâmetro para o seu relatório, caso este o tenha. Por último foi transmitida a conexão, para que o relatório executasse com sucesso. A saída foi definida pelo setContentType(), que através do objeto response, possibilitou a finalização com o MIME TYPE para que o browser o reconheça como PDF.
Atenção: O exemplo passado do Servlet, define apenas um modelo didático, não sendo ideal para sistemas em produção. Recomendo o conhecimento de Design Patterns.
A página que chamará o Servlet
Você mesmo pode criar se desejar, uma página que chamará seu Servlet. O trecho a seguir mostra a chamada ao Servlet, lembrando que o nome dado está configurado no deployment descriptor (web.xml), que para o caso deste livro, será gerado automaticamente pela IDE. Portanto, abra o arquivo index.jsp e adicione o pequeno trecho mostrado na Listagem 2 a seguir: Listagem 2 – Alteração do arquivo index.jsp <%@ page contentType="text/html" pageEncoding="UTF-8"%> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> Relatórios JasperReportsClique aqui para visualizar seu relatório Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
88
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 28 – Relatório exibido no browser após sua chamada Trabalhando com parâmetros em seus relatórios
O primeiro exemplo demonstra somente a chamada ao relatório criado, sem transmitir parâmetros. Para o segundo exemplo, você vai adicionar um parâmetro ao relatório. Para fazer este, abra o projeto do Capítulo 4, TrabComPadroes . Adicione um diretório chamado relatorio e copie para este o relatório criado.
Figura 29 – Exibição do projeto TrabComPadroes contendo o relatorio.jrxml
Abra o arquivo relatorio.jrxml . Na janela Outline, clique com o direito do mouse sobre Parameters e no menu de contexto selecione parameter em Add.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
89
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 30 – Adicionando um parâmetro pelo menu de contexto
Com o parâmetro criado e selecionado, vá até a janela Properties e altere os campos como mostra a Tabela 3: Tabela 3 – Propriedades do parâmetro criado
Propriedade Name Parameter Class Default value expression
Valor ID java.lang.Integer new Integer(0)
Figura 31 – Propriedades alteradas do parâmetro adicionado
Abra a caixa de diálogo Report Query, e altere a query como mostrado na Listagem 3 a seguir: Listagem 3 – Alteração da query usada no relatório
SELECT FROM
*
Autores
WHERE id=$P{ID}
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
90
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 32 – Alteração da instrução SQL
Feche a caixa de diálogo e clique em Preview para gerar o arquivo .jasper. Adicionando o Servlet Relatorio
Crie um Servlet chamado Relatorio e adicione o conteúdo similar ao mostrado na Listagem 4 a seguir: Listagem 4 – O Servlet Relatorio //...omitido por não haver alterações
connection = (Connection) ConnectionFactory.getConnection( ); HashMap parameterMap = new HashMap(); //o Nome do parâmetro e o valor é passado ao HashMap
parameterMap.put("ID", Integer.parseInt(id));
// envia o relatório em formato PDF para o browser
response.setContentType("application/pdf");
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
91
Desenvolvendo Aplicações Web com NetBeans IDE 6 //para gerar o relatório em PDF // o método runReportToPdfStream foi usado
O parâmetro passado é um java.util.HashMap() , que define se haverá um ou mais parâmetros. O parâmetro criado no relatório possui um nome, e é este que deve ser utilizado neste HashMap : ID (referindo-se a $P{ID}. Como se trata de uma chave string e de um valor numérico inteiro, graças ao método put(Key, Value), o exemplo capturará o campo chave de cada autor e o transmitirá ao parâmetro, da seguinte forma: String id = request.getParameter( "id"); parameterMap.put("ID", Integer.parseInt(id));
Chamando o Servlet para gerar o relatório
Abra o arquivo mostrarAutoresCads.jsp e adicione mais uma coluna a tabela, sendo que neste última haverá a chamada ao servlet Relatorio, como mostra o detalhe na Listagem 5 a seguir: Listagem 5 – Chamando o Servlet por mostrarAutoresCads.jsp <%@ page contentType="text/html" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> Trabalhando com DAO e Model 2
Atenção: No CD-ROM há um vídeo que ensina a criar seu relatório usando o assistente.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
93
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 5 Estudo de caso completo com Visual Web JSF Este capítulo extra é a continuação do sistema iniciado nos Capítulos 7 e 8, sendo que sem a leitura destes, será mais difícil sua execução. Adicionando novas características ao administrador
Enquanto que no livro você pôde criar uma aplicação com os elementos fundamentais do Visual Web JSF, entendendo os detalhes de como funcionam, neste capítulo extra, será finalizada toda a área administrativa, adicionando relacionamento às tabelas. Além disso, outros componentes serão usados, integrando-se para criar uma área administrativa mais complexa. Neste capítulo será apresentado: A criação de mais três entidades (tabelas); Utilização de campos ocultos; Transmitindo dados via HTTP, pelo método GET; Utilizando o componente Listbox com banco de dados; • • • •
As entidades e seus relacionamentos No decorrer do livro, duas tabelas foram utilizadas para o desenvolvimento do administrador do aplicativo Web: livros e autores. Agora, será necessário criar três novas tabelas: editoras, publicacao e livro_autor.
Figura 1 – Modelo de dados do projeto
A Listagem 1 mostra o script para a criação das tabelas que serão adicionadas (veja o quadro “Utilizando o NetBeans para instruções SQL ”) no banco de dados de livraria .
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
94
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 1. Script para criação das tabelas do projeto CREATE TABLE editoras ( int(11) NOT NULL auto_increment, id editora varchar(50) default NULL, PRIMARY KEY (id) ) ENGINE=InnoDB;
CONSTRAINT fk_autor_livro FOREIGN KEY (autor_id ) REFERENCES autores(id ) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fk_livro_autor FOREIGN KEY (livro_id ) REFERENCES livros(id ) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE = InnoDB;
Entendendo o relacionamento
Quando um livro, uma editora e um autor são cadastrados, podemos relacioná-los. Um livro pode pertencer a um ou mais autores, quanto que a publicação geralmente é feita em somente uma editora. Desta forma, se o livro “X”, foi escrito pelos autores “A”, “B” e “C”, será publicado pela editora “Ciência Moderna. Logo, podemos ter muitos autores para um determinado livro ou um autor para muitos livros. Esta é a modelagem mais simples de se entender. Para que haja a relação entre autor e livro (ou vice-versa), temos uma tabela que possui o relacionamento Many-To-Many (Muitos-para-Muitos), ao qual armazenará o código do autor e do seu respectivo livro escrito. É evidente que na tabela de livros temos os campos publicacao e edicao, que devem ser transferidos para a tabela publicacao, mas que não fora feito para apenas estender o exemplo do livro.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
95
Desenvolvendo Aplicações Web com NetBeans IDE 6 Utilizando o NetBeans para inst ruções SQL No NetBeans, para executar o script da Listagem 1 , siga os passos descritos a seguir: 1. Tenha conectado seu banco de dados, como descrito no livro através do Capítulo 4 em “Se conectando ao banco de dados ”; 2. Com o direito do mouse sobre Tables>Execute Command , digite o script das tabelas na janela SQL Command 1 e clique no botão Run SQL(Ctrl+Shift+E) (veja detalhes na Figura 4.9 do livro); 3. Verifique a saída na janela Output>SQL Command 1 Execution ; 4. Para exibir as tabelas criadas, vá em Services>“selecione a sua conexão” >Tables e, com o direito do mouse, selecione Refresh no menu de contexto. Atenção: Adicione o driver JDBC do MySQL ao projeto.
Adicionando novas páginas do administrador A página responsável pelo cadastro de editoras é o mais simples, portanto será apresentada inicialmente. Crie uma nova página Visual Web JSF Page chamada de Editora, dentro do diretório admin. A Figura 2 exibe como esta será formada e no quadro “Componentes da página Editora” há uma descrição dos elementos que compõe a página.
Figura 2 – A página administrativa de cadastro de editoras Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
96
Desenvolvendo Aplicações Web com NetBeans IDE 6 Componentes da página Editora Siga estes passos para a página Editora, conforme visto na Figura 2: 1. Adicione um componente Page Fragment Box e selecione o menu do administrador. Posicione-o como os demais já feitos; 2. Arraste da janela Palette o componente Label para o Design da página. Posicione-o e digite Editora: (altere em text na janela Properties se necessário); 3. Arraste um componente Text Field, ao lado do rótulo inserido. Altere a propriedade id através de Properties para tfEditora; 4. Adicione o componente Button na página e altere em Properties a propriedade id para btSalvar e text para Salvar; 5. Para finalizar o formulário, adicione o componente Message Group logo abaixo do formulário; 6. Adicione um componente Table abaixo do formulário. Arraste da janela Services, através da tabela editoras (se não estiver aparecendo, clique com o direito sobre Tables, na sua conexão, e selecione Refresh). Com o direito sobre ela, selecione Table Layout . Altere as propriedades de Header Text das duas colunas e adicione duas novas, chamando uma de Excluir e Atualizar, alterando também em Value Expression neste caso. Nas duas colunas adicionadas, mude também a propriedade Component Type para Hyperlink. Se desejar, coloque paginação; 7. No Design, selecione o link Excluir da tabela adicionada e em Properties altere o id para excluir. Faça o mesmo para o link Atualizar modificando para atualizar; 8. Para finalizar o componente Table, vá à janela Properties e desça a rolagem até o item Advanced e marque a opção internalVirtualForm. Veja detalhes no Capítulo 8 a respeito.
O bean Editora
Assim como feito nos demais exemplos de cadastro criados no livro, para o cadastro de editora haverá um JavaBean específico. A Listagem 2 exibe o código deste bean: Listagem 2. O bean Editora public class EditoraBean { private RowKey rowKey; private String editora; public RowKey getRowKey() { return rowKey; } public void setRowKey(RowKey rowKey) { this.rowKey = rowKey; } public String getEditora() { return editora; } public void setEditora(String editora) { this.editora = editora; } }
A explicação da Listagem 2 é a mesma elaborada no livro, no Capítulo 8.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
97
Desenvolvendo Aplicações Web com NetBeans IDE 6 Os códigos do botão e dos links
Como já sabe, basta dar um duplo clique em cada elemento e definir seu código. A seguir você possui as listagens contendo os códigos de cada elemento: Listagem 3. O código do link Excluir do componente Table da página public String excluir_action() { try { //captura a linha atual do link de exclusão clicado
RowKey rowKey = tableRowGroup1.getRowKey(); if (rowKey != null) {
//atualiza o cache para iniciar a exclusão
editorasDataProvider.refresh();
//remove a linha existente no objeto editorasDataProvider
editorasDataProvider.removeRow(rowKey); //reflete esta ação no banco de dados
editorasDataProvider.commitChanges();
//atualiza o cache para exibir no componente Table
editorasDataProvider.refresh(); } //limpa os campos existentes
tfEditora.setText(null);
//torna nulo o valor de rowkey em EditoraBean
getSessionBean1().getEditoraBean().setRowKey(null); //informa ao administrador a exclusão
info("Editora excluída!");
} catch (Exception ex) { editorasDataProvider.revertChanges(); editorasDataProvider.refresh(); error("Erro encontrado: " + ex); } //retorna nulo pois não muda a página
}
return null;
Listagem 4. O código do link Atualizar do componente Table da página public String atualizar_action() { try { //leva para o bean EditoraBean os valores existentes //nas linhas adicionadas
editoraBean = getSessionBean1().getEditoraBean(); // captura a linha atual do componente Table
TableRowDataProvider rowData = (TableRowDataProvider) getBean("currentRow"); // adiciona os valores dos campos e principalmente o RowKey // no Bean EditoraBean
editoraBean.setRowKey(rowData.getTableRow()); editoraBean.setEditora((String) rowData.getValue("editoras.editora")); } catch (Exception ex) { //informa o erro caso ocorra ao administrador
}
error("Erro encontrado: " + ex);
//retorna nulo pois não muda a página
}
return null;
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
98
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 5. O código do botão Salvar do formulário da página public String btSalvar_action() { try { RowKey rowKey = getSessionBean1().getEditoraBean().getRowKey(); String mensagem; if (rowKey == null) { //prepara uma nova linha para inserção de dados
rowKey = editorasDataProvider.appendRow();
mensagem = "Adicionado com sucesso!"; } else {
//atualiza o cache para iniciar a atualização
}
editorasDataProvider.refresh(); mensagem = "Atualizado com sucesso!";
//captura o valor do componente no formulário //e o atribui a seu determinado campo no banco de dados
editorasDataProvider.setValue("editoras.editora", rowKey , tfEditora.getText()); //grava as informações no banco de dados
editorasDataProvider.commitChanges(); //limpa os campos existentes
tfEditora.setText(null);
//torna nulo o valor de rowkey em EditoraBean
getSessionBean1().getEditoraBean().setRowKey(null); //informa ao administrador o cadastro efetuado
error("Não foi possível adicionar" + ex.getMessage()); editorasDataProvider.revertChanges();
//retorna nulo pois não muda a página
}
return null;
As Listagem 3, 4 e 5 exibem cada um dos componentes que terão seu comportamento determinado por suas ações, conforme já visto em outros cadastros feitos no livro. Portanto, a explicação será omitida. Alterando o método prerender()
Como já visto no livro, através do Capítulo 8, o método callback prerender() será alterado para preencher o Text Field tfEditora para que este exiba o texto do nome da editora selecionado através do componente Table da página. Listagem 6. O código do método Callback prerender() da página public void prerender() { //verifica se RowKey não é nulo
Ao longo das listagens, fora utilizado uma variável editoraBean, que deve ser declarada como mostrado a seguir, no código da página: EditoraBean editoraBean = new EditoraBean();
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
99
Desenvolvendo Aplicações Web com NetBeans IDE 6 A página de criar publicações A página de publicações possui um aspecto diferente das páginas já criadas. Seu propósito é ligar uma Editora a um determinado Livro. Para escolher as editoras, você utilizará um componente Drop Down List , que exibirá todas as editoras cadastradas e enviará o valor chaves da selecionada para o cadastro. O livro selecionado será armazenado em um campo oculto, que será incluído na página através do componente Hidden Field. Crie uma página Visual Web JSF Page chamada de Publicar. Adicione os componentes exibidos na Figura 3, incluindo o componente Drop Down List .
Figura 3 – Aparência da página Publicar
A Tabela 1 mostra os componentes que terão suas propriedades alteradas. Tabela 1 – Alteração das propriedades dos componentes do formulário da página
Componente Static Text Label Drop Down List Button Hidden Field*
Propriedade text text id text id id
Valor Editoras Cadastradas Editoras: editoras Publicar btPublicar id
* Para alterar as propriedades do componente Hidden Field, cuja aparência não é exibida no design da página, selecione-o através da janela Navigator (veja número 2 na Figura 3). Configurando o componente Drop Down List editoras
Arraste Services>Tables>editoras para a página. O Visual Web JSF irá questioná-lo, através da caixa de diálogo Add New Data Provider with RowSet for Table editoras . Esta caixa de diálogo está reconhecendo que já há em SessionBean1 um RowSet para editoras, selecionando já todos os Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
100
Desenvolvendo Aplicações Web com NetBeans IDE 6 dados desta tabela. Como vamos usar o mesmo para exibir no componente Drop Down List , mantenha a opção Use, que foi sugerida, selecionada e confirme.
Figura 4 – Adicionando um novo data provider
Clique com o direito do mouse sobre o componente Drop Down List editoras e selecione, no menu de contexto, o item Bind to Data (veja Figura 5).
Figura 5 – Selecionando Bind to Data no menu de contexto
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
101
Desenvolvendo Aplicações Web com NetBeans IDE 6 Na caixa de diálogo Bind to Data, selecione a guia Bind to Data Provider . Em Choose a Data Provider to bind to editoras o item editorasDataProvider. Automaticamente o Visual Web JSF selecionará em Value field o campo chave, que no caso será editoras.id e em Display field o item editoras.editora. Caso isso não ocorra, deverá ser selecionado manualmente.
Figura 6 – Ligando o data provider ao componente Drop Down List editoras
Observando o diálogo (ver Figura 6), você deve ter concluído que serão exibidos os textos com os nomes das editoras e, o item selecionado transmitido para ser salvo, será o valor do código chave. Arrastando a tabela publicacao para a página
Como os dados envolvidos no formulário desta página serão salvos na tabela publicacao, arraste-a para a página (SEM ser sobre quaisquer componentes exibidos). Verifique que em Navigator agora há o Data Provider chamado publicacaoDataProvider dentro do nó de Publicar. Adicionando código ao botão Publicar
Dê um duplo clique no componente Button btPublicar e adicione o código da Listagem 7. Listagem 7. O código do botão btPublicar do formulário da página public String btPublicar_action() { try { //prepara uma nova linha para inserção de dados
RowKey rowKey = publicacaoDataProvider.appendRow(); //captura os valores de cada componente no formulário //e os atribui a seus determinados campos no banco de dados
publicacaoDataProvider.setValue("publicacao.livro_id", rowKey, id.getText()); publicacaoDataProvider.setValue("publicacao.editora_id", rowKey, editoras.getValue()); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
102
Desenvolvendo Aplicações Web com NetBeans IDE 6 //grava as informações no banco de dados
publicacaoDataProvider.commitChanges();
//retorna a seguinte string em caso de sucesso
return "publicado";
} catch (Exception e) { //em caso de erro, exibe ao usuário
error("Erro: " + e.getMessage());
//reverte alterações feitas no data provider
publicacaoDataProvider.revertChanges();
} //retorna nulo em caso de erro, não mudando de página
}
return null;
Observando a Listagem 7, percebemos que a captura do valor de um componente Hidden Field é similar ao Text Field, através do método getText(). Para o componente Drop Down List editoras, utilizamos o método getValue() para capturar o valor selecionado. Ao realizar com sucesso, este botão retorna a string “publicar”, o que indica que o usuário será direcionado a outra página. Adicionando código a página
Continuando no código, você deverá alterar algumas partes para que possa executar certas ações que caracterização o seu uso. A Listagem 8 exibe o que será alterado. Listagem 8. Alterações do código da página //...omitido por não ser alterado
public void prerender() { //captura a variavel GET titulo
this.setTitulo((String) getExternalContext(). getRequestParameterMap().get("titulo")); } //...omitido por não ser alterado
private String livid; public String getLivid() { return livid; } public void setLivid(String livid) { this.livid = livid; } private String titulo; public String getTitulo() { return titulo; } public void setTitulo(String titulo) { this.titulo = titulo; } //...omitido por não ser alterado
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
103
Desenvolvendo Aplicações Web com NetBeans IDE 6 No código do método prerender() exibido na Listagem 8, exibe um novo método não utilizado até o momento. Através de getExternalContext() , você tem acesso ao método getRequestParameterMap(), que possibilita, através de get(), capturar o valor de uma variável transmitida pelo método GET. Isso significa que transmitiremos uma variável pelo cabeçalho HTTP da página (barra de endereços) chamada de “ titulo”. Esta variável será capturada e utilizada pela página. Veja mais adiante a explicação do que será transmitido. A segunda forma de receber dados pelo método GET através de uma página criada pelo Visual Web JSF é similar ao utilizado pelo JavaServer Faces, utilizando getters e setters. Como exemplo, a variável livid será utilizada para este fim. Configurando o Hidden Field id e o título da página
Volte ao Design da página. Selecione na janela Navigator a página Publicar. Vá à janela Properties e clique no botão com três pontos em Title. Altere como mostrado no trecho a seguir, na caixa de diálogo Title:
Publicar livro #{admin$Publicar.titulo} Seu exemplo deverá ser similar ao da Figura 7.
Figura 7 – Alteração da propriedade Title da página
Faça o mesmo com o campo oculto (Hidden Field) id. Selecione-o através da janela Navigator e na propriedade text clique no botão de três pontos. Em Use bind, selecione Bind to an Object e expanda admin/Publicar. Selecione livid e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
104
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 8 – Bind para a variável livid Transmitindo via método GET
Abra a página Livro.jsp, de admin, e adicione uma nova coluna ao componente Table da página. Esta nova coluna terá um Hyperlink como tipo de componente ( Component Type ). Em Header Text digite Publicação e em Value Expression digite Gerar. Veja os detalhes na Figura 9.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
105
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 9 – A nova coluna chamada de Publicação
Selecione o link Gerar, em destaque na Figura 10, e vá até suas propriedades. Dê um clique no botão de três pontos na propriedade url.
Figura 10 – A coluna Publicação e seu link Gerar
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
106
Desenvolvendo Aplicações Web com NetBeans IDE 6 Digite em URL, mantendo Use value, como mostrado a seguir: /admin/Publicar.faces?livid =#{currentRow.value['livros.id']} &titulo=#{currentRow.value['l ivros.titulo']}
O que será transmitido via URL foi colorido da seguinte forma: Em vermelho – temos as variáveis que serão transmitidas; Em azul – temos os valores destas variáveis, que correspondem a valores das colunas do banco de dados; Em verde – a concatenação para envio de mais de uma variável, o que ocorre no caso. • •
•
Figura 11 - Alteração no campo URL de Gerar Configurando faces-config.xml para trabalhar com GET
Para capturar um valor transmitido pelo método GET no JavaServer Faces, utilizamos o , que deve possuir em seu valor a expressão #{param.VARIAVEL} . Veja na Listagem 9 como ficará a alteração feita no arquivo faces-config.xml: Listagem 9. Alteração em faces-config.xml para a página Publicar admin$Publicarbr.com.integrator.admin.Publicarrequest
livid #{param.livid}
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
107
Desenvolvendo Aplicações Web com NetBeans IDE 6 A página de publicações Crie uma nova página Visual Web JSF Page chamada de Publicados. Adicione os componentes da Figura 12 a seguir. Altere o componente Table como o quadro “ Exibindo as Publicações Cadastradas” descreve.
Figura 12 – Design da página Publicados
Exibindo as Publicações Cadastradas Siga estes passos para o componente Table da página Publicados, conforme visto na Figura 12: 1. Arraste de Services>SUA CONEXAO>Tables a tabela publicacao para a página ( NÃO faça sobre o componente Table); 2. Assim como já ocorrido em caso anterior, o Visual Web JSF irá questioná-lo, através da caixa de diálogo Add New Data Provider with RowSet for Table publicacao . Selecione desta vez a opção Create em admin/Publicados e confirme; 3. Expanda o nó de Publicados, na janela Navigator, e dê um duplo clique em publicacaoRowSet; 4. Ao surgir o Design Query, clique com o direito do mouse e selecione Add Table na parte superior da janela (veja detalhe na Figura 13). Adicione as tabelas editoras e livros; 5. Deixe marcado somente os campos para sua query: publicacao.id, editoras.editora e livros.titulo; 6. Volte à página Publicados, em Design, e com o direito do mouse sobre o componente Table, vá até Table Layout ; 7. Altere a ordem e os títulos em Header Text na seqüência: ID, Editora, Título; 8. Na guia Options digite no campo Title “ Publicações Cadastradas” e no campo Empty Data Message “ Não há publicações no Momento ”. Se desejar, marque Enable Pagination e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
108
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 13 – A query relacionada
Vinculando o livro a seus autores Diferente do link Gerar, que foi transmitido via método GET, o link que será criado agora transmitirá via método POST, mas sem usar uma sessão. Abra a classe RequestBean1 e adicione em seu final o trecho da Listagem 10. Listagem 10. Alteração na classe RequestBean1 //...
omitidos por não haver alterações
private String livid; public String getLivid() { return livid; } public void setLivid(String livid) { this.livid = livid; }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
109
Desenvolvendo Aplicações Web com NetBeans IDE 6 Alterando novamente a página Livro
Na página de cadastro de Livros ( Livro.jsp), adicione mais uma coluna no componente Table e mova antes da coluna de Publicações, deixando-a similar a Figura 14 mostrada a seguir:
Figura 14 – Nova coluna Autor na tabela da página Livros
Selecione o link Adicionar da coluna Autor, do componente Table, e altere a propriedade id para adicionar (Figura 15).
Figura 15 – Propriedade id alterada do link Adicionar do componente Table Adicionando código ao link Adicionar
Dê um duplo clique no link Adicionar, do componente Table, da página Livro e adicione o código mostrado a seguir na Listagem 11: Listagem 11. Código do link Adicionar public String adicionar_action() { //captura a linha atual do link de adição clicado
TableRowDataProvider rowData = (TableRowDataProvider) getBean("currentRow"); //o coloca no bean RequestBean1 para que possa transmitir //o valor para a página LivroAutor
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
110
Desenvolvendo Aplicações Web com NetBeans IDE 6 O código deste link simplesmente adicionará o ID do livro selecionado, no componente Table, a livid de RequestBean1, criado anteriormente para ser puxado pela página que irá vincular o autor ao livro. A página de adição de autor ao livro
Crie uma página similar a Figura 16, alterando as propriedades conforme a Tabela 2.
Figura 16 – Vinculando o livro aos autores Tabela 2 – Alteração das propriedades dos componentes do formulário da página
Componente Static Text Label Drop Down List Button
Propriedade text text id text id
Valor Vincular Autor ao Livro Autores: autores Adicionar ao Livro btAdLivro
Configurando o componente Drop Down List autores
Arraste Services>Tables>autores para a página. O Visual Web JSF irá questioná-lo, através da caixa de diálogo Add New Data Provider with RowSet for Table autores . Ao ser questionado quanto a criação do Data Provider, mantenha a opção Use, que foi sugerida, selecionada e confirme. Clique com o direito do mouse sobre o componente Drop Down List autores e selecione, no menu de contexto, o item Bind to Data (similar ao da Figura 5 em exemplo anterior). Na caixa de diálogo Bind to Data, selecione a guia Bind to Data Provider . Em Choose a Data Provider to bind to autores o item autoresDataProvider. Automaticamente o Visual Web JSF
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
111
Desenvolvendo Aplicações Web com NetBeans IDE 6 selecionará em Value field o campo chave, que no caso será autores.id e em Display field o item autores.nome. Caso isso não ocorra, deverá ser selecionado manualmente. Confirme.
Figura 17 – Bind to Data para o componente Drop Down Listo autores O código do botão do formulário
Dê um duplo clique no botão Adicionar ao Livro e adicione o código da Listagem 12. Listagem 12. Código do botão Adicionar ao Livro public String btAdLivro_action() { //capta o id do livro em getRequestBean1()
String livid = getRequestBean1().getLivid(); try { //prepara uma nova linha para inserção de dados
RowKey rowKey = livro_autorDataProvider.appendRow(); //captura os valores de cada componente no formulário //e os atribui a seus determinados campos no banco de dados
livro_autorDataProvider.setValue("livro_autor.livro_id", rowKey, livid ); livro_autorDataProvider.setValue("livro_autor.autor_id", rowKey, autores.getValue()); //grava as informações no banco de dados
livro_autorDataProvider.commitChanges(); //retorna a string publicado
return "publicado"; } catch (Exception e) { error("Erro: " + e.getMessage()); } //não vai a página alguma caso haja um erro
return null; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
112
Desenvolvendo Aplicações Web com NetBeans IDE 6 }
Similar ao criado para vincular um livro a uma publicação e sua respectiva editora, neste caso, a diferença fica por conta de não estarmos usando o envio dos dados via método GET, mas não colocando os dados em Sessão, como já fora feito em outros exemplos.
A página de autores publicados A última página Visual Web JSF Page a ser criada no administrador será AutoresPublicados. Sua aparência será similar a Figura 18. Altere o componente Table como o quadro “ Exibindo os Autores Publicados Publicados ” descreve.
Figura 18 – Design da página AutoresPublicados
Exibindo os Aut ores Publicados Publicados Siga estes passos para o componente Table da página Publicados, conforme visto na Figura 18: 1. Arraste de Services>SUA CONEXAO>Tables a tabela livro_autor para a página ( NÃO faça sobre o componente Table); 2. Expanda o nó de AutoresPublicados, na janela Navigator, e dê um duplo clique em livro_autorDataProvider; 3. Ao surgir o Design Query, clique com o direito do mouse e selecione Add Table na parte superior da janela. Adicione as tabelas autores e livros (veja o resultado final na Figura 19); 4. Deixe marcado somente os campos para sua query: autores.nome e livros.titulo; 5. Volte à página AutoresPublicados, em Design, e com o direito do mouse sobre o componente Table, vá até Table Layout ; 6. Deixe a ordem dos títulos em Header Text na seqüência: Título e Autor; 7. Na guia Options digite no campo Title “ Autores publicados” e no campo Empty Data Message “ Não há autores com livros cadastrados ”. Se desejar, marque Enable Pagination e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
113
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 19 – A query relacionada
A navegação em em faces faces-config.xml
Vá ao arquivo faces-config.xml e altere a navegação, arrastando do botão Adicionar ao Livro, da página LivroAutor, para a página criada (AutoresPublicados). A Listagem 13 exibe a navegação em detalhe no formato XML. Listagem 13. Navegação da página LivroAutor para para Aut oresPu or esPubl blic icado adoss ... admin$LivroAutor br.com.integrator.admin.LivroAutorrequest/admin/LivroAutor.jsppublicado/admin/AutoresPublicados.jsp
...
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
114
Desenvolvendo Aplicações Web com NetBeans IDE 6 Alterando o menu Adicione mais três links: Cadastrar Editoras , Publicações e Autores Publicados .
Figura 20 – Menu da área administrativa do d o site
Altere a propriedade id de cada um conforme deseja e altere para a string de retorno conforme mostrado em “Criando o relacionamento entre as páginas ”.
Criando o relacionamento entre as páginas Devido a inúmeros relacionamentos, neste estudo de caso, o arquivo faces-config.xml foi colocado na íntegra (Listagem 13), em seu formato original, XML, para que você possa acompanhar cada relação, caso tenha impresso este capítulo. É recomendáv r ecomendável el olhar o código fonte do projeto, contido também no CD-ROM, para melhor compreensão. compreensão. Listagem 13. Arquivo faces-config.xml SessionBean1br.com.integrator.SessionBean1sessionPage1br.com.integrator.Page1requestApplicationBean1br.com.integrator.ApplicationBean1applicationRequestBean1br.com.integrator.RequestBean1requestmenubr.com.integrator.menurequestadmin$Livrobr.com.integrator.admin.LivrorequestLivrosbr.com.integrator.Livros Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
115
Desenvolvendo Aplicações Web com NetBeans IDE 6 requestContatobr.com.integrator.Contatorequest/*pesquisar/Pesquisado.jsp/Page1.jspcontato/Contato.jsplivros/Livros.jspautores/Autores.jspadmin/Admin.jsp/Livros.jspcontato/Contato.jspautores/Autores.jspadmin/Admin.jsp/Contato.jsplivros/Livros.jspautores/Autores.jspadmin/Admin.jspAutoresbr.com.integrator.Autoresrequestadmin$menubr.com.integrator.admin.menurequestadmin$Autorbr.com.integrator.admin.Autor Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
116
Desenvolvendo Aplicações Web com NetBeans IDE 6 requestAdminbr.com.integrator.Adminrequest/Admin.jsplivros/Livros.jspautores/Autores.jspcontato/Contato.jsplogado/admin/Livro.jsp/admin/Autor.jsplogout/Admin.jspcadlivro/admin/Livro.jspcaded/admin/Editora.jspautpub/admin/AutoresPublicados.jsppubs/admin/Publicados.jsp/admin/Livro.jspcadautor/admin/Autor.jsplogout/Admin.jspcaded/admin/Editora.jsppubs/admin/Publicados.jspautpub/admin/AutoresPublicados.jspadlivroautor/admin/LivroAutor.jsp Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
117
Desenvolvendo Aplicações Web com NetBeans IDE 6
/Autores.jspadmin/Admin.jsplivros/Livros.jspbr.com.integrator.BundlePesquisadobr.com.integrator.Pesquisadorequest/Pesquisado.jsplivros/Livros.jspautores/Autores.jspadmin/Admin.jspcontato/Contato.jspBuscabr.com.integrator.Buscarequesttopobr.com.integrator.toporequestadmin$Editorabr.com.integrator.admin.Editorarequest/admin/Editora.jspcadlivro/admin/Livro.jsplogout/Admin.jspcadautor/admin/Autor.jsppubs/admin/Publicados.jspautpub/admin/AutoresPublicados.jsp Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
118
Desenvolvendo Aplicações Web com NetBeans IDE 6
admin$Publicarbr.com.integrator.admin.Publicarrequestlivid#{param.livid}admin$Publicadosbr.com.integrator.admin.Publicadosrequest/admin/Publicar.jsppublicado/admin/Publicados.jspcadlivro/admin/Livro.jspcadautor/admin/Autor.jsplogout/Admin.jspcaded/admin/Editora.jsppubs/admin/Publicados.jspautpub/admin/AutoresPublicados.jsp/admin/Publicados.jspcadlivro/admin/Livro.jsplogout/Admin.jspcadautor/admin/Autor.jspcaded/admin/Editora.jspautpub/admin/AutoresPublicados.jspadmin$LivroAutorbr.com.integrator.admin.LivroAutorrequest/admin/LivroAutor.jsppublicado/admin/AutoresPublicados.jsp Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
120
Desenvolvendo Aplicações Web com NetBeans IDE 6
Capítulo Extra 6 Estudo de caso completo com Visual Web JSF, Spring e Hibernate utilizando JPA
Este capítulo extra é uma versão do sistema criado nos Capítulos 7, 8 e estendidos no Capítulo Extra 5, só que criado utilizando Spring 2.5, Hibernate 3.2 e JPA (Java Persistence API), onde muitas explicações técnicas se encontram no Capítulo 10. As características da aplicação
O sistema segue o roteiro proposto pelo mesmo exemplo tido ao longo dos Capítulos 7, 8 e Extra 5, portanto, o design das páginas serão omitidos, sempre referindo a estes capítulos quando se tratar deste assunto. Neste capítulo será apresentado: A criação das entidades (POJOs); O trabalho com relacionamentos da JPA (One-To-Many, Many-To-One e Many-To-Many); A facilidade incorporada pelo Spring Framework; A facilitação do DAO Genérico criado para gerar o sistema; Utilização do pool C3P0 e cache de segundo nível com EhCache. • • • • •
Ao final deste capítulo, o leitor terá habilidade de trabalhar em sistemas complexos e completos utilizando as tecnologias relacionadas, incluindo o seu teor técnico para maiores detalhes.
O Projeto Crie um novo projeto Web Java e chame-o de DesComVWSpringJPAHibernate. Selecione o framework Visual Web JSF e altere seu pacote para br.com.integrator. Após a criação do projeto, adicione o suporte ao Spring Framework através do direito do mouse sobre Libraries, em Add Library>spring-framework-2.5>Add Library . O plugin que fora instalado possui as bibliotecas do Hibernate e do Spring, como já visto no Capítulo 10.
Atenção: Caso não tenha passado pelo livro, algumas bibliotecas podem estar faltando, portanto, confira os detalhes no capítulo 10 do seu livro.
As entidades e seus relacionamentos Como dito no Capítulo Extra 5, no decorrer do livro, duas tabelas foram utilizadas para o desenvolvimento da aplicação com Visual Web JSF. Agora, será necessário criar três novas tabelas, totalizando cinco: livros, autores, editoras, publicacao e livro_autor. As tabelas são ilustradas na Figura 1.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
121
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 1 – Modelo de dados do projeto
A Listagem 1, do Capítulo Extra 5, mostra o script para a criação das tabelas que serão adicionadas.
As entidades POJO Na Figura 2, observa-se o mapeamento de quatro objetos que relacionam-se as cinco tabelas encontradas no banco de dados. Para criá-las pelo NetBeans, siga os passos demonstrados no quadro “Criando Entidades Persistentes no NetBeans ”.
Figura 2 – Objetos a serem persistidos gerado por engenharia reversa do NetBeans IDE 6 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
122
Desenvolvendo Aplicações Web com NetBeans IDE 6 Criando entidades persist entes no NetBeans Siga estes passos para criar as entidades persistentes em seu projeto, para ficar em conformidade com o visto na Figura 2: 1. Com o direito do mouse sobre o projeto, selecione New>Entity Classes from Database ; 2. Na caixa de diálogo New Entity Classes from Database selecione crie um DataSource como já fora feito no Capítulo 10, em “Criando a Entidade Autor ”; 3. Selecione todas as tabelas do banco de dados livraria na segunda etapa e avance (veja Figura 3); 4. Na terceira etapa, altere o nome das classes em Class Name para o singular, seguindo o padrão de desenvolvimento. Altere o pacote digitando br.com.integrator.entities; 5. Clique no botão Create Persistence Unit e mantenha o Hibernate, dando um nome de livraria na Persistence Unit. Confirme tudo.
Figura 3 – Selecionando as tabelas para criar as entidades persistentes
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
123
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 4 – Criação das entidades e seu pacote
Atenção: Procure não se confundir neste capítulo. Se estiver falando do Capítulo 10, significa que a explicação está neste lugar. O mesmo vale para o Capítulo 8 e Extra 5. Este capítulo é uma mistura de ambos, onde no 8 e Extra 5 temos o layout proposto e no 10 a integração com Spring, Hibernate e JPA. Alterando as entidades
Embora o trabalho mais difícil seja feito pelo NetBeans IDE, altere as entidades criadas para como mostrado nas Listagens de 1 a 5, a seguir, onde serão omitidos as anotações @NamedQueries e os métodos getters e setters: Listagem 1. O código da entidade Usuario @Entity @Table(name = "usuarios") public class Usuario implements Serializable { private static final long serialVersionUID = 1L; @Id @Column(name = "id", nullable = false) private Integer id; @Column(name = "usuario") private String usuario; @Column(name = "senha") private String senha; //getters e setters omitidos
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
124
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 2. O código da entidade Livro @Entity @Table(name = "livros") public class Livro implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY ) @Column(name = "id", nullable = false) private Integer id; @Column(name = "titulo") private String titulo; @Column(name = "edicao") private Integer edicao; @Column(name = "publicacao") private Integer publicacao; @Column(name = "descricao") private String descricao; @Column(name = "imagem") private String imagem; ) @OneToMany (mappedBy = "livro", fetch = FetchType. LAZY private Collection publicacoes;
@ManyToMany (fetch=FetchType.LAZY, mappedBy = "livros") private Set autores; //getters e setters omitidos
Listagem 3. O código da entidade Autor @Entity @Table(name = "autores") public class Autor implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY ) @Column(name = "id", nullable = false) private Integer id; @Column(name = "nome") private String nome; @Column(name = "email") private String email; @Column(name = "nascimento") @Temporal(TemporalType.DATE ) private Date nascimento; @ManyToMany(cascade={CascadeType.MERGE ,CascadeType.PERSIST }) @JoinTable(name="livro_autor", joinColumns=@JoinColumn(name="autor_id"), inverseJoinColumns=@JoinColumn(name="livro_id")) private Set livros; //getters e setters omitidos
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
125
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 4. O código da entidade Editora @Entity @Table(name = "editoras") public class Editora implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY ) @Column(name = "id", nullable = false) private Integer id; @Column(name = "editora") private String editora; @OneToMany(mappedBy = "editora", fetch = FetchType.LAZY ) private Collection publicacoes; //getters e setters omitidos
Listagem 5. O código da entidade Publicacao @Entity @Table(name = "publicacao") public class Publicacao implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY ) @Column(name = "id", nullable = false) private Integer id; @JoinColumn(name = "editora_id", referencedColumnName = "id") @ManyToOne(fetch = FetchType. EAGER) private Editora editora; @JoinColumn(name = "livro_id", referencedColumnName = "id") @ManyToOne(fetch = FetchType. EAGER) private Livro livro; //getters e setters omitidos
Mapeamento objetos simples
O mapeamento mais simples, onde um objeto tem apenas tipos de dados básicos, que se entende por tipos básicos aqueles que possuem um correspondente na SQL, ou seja, o tipo String em Java é considerado os de campos de texto em seu correspondente SQL. Mapeamento de objetos com coleção de objetos
Esse mapeamento é usado quando um objeto possui um conjunto de outros objetos. Para entendê-lo, observe que temos na entidade Livro, uma coleção de publicacoes, por exemplo, que armazenará o conjunto de publicações. Em sua classe relacionada, através da entidade Publicacao, temos o atributo livro, que simplesmente relaciona um livro a sua publicação, enquanto que publicacoes, de Livro, referencia a classe Publicacao. Isso indica que podemos ter muitas publicações de um determinado livro. Ou melhor explicando, cada livro lançado pode ter sua determinada publicação e sua exclusão não afeta ao fato de existir um livro. Estes relacionamentos são:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
126
Desenvolvendo Aplicações Web com NetBeans IDE 6 •
•
One-To-Many (Um-Para-Muitos) – relacionamento da tabela livros (entidade Livro ) para a tabela publicacoes (entidade Publicacao ). Para este relacionamento utilizamos a anotação @OneToMany; Many-To-One (Muitos-Para-Um) – o inverso do relacionamento Um-Para-Muitos. Para este relacionamento utilizamos a anotação @ManyToOne;
A classe Livro, no exemplo, é a que possui um mapeamento do tipo Um-Para-Muitos (1-n) , através do atributo de coleção publicacoes. O seu mapeamento foi feito na Listagem 2 a partir da anotação @OneToMany. Como a coleção conterá objetos do tipo Publicacao, então está classe também deverá ser uma classe persistente da aplicação - observe que utilizamos generics para o tipo. Na anotação @OneToMany , existe um atributo denominado mappedBy que deverá receber como valor o nome do atributo encontrado na classe Publicacao (classe dos tipos de objetos da coleção). Ou seja, a tabela publicacao possui uma chave estrangeira (livro_id) para a tabela livros, que é representada pelo atributo de classe livro da entidade Publicacao, utilizado pelo atributo mappedBy da anotação @OneToMany, ou seja, mappedBy=“livro” . Já o atributo fetch indica quando o conteúdo do atributo será trazido da base de dados. Este por sua vez, possui dois valores: •
FetchType.EAGER : este valor indica que, se o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.EAGER fará com que o seu conteúdo também seja
trazido; •
FetchType.LAZY: este atributo indica que, se o objeto "pai" for trazido da base de dados, o atributo mapeado com fetch=FetchType.LAZY fará com que o seu conteúdo somente seja
trazido quando acessado pela primeira vez. Quando um relacionamento utiliza FetchType.LAZY, a consulta retorna apenas os dados referentes a livros, de forma que se fossem necessários os dados da coleção publicacoes, bastaria acessar o atributo que a representa no objeto Livro. A anotação @ManyToOne também possui o atributo fetch , que possui o mesmo comportamento de @OneToMany. Com a anotação @JoinColumn informamos qual o nome da coluna que corresponde à chave estrangeira do mapeamento, o que no caso deste exemplo, seria name=“livro_id” . O atributo referencedColumnName indica a coluna referenciada na tabela “pai” do banco de dados, que no caso em livros, seria o campo id. Já para o caso da tabela livro_autor, há um relacionamento Muitos-Para-Muitos. As das entidades Livro e Autor, ilustradas nas Listagens 2 e 3, respectivamente, possuem mapeamentos de coleções com o relacionamento Muitos-Para-Muitos (n-n), que é feito a partir da anotação @ManyToMany . O uso da anotação @JoinTable também se faz necessário para informar o nome da tabela intermediária entre as entidades. Esta anotação possui o atributo name que informa o nome da tabela intermediária que representa o mapeamento Muitos-Para-Muitos, no caso, a tabela livro_autor. O atributo joinColumns recebe como valor uma anotação @JoinColumn , informando o nome da coluna na tabela intermediária, que representa a classe onde está o mapeamento MuitosPara-Muitos. No atributo inverseJoinColumns é informado qual a coluna que representa a outra entidade no relacionamento. Na entidade Livro, para não haver a repetição das anotações utilizadas em Autor, basta adicionar o atributo mappedBy em @ManyToMany , ficando mappedBy= “livros” . Isso indica que na classe Autor há um atributo chamado livros que contém a informação mapeada. Esta condição também indica que Livro seria o lado “fraco” do relacionamento. O uso de Set para o tipo dos atributos livros e autores é para que não haja repetições. Nossa intenção é trabalhar da seguinte forma: Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
127
Desenvolvendo Aplicações Web com NetBeans IDE 6 Você pode ter muitos autores para um livro, na tabela livro_autor, mas só terá um livro para cada autor, em outras palavras, um livro pode ter sido escrito por muitos autores, mas estes não se repetem para cada livro, como: Edson Gonçalves, Edson Gonçalves escreveu Desenvolvendo aplicações Web com NetBeans 6 , ou seja, houve uma repetição desnecessária de dados que o Hibernate ignorará.
Utilizando o DAO genérico para criar outros No Capítulo 10 do livro, temos um DAO genérico que facilita o desenvolvimento de outros sem esforço adicional e repetição de código. Tanto a interface BaseDao como a classe que a implementa, BaseDaoImp, terão um método adicional, como mostrado nas Listagens 6 e 7. Listagem 6. A interface BaseDao alterada ...
public interface BaseDao { //..omitido por não haver alteração
public abstract Query pesq (String query); }
Listagem 7. A classe BaseDaoImp alterada ... public class BaseDaoImp implements BaseDao { //..omitido por não haver alteração
public Query pesq(String query) { return getEntityManager().createQuery(query); } }
Este método adicionado permitirá a execução de queries personalizadas, para os casos em que iremos utilizar mais de uma entidade. Os DAOs
Como definido no Capítulo 10 do livro, temos que criar os DAOs para trabalhar com as entidades desenvolvidas, estendendo a base. As Listagens de 8 a 17 mostram os DAOs que serão usados neste capítulo. Listagem 8. A interface EditoraDao package br.com.integrator.dao; import br.com.integrator.entities.Editora; public interface EditoraDao extends BaseDao{ }
Listagem 9. A classe EditoraDaoImp package br.com.integrator.dao; import br.com.integrator.entities.Editora; public class EditoraDaoImp
extends BaseDaoImp implements EditoraDao {
} Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
128
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 10. A interface LivroDao package br.com.integrator.dao; import br.com.integrator.entities.Livro; public interface LivroDao extends BaseDao{ }
Listagem 11. A classe LivroDaoImp package br.com.integrator.dao; import br.com.integrator.entities.Livro; public class LivroDaoImp
extends BaseDaoImp implements LivroDao {
}
Listagem 12. A interface PublicacaoDao package br.com.integrator.dao; import br.com.integrator.entities.Publicacao; public interface PublicacaoDao extends BaseDao{ }
Listagem 13. A classe PublicacaoDaoImp package br.com.integrator.dao; import br.com.integrator.entities.Publicacao; public class PublicacaoDaoImp implements PublicacaoDao {
extends BaseDaoImp
}
Listagem 14. A interface UsuarioDao package br.com.integrator.dao; import br.com.integrator.entities.Usuario; public interface UsuarioDao extends BaseDao{ }
Listagem 15. A classe UsuarioDaoImp package br.com.integrator.dao; import br.com.integrator.entities.Usuario; public class UsuarioDaoImp
extends BaseDaoImp implements UsuarioDao {
}
Listagem 16. A classe AutorDao package br.com.integrator.dao; import br.com.integrator.entities.Autor; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
129
Desenvolvendo Aplicações Web com NetBeans IDE 6 public interface AutorDao extends BaseDao{ }
Listagem 17. A classe AutorDaoImp package br.com.integrator.dao; import br.com.integrator.entities.Autor; public class AutorDaoImp
extends BaseDaoImp
implements AutorDao {
}
Configurando o Spring Com a criação dos DAOs, o Spring precisará ser configurado para que o acesso a dados se apóie nos recursos do framework. Com o direito sobre WEB-INF, em Projects, vá em New>Other. Na caixa de diálogo, vá em Spring Framework e selecione Spring Beans Context file . Na segunda etapa, altere para applicationContext em File Name. Na terceira etapa do assistente, selecione o Namespace exibido na Figura 5 e confirme.
Figura 5 – Seleção do namespace do arquivo de configuração do Spring Framework.
O assistente adicionará automaticamente o Namespace utilizado pelo Spring em seu arquivo de configuração. Resta configurar os beans que serão utilizados para que o Spring possa gerir as transações e informá-lo da classe que será usada para a injeção de dependências. Para a execução em ambientes Java EE, utilizamos a factory org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean : Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
130
Desenvolvendo Aplicações Web com NetBeans IDE 6 Com a propriedade de LocalContainerEntityManagerFactoryBean especificamos o nome da persistence unit do arquivo persistence.xml. Veja outros detalhes no Capítulo 10 . JpaTransactionManager precisa de qualquer implementação de javax.persistence.EntityManagerFact ory para colaborar com EntityManager produzido pela fabrica, para conduzir transações. O JpaTransactionManager é recomendado para aplicações que utilizam apenas uma EntityManager . Para que não tenhamos que fazer injeção de dependência do EntityManager em todos os nossos DAOs, utilizamos a classe org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor , que procura todas as classes anotadas com @PersistenceContext e faz a injeção de dependência automaticamente:
A Listagem 18 exibe o arquivo de configuração do Spring que será utilizado pela aplicação. Listagem 18. Configuração do arquivo applicationContext.xml .
Para iniciar o Spring com a aplicação, o arquivo applicationContext.xml deverá ser registrado por um listener em web.xml: org.springframework.web.context.ContextLoaderListener
Para trabalhar com a JPA, o Spring também fornece mais configurações. Ao trabalhar com relacionamentos para outras entidades, é importante entender que; como estamos trabalhando com o Hibernate, em alguns casos você utilizou a estratégia Lazy. Quando a aplicação termina de ler os dados desta estratégia, a sessão é fechada, lançando uma exceção do tipo LazyInitializationException . Isso significa que temos de deixar a sessão do Hibernate aberta ou inicializar todos os relacionamentos antes de renderizar a página. Evidentemente que, este tipo de situação por si só, causaria um problema de performance. Para evitá-la, no Hibernate, utilizamos um padrão chamado Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
131
Desenvolvendo Aplicações Web com NetBeans IDE 6 de "Open Session in View". Quando um servidor web recebe uma requisição, esta é automaticamente filtrada pelo Interceptador/Filtro, podendo executar qualquer código antes e depois da mesma. Embora o exemplo deste artigo não trate de relacionamentos, muito menos sobre a estratégia Lazy, é importante comentar que, no uso de JPA, teríamos que criar um padrão semelhante para EntityManager 2. O Spring possui um filtro que trabalha sobre este conceito, criando um padrão "Open EntityManager in View", que deve ser configurado em web.xml, conforme o trecho mostrado: openEntityManager org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
Para este capítulo, iremos utilizar o Filtro, como exemplo, onde na Listagem 19 é exibida toda a configuração que deve ser adicionada em web.xml. Listagem 19. Configurando o Spring Framework em web.xml .
Criando um teste unitário Para verificar se está funcionando os DAOs criados, é uma boa prática desenvolver um teste sobre as classes criadas. No Capítulo 4 você viu como fazer um teste unitário para uma classe que utilizava acesso a dados via JDBC. Neste capítulo, será um exemplo de como fazer testes usando o Spring Framework. Para executar este teste, vamos utilizar os recursos do Spring Framework na versão 2.5. Mas para isso, teremos que adicionar duas bibliotecas JARs: junit-4.4.jar e spring-teste.jar. Ambos os arquivos existem no download da biblioteca Spring com suas dependências.
2
A interface EntityManager é responsável pelas operações de persistência no EJB 3.0 e gerência de entidades persistentes (Entidades). Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
132
Desenvolvendo Aplicações Web com NetBeans IDE 6 Clique com o direito sobre Test Libraries, em seu projeto, e selecione no menu de contexto o item Add JAR/Folder . Selecione as duas bibliotecas citadas e confirme. Veja onde elas ficarão, na Figura 6.
Figura 6 – Adição das bibliotecas em Test Libraries
Listagem 20. Teste unitário usando o Spring Framework package br.com.integrator.test; import br.com.integrator.dao.UsuarioDao; import br.com.integrator.entities.Usuario; import java.util.List; import org.junit.Test; import static org.junit.Assert.*; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner. class) @ContextConfiguration(locations={ "classpath:**/applicationContext*.xml" }) public class UsuarioDAOTest {
private UsuarioDao usuarioDao; @Autowired public void setUsuarioDao (UsuarioDao usuarioDao) { this.usuarioDao = usuarioDao; } @Test public void addUsuario (){ Usuario usuario = new Usuario(); usuario.setId(1); usuario.setUsuario("integrator"); usuario.setSenha("integrator"); usuarioDao.save(usuario);
}
List users = usuarioDao.getAll("SELECT u FROM Usuario u"); assertEquals (1, users.size());
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
133
Desenvolvendo Aplicações Web com NetBeans IDE 6
@Test public void atuUsuario (){ Usuario usuario = usuarioDao.getById(1); usuario.setUsuario("edson"); usuarioDao.update(usuario); List users = }
@Test public void excUsuario (){ Usuario usuario = usuarioDao.getById(1); usuarioDao.delete(usuario); List users = }
usuarioDao.getAll("SELECT u FROM Usuario u");
assertEquals (0, users.size());
}
A Listagem 20 exibe um teste unitário utilizando as anotações do Spring Framework. Embora o NetBeans possua uma biblioteca JUnit em seu programa, infelizmente, para usar a anotação @RunWith, foi preciso adicionar a biblioteca compatível com a versão atual, no momento em que este livro é escrito, do Spring. Com a anotação @ContextConfiguration você define o nome do arquivo de configuração da aplicação feito para o uso do Spring, definindo seu nome através do atributo locations (que aceita um array para mais arquivos). Com a anotação @Autowired você tem a injeção do Spring e pode então criar seus testes unitários. Os detalhes dos métodos que podemos usar para testes podem ser vistos no Capítulo 4.
Figura 7 – Resultados do teste unitário
Você pode fazer outros testes com os demais DAOs criados.
Controlando o acesso Temos para o caso, diversos Facades que serão usados para controlar os DAOs criados e integrá-los a sua aplicação Visual Web JSF. As Listagens a seguir mostram as classes responsáveis pela lógica de negócios, delegando chamadas à camada de acesso a dados e controle transacional. Este controle de transações será administrado pelo Spring, através da injeção nos atributos que já foram configurados no arquivo applicationContext.xml : Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
134
Desenvolvendo Aplicações Web com NetBeans IDE 6
id="autorDao" ... id="editoraDao " ... id="usuarioDao " ... id=" publicacaoDao" ... id="livroDao" ...
Estas classes terão depois a injeção do Spring no managed bean para trabalhar com o JavaServer Faces. Para trabalhar com a entidade Autor, recorra ao livro, que já possui o Facade AutorController , ao qual aqui serão apenas apresentados os métodos adicionais a classe. Listagem 21. Métodos adicionais da classe AutorController //...omitido por não haver mudanças
public Autor pesquisarAutor (Long id) { return autorDao.getById(id); } public List todosAutorLivro () { return autorDao.pesq("SELECT a.id, a.nome, l.titulo " + "FROM Autor a JOIN a.livros l").getResultList(); }
Listagem 22. O código da classe UsuarioController package br.com.integrator.controller; import java.util.List; import br.com.integrator.dao.BaseDao; import br.com.integrator.entities.Usuario; import javax.persistence.Query; public class UsuarioController { /** * Injetado pelo Spring * @param usuarioDao */
private BaseDao usuarioDao; public BaseDao getUsuarioDao () { return usuarioDao; } public void setUsuarioDao (BaseDao UsuarioDao) { this.usuarioDao = UsuarioDao; } public void atualizar (Usuario Usuario) { usuarioDao.update(Usuario); } public void salvar(Usuario Usuario) { usuarioDao.save(Usuario); } public void excluir(Usuario Usuario) { usuarioDao.delete(Usuario); } public List todos() { return usuarioDao.getAll("SELECT u FROM Usuario u"); } public Usuario pesquisar(String usuario){ Query q = usuarioDao.pesq("SELECT u FROM Usuario u WHERE u.usuario=?1"); return (Usuario) q.setParameter(1, usuario).getSingleResult(); } } Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
135
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 23. O código da classe EditoraController package br.com.integrator.controller; import java.util.List; import br.com.integrator.dao.BaseDao; import br.com.integrator.entities.Editora; public class EditoraController { /** * Injetado pelo Spring * @param editoraDao */
private BaseDao editoraDao; public BaseDao getEditoraDao () { return editoraDao; } public void setEditoraDao (BaseDao EditoraDao) { this.editoraDao = EditoraDao; } public void atualizar (Editora Editora) { editoraDao.update(Editora); } public void salvar(Editora Editora) { editoraDao.save(Editora); } public void excluir(Editora Editora) { editoraDao.delete(Editora); }
}
public List todos() { return editoraDao.getAll("SELECT e FROM Editora e"); }
Listagem 24. O código da classe LivroController package br.com.integrator.controller; import java.util.List; import br.com.integrator.dao.BaseDao; import br.com.integrator.entities.Livro; import javax.persistence.Query; public class LivroController { /** * Injetado pelo Spring * @param livroDao */
private BaseDao livroDao; public BaseDao getLivroDao() { return livroDao; } public void setLivroDao (BaseDao LivroDao) { this.livroDao = LivroDao; } public void atualizar (Livro Livro) { livroDao.update(Livro); } public void salvar(Livro Livro) { livroDao.save(Livro); } public void excluir(Livro Livro) { Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
136
Desenvolvendo Aplicações Web com NetBeans IDE 6 }
livroDao.delete(Livro);
public List todos() { return livroDao.getAll("SELECT l FROM Livro l"); } public List pesquisar(String titulo){ Query q = livroDao.pesq("SELECT l FROM Livro l WHERE l.titulo LIKE ?1"); return q.setParameter(1, "%"+titulo+"%").getResultList(); } public Livro pesquisarLivro(Integer id) { return livroDao.getById(id); } }
Listagem 25. O código da classe PublicacaoController package br.com.integrator.controller; import java.util.List; import br.com.integrator.dao.BaseDao; import br.com.integrator.entities.Publicacao; public class PublicacaoController { /** * Injetado pelo Spring * @param publicacaoDao */
private BaseDao publicacaoDao; public BaseDao getPublicacaoDao () { return publicacaoDao; } public void setPublicacaoDao (BaseDao PublicacaoDao) { this.publicacaoDao = PublicacaoDao; } public void atualizar (Publicacao Publicacao) { publicacaoDao.update(Publicacao); } public void salvar(Publicacao Publicacao) { publicacaoDao.save(Publicacao); } public void excluir(Publicacao Publicacao) { publicacaoDao.delete(Publicacao); } public List todasPublicacoes () { return publicacaoDao.pesq("SELECT p.id, l.titulo, e.editora FROM " + "Publicacao p JOIN p.editora e " + "JOIN p.livro l").getResultList(); } public List todosLivroAutorPub () { return publicacaoDao.pesq("SELECT p.id, l.titulo, e.editora, a.nome FROM " + "Publicacao p JOIN p.editora e " + "JOIN p.livro l JOIN l.autores a").getResultList(); } }
Estas classes dispensam apresentação, uma vez que trabalham com seus respectivos DAOs para criar os CRUDs.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
137
Desenvolvendo Aplicações Web com NetBeans IDE 6 Integrando o Visual Web JSF ao Spring Para configurar o Spring de modo que ele possibilite se integrar ao JavaServer Faces, é necessário adicionar o elemento variable-resolver , no arquivo faces-config.xml, como fora feito no Capítulo 10 o livro, para chamar a classe DelegatingVariableResolver do do framework: org.springframework.web.jsf.DelegatingVariableResolver
A classe DelegatingVariableResolver é capaz de resolver beans declarados no Spring e injetá-los no managed bean de forma transparente. Esta injeção é indicada com a sintaxe #{bean nomeado no Spring} , a mesma utilizada pelo JSF para injetar dependências nos managed beans. Isso indica que nosso managed bean deixa de ser responsável por instanciar o objeto que irá utilizar e passa a recebê-lo do Spring. A Listagem 26 mostra os managed beans configurados em faces-config.xml. Listagem 26. Alterações no arquivo faces-config.xml //...omitido por não haver alterações
org.springframework.web.jsf.DelegatingVariableResolver UsuarioController UsuarioController br.com.integrator.controller.UsuarioController session sessionusuarioDao #{usuarioDao} LivroController LivroController br.com.integrator.controller.LivroController session sessionlivroDao #{livroDao} EditoraController EditoraController br.com.integrator.controller.EditoraController session sessioneditoraDao #{editoraDao} AutorController AutorController br.com.integrator.controller.AutorController session sessionautorDao Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
138
Desenvolvendo Aplicações Web com NetBeans IDE 6 #{autorDao} PublicacaoController PublicacaoController br.com.integrator.controller.PublicacaoController session session publicacaoD publicacaoDao ao #{publicacaoDao} ...
Atenção: Para detalhes quanto ao comportamento mostrado aqui, veja o Capítulo 10 .
Acessando o Facade pelo Visual Web JSF Para acessarmos as classes Facade criadas, e seus métodos através do Design do Visual Web JSF, será necessário configurar a classe SessionBean1, o padrão do Visual Web JSF é trafegar em um escopo de sessão. Listagem 27. Alterações na classe SessionBean1 //...omitido por não haver alterações por enquanto
private Integer private Integer id id = = null null; ; public Integer getId() { public Integer return id id; ; }
public void void setId(Integer setId(Integer id) { this. this .id id = = id; } private Livro[] private Livro[] livros livros; ; public Livro[] getLivros() { public Livro[] return livros livros; ; } public void void setLivros(Livro[] setLivros(Livro[] livros) { this. this .livros livros = = livros; } //carrega todos os livros public void void todosLivros() todosLivros() { livros = livros = (Livro[]) getLivroController(). todos().toArray(new Livro[0]); } private Editora[] private Editora[] editoras editoras; ; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
139
Desenvolvendo Aplicações Web com NetBeans IDE 6 public Editora[] getEditoras() { public Editora[] return editoras editoras; ; } public void void setEditoras(Editora[] setEditoras(Editora[] editoras) { this. this .editoras editoras = = editoras; } //carrega todas as editoras
public void void todasEditoras() todasEditoras() { editoras = editoras = (Editora[]) getEditoraController(). todos().toArray(new Editora[0]); } private Autor[] private Autor[] autores autores; ; public Autor[] getAutores() { public Autor[] return autores autores; ; } public void void setAutores(Autor[] setAutores(Autor[] autores) { this. this .autores autores = = autores; } //carrega todos os autores
Atenção: Termine fazendo Build no projeto, como recomendado no Capítulo 10 (veja as explicações de como funciona no livro em caso de dúvida).
Os arquivos persistence.xml e log4j.properties Altere o arquivo persistence.xml e crie o log4j.properties como feito no livro, através do Capítulo 10.
As páginas da aplicação As páginas da aplicação seguirão o Layout (design, componentes, propriedades dos componentes) mostradas nas montagens decorridas dos Capítulos 7, 8 e Extra 5.
Montando sua aplicação para utilizar Spring e Hibernate com JPA Seguindo um roteiro apresentado pelo Capítulo 8, iremos gradualmente trabalhar com a aplicação Visual Web JSF integrada com Spring e Hibernate através da JPA (diferente do CRUD elaborado no Capítulo 10 sobre este mesmo assunto). Crie uma página Visual Web JSF chamada Livros, como feito no início do Capítulo 8 do livro.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
140
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 8 – Tela inicial da página Livros
Vá até Table Layout e altere em Get Data From para livros. Deixe os campos para serem exibidos e os configure como no Capítulo 8, conforme a Figura 9.
Figura 9 – Definição dos campos do componente Table
Assim como apresentado no Capítulo 10, no desenvolvimento integrado com o Spring e JPA, o Visual Web JSF pega os valores do Array livros e possibilita manipulá-los visualmente. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
141
Desenvolvendo Aplicações Web com NetBeans IDE 6 Por fim, adicione no método prerender() a chamada ao método todosLivros() de SessionBean1: public void prerender() { getSessionBean1().todosLivros(); }
Nota: Não se preocupe com a navegação de páginas, pois esta será feita de uma forma mais simples para este estudo de caso.
A criação do cadastro de livros Na área administrativa, como feito no Capítulo 8, temos o cadastro de livros, dentro do diretório admin. Para este caso, a primeira diferença apenas no arquivo estará no nome, que deverá ser Livros e não Livro como no primeiro exemplo. Isso é necessário para evitar problemas quanto à classe da página, que possui seu mesmo nome, ficando idêntica a entidade Livro. Veja a Figura 10 para maior esclarecimento.
Figura 10 – Layout da página Livros de admin
Para este caso, será necessário criar apenas um formulário virtual para o link Editar. Os demais detalhes para a elaboração do design serão os mesmos. Para o componente Table será executado o mesmo passo que na elaboração da página para exibir os livros, com a diferença de acrescentarmos três links. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
142
Desenvolvendo Aplicações Web com NetBeans IDE 6 Detalhe da página Livros de admin
Abra a página Livros.jsp, de admin, e adicione uma nova coluna ao componente Table da página. Esta nova coluna terá um Hyperlink como tipo de componente ( Component Type ). Em Header Text digite Publicação e em Value Expression digite Gerar. Selecione o link Gerar, e vá até suas propriedades. Dê um clique no botão de três pontos na propriedade url. Digite em URL, mantendo Use value, como mostrado a seguir: /admin/Publicar.faces?livid =#{currentRow.value['livros.id']} &titulo=#{currentRow.value['l ivros.titulo']}
O que será transmitido via URL foi colorido da seguinte forma: Em vermelho – temos as variáveis que serão transmitidas; Em azul – temos os valores destas variáveis, que correspondem a valores das colunas do banco de dados; Em verde – a concatenação para envio de mais de uma variável, o que ocorre no caso. • •
•
Nota: Caso precise de detalhes visuais para entender este trecho, olhe no Capítulo Extra 5 . Criando o CRUD com a página
Como um CRUD já foi apresentado passo a passo no Capítulo 10, com suas devidas explicações, serão mostrados apenas os códigos de cada elemento a seguir. Listagem 28. Criação do método getLivroController() protected LivroController getLivroController() { return (LivroController) getBean("LivroController"); }
Listagem 29. Alterações no método prerender() public void prerender() { //verifica se id não é nulo
Integer id = getSessionBean1().getId(); if (id != null) { //capta os Livros
Livro[] livros = getSessionBean1().getLivros(); //filtra somente o selecionado para edição
//chama o método todosLivros() para refletir na tabela
getSessionBean1().todosLivros (); }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
143
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 30. Alterações no método do link Excluir public String excluir_action () { try { //captura a linha atual do link de exclusão clicado
RowKey rowKey = tableRowGroup1.getRowKey(); if (rowKey != null) {
Livro[] livros = getSessionBean1().getLivros(); Integer id = Integer.parseInt(rowKey.getRowId()); //seleciona somente o livro que será removido
Livro livro = livros[id];
//chama o controller para excluir o livro selecionado
getLivroController().excluir(livro);
//limpa o ID de SessionBean1 caso esteja com valor
getSessionBean1().setId(null); //limpa os campos existentes
Listagem 32. Alterações no método do botão Salvar public String btSalvar_action () { String imagem = null; //define o upload de arquivos através do componente File Upload
UploadedFile uploadedFile = fimagem.getUploadedFile(); if (!uploadedFile.getOriginalName().equals("")) {
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
144
Desenvolvendo Aplicações Web com NetBeans IDE 6 ServletContext theApplicationsServletContext = (ServletContext) this.getExternalContext().getContext(); //define o caminho físico do diretório images
String path = theApplicationsServletContext.getRealPath("/images"); //captura o nome original do arquivo
imagem = uploadedFile.getOriginalName(); //captura o tipo de arquivo
String uploadedFileType = uploadedFile.getContentType(); //verifica se o arquivo é uma imagem válida
if (uploadedFileType.equals("image/jpeg") || uploadedFileType.equals("image/pjpeg") || uploadedFileType.equals("image/gif")) { try { File file = new File(path + "/" + imagem); //escreve o arquivo no diretório determinado
uploadedFile.write(file);
} catch (Exception ex) { error("Problema com o arquivo: " + imagem); } } else { error("É aceito somente JPEG, PJPEG ou GIF."); }
}
try { String mensagem; Integer id = getSessionBean1().getId(); //se não houver algo em edição
if (id == null) {
Livro livro = new Livro(); //captura os valores de cada componente no formulário //e os atribui a seus determinados campos no banco de dados
livro.setTitulo(tftitulo.getText().toString()); livro.setEdicao((Integer) tfedicao.getText()); livro.setPublicacao((Integer) tfpublicacao.getText()); livro.setDescricao(tadescricao.getText().toString()); livro.setImagem(imagem); getLivroController().salvar(livro); info("Salvo com sucesso!"); } else { Livro[] livros = getSessionBean1().getLivros(); //seleciona somente o livro que será editado
Livro livro = livros[id];
//caso não haja novo upload da imagem //utiliza a antiga
if (uploadedFile.getOriginalName().equals("")) { imagem = livro.getImagem(); } //captura os valores de cada componente no formulário //e os atribui a seus determinados campos no banco de dados
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
145
Desenvolvendo Aplicações Web com NetBeans IDE 6 } //limpa os campos existentes
tftitulo.setText(null); tfedicao.setText(null); tfpublicacao.setText(null); tadescricao.setText(null); //torna nulo o valor de id
getSessionBean1().setId(null); } catch (Exception ex) { //informa o erro caso ocorra ao administrador
}
error("Não foi possível adicionar" + ex.getMessage());
//retorna nulo pois não muda a página
}
return null;
As demais páginas administrativas de cadastro simples Agora você criará mais duas páginas para cadastros CRUD: Editoras e Autores. Ambos seguirão um layout similar ao da página de Livros, tirando o fato de não haver imagens e upload de arquivos.
Figura 11 – Página de cadastro de Autores
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
146
Desenvolvendo Aplicações Web com NetBeans IDE 6 Para a página de cadastro de autores, você trabalhará com Autor e getAutores(). Para o cadastro de editoras, será Editora e getEditoras() . Em ambos os casos, serão necessários o uso de formulários virtuais para a chamada de edição de dados.
Figura 12 – Página de cadastro de Editoras
Observação: Os códigos das páginas Editoras e Autores serão omitidos deste capítulo, uma vez que podem ser encontrados nos arquivos fontes do projeto no livro, incluso no CD-ROM, e por possuem semelhanças entre suas operações.
Acessando a área administrativa Como feito no Capítulo 8, fora do diretório admin há uma página chamada Admin. Esta página é utilizada para se logar no sistema. Somente para relembrar, este login é guardado e fica operante através de um Servlet Filter, também criado no capítulo citado.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
147
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 13 – Área de entrada para a sessão administrativa
Para a elaboração deste exemplo, usamos na classe UsuarioController (Listagem 22) um método chamado de pesquisar() : public Usuario pesquisar(String usuario){ Query q = usuarioDao .pesq("SELECT u FROM Usuario u WHERE u.usuario=?1" ); return (Usuario) q.setParameter(1, usuario).getSingleResult(); }
Uma característica específica, herdada do JDBC, é o uso de parâmetros nas queries. Com algumas adições a query JPQL, o código da query ficou u.usuario=?1, onde o número 1 é um parâmetro. Lembra-se do parâmetro “?” usado em JDBC? O método setParameter() usado para transmitir o parâmetro para a consulta. Como o resultado deve ser somente uma linha, seu tipo é Usuario e o resultado é gerado pelo método getSingleResult() . As Listagens 33, 34 e 35 demonstram os códigos necessários para serem adicionados a classe Admin.java (que acompanha a página Admin). Listagem 33. Criação do método getUsuarioController() protected UsuarioController getUsuarioController () { return (UsuarioController) getBean("UsuarioController"); }
Listagem 34. Alterações no método prerender() public void prerender() { //exibe a mensagem caso o usuário tente entrar na área //administrativa sem se logar
FacesContext fc = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) fc.getExternalContext().getSession(false); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
148
Desenvolvendo Aplicações Web com NetBeans IDE 6 //captura a sessão msg
String msg = (String) session.getAttribute("msg"); //verifica se não é nula
if (msg != null) { error(msg); } //exibe ao usuário }
Listagem 35. Alterações no método do botão Logar public String logar_action () { try { //captura o login passado pelo campo usuario
Usuario u = getUsuarioController().pesquisar (tfUsuario.getText().toString()); //verifica se a senha está correta, evitando SQL Injection
if (tfSenha.getText().equals(u.getSenha())) { //captura a sessão do contexto criado //pelo JavaServer Faces do VW
FacesContext fc = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession) fc.getExternalContext().getSession(false); //cria uma sessão contendo o nome de usuario chamada logado
session.setAttribute("logado", tfUsuario.getText()); //caso a sessão msg esteja com valor, a remove
if (session.getAttribute("msg") != null) { session.removeAttribute("msg"); } //redireciona para a área administrativa
return "logado";
} else { error("Senha inválida"); } } catch (Exception ex) { //exibe a mensagem de login ou senha inválidos
}
error("Login ou senha inválidos");
//retorna nulo em caso de erro, não direcionando a página alguma
}
return null;
Observando na Listagem 35, temos a chamada ao método pesquisar() , de UsuarioController , que faz a pesquisa e retorna o objeto Usuario : Usuario u = getUsuarioController().pesquisar (tfUsuario.getText().toString());
Assim que retornado, para compará-lo a senha transmitida, temos a chamada de getSenha() de Usuario . if (tfSenha.getText().equals( u.getSenha())) { ...
As demais características, como criação da Session são similares ao usado na versão SQL.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
149
Desenvolvendo Aplicações Web com NetBeans IDE 6 A página de publicação Esta página em especial também possui características próprias, pois temos um componente Drop Down List. Este componente deve ser tratado especialmente pela aplicação para que seja possível exibir a lista de editoras cadastradas. Diferente do caso em SQL, ao qual temos as opções visíveis, neste caso, com o uso da JPA, você têm que criar seu preenchimento manualmente.
Figura 14 – Aparência da página Publicar
Na Listagem 36 você possui o conteúdo que será adicionado no método init() da classe SessionBean1 . Listagem 36. Alterações no método init() da classe SessionBean1 public void init() { // ... omitido por não ter sido alterado //cria um list de valores recebidos do método todos()
List editList = null; editList = getEditoraController(). todos(); //gera uma nova lista de opções
editoraOptions = new Option[editList.size()]; Iterator iter = editList.iterator(); //preenche a Drop Down List com os valores encontrados no banco de dados
for (int i = 0; iter.hasNext(); i++) { Editora editora = (Editora) iter.next(); Option opt = new Option("" + editora.getId(), editora.getEditora()); editoraOptions[i] = opt; } }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
150
Desenvolvendo Aplicações Web com NetBeans IDE 6 Através do método getEditoraController() você gera um List com o resultado do método todos(), e cria um novo objeto Option . Este objeto inicia com o tamanho da listagem que comportará: new Option[editList.size()];
E depois tem seus valores e rótulos preenchidos através de um loop que varre os dados e os separa em um novo objeto Option: for (int for ( int i i = 0; iter.hasNext(); iter.hasNext(); i++) { Editora editora = (Editora) iter.next(); Option opt = new new Option( Option("" "" + + editora.getId() ,editora.getEditora() ); editoraOptions [i] = opt; }
Observe que o objeto Option possui possui um construtor com dois parâmetros, parâmetros, recebendo no primeiro o ID que será transmitido e no segundo o rótulo que será exibido ao usuário. Separadamente você teria dois métodos ( setValue() e setLabel()), caso não recorresse ao construtor: Option opt = new new Option(); Option(); opt. setValue (editora.getId()); //o valor que de cada item opt. setLabel (editora.getEditora()); //o rótulo de cada item
Como não declaramos editoraOptions , vá ao assistente e o crie.
Figura 15 – Criando o atributo editoraOptions
Depois de criado, vá até ele e gere, com o direito do mouse, no menu de contexto os métodos get e set, através de Insert Code>Getter and Setter. O resultado é exibido na Figura 16 .
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
151
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 16 – Geração dos métodos get e set de editoraOptions Ligando o Drop Down List List editoras editoras a editoraOptions
Após as alterações, faça Build no projeto. Vá ao Design da página Publicar e clique com o direito sobre o componente Drop Down List editoras adicionado. Selecione no menu de contexto o item Bind to Data. Na caixa de diálogo (veja Figura 17), selecione em SessionBean1 o item editoraOptions .
Figura 17 – Seleção de editoraOptions Adicionando código ao botão Publicar
Dê um duplo clique no componente Button btPublicar e adicione o código da Listagem 37.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
152
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 37. O código do botão btPublicar do do formulário da página public String btPublicar_ public String btPublicar_actio action n () { try { try { //prepara uma nova linha para inserção de dados
Publicacao publicacao = new new Publicacao(); Publicacao(); Editora editora = new new Editora(); Editora(); Livro livro = new new Livro(); Livro();
//captura os valores de cada componente no formulário //e os atribui a seus determinados campos
editora.setId(Integer.parseInt(editoras.getValue().toString())); editora.setId(Integer.parseInt(editoras .getValue().toString())); livro.setId(Integer.parseInt(id livro.setId(Integer.parseInt( id.getText().toString())); .getText().toString())); publicacao.setLivro(livro); publicacao.setEditora(editora); //grava as informações no banco de dados
getPublicacaoController().salvar(publicacao); //redireciona a página
return "pubs" "pubs"; ;
} catch (Exception catch (Exception e) { error("Erro: error("Erro: " + e.getMessage()); } //retorna nulo em caso de erro
}
return null; null;
Como ocorrido no Capítulo Extra 5 , você captura os valores do campo oculto e também do Drop Down List e os grava na tabela publicacao. A diferença aqui está em como é feita esta operação. Enquanto que com acesso direto a dados é necessário apenas fazer uma referência a tabela, aqui, o responsável por salvar exige um objeto Publicacao . Este objeto precisa de dois objetos: Editora e Livro . Cada um destes dois objetos armazenará seu valor correspondente e em seguida será “envolvido” pelo objeto Publicacao , através de métodos setters. Por fim, a chamada ao método salvar(), de PublicacaoController , armazenará os dados. Adicionando código a página
Continuando no código, você deverá alterar algumas partes para que possa executar certas ações que caracterização o seu uso. A Listagem 38 exibe o que será alterado. Listagem 38. Alterações do código da página //...omitido por não ser alterado
public void prerender() prerender() { //captura a variavel GET titulo
this.setTitulo((String) this .setTitulo((String) getExternalContext(). getRequestParameterMap().get("titulo" getRequestParameterMap().get( "titulo")); )); } //...omitido por não ser alterado
private String livid livid; ; public String getLivid public String () () { return livid livid; ; } public void setLivid (String (String livid livid) ) { this. this .livid livid = = livid livid; ; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
153
Desenvolvendo Aplicações Web com NetBeans IDE 6 } private String private String titulo titulo; ; public String getTitulo () { public String return titulo titulo; ; } public void setTitulo (String titulo titulo) ) { this. this .titulo titulo = = titulo titulo; ; } //...omitido por não ser alterado
No código do método prerender() exibido na Listagem 38, exibe um novo método não utilizado até o momento. Através de getExternalContext() , você tem acesso ao método getRequestParameterMap(), que possibilita, através de get(), capturar o valor de uma variável transmitida pelo método GET. Isso significa que transmitiremos uma variável pelo cabeçalho HTTP da página (barra de endereços) chamada de “ titulo”. Esta variável será capturada e utilizada pela página. Veja mais mais adiante a explicação explicação do que será será transmitido. A segunda forma de receber dados pelo método GET através de uma página criada pelo Visual Web JSF é similar ao utilizado pelo JavaServer Faces, utilizando getters e setters. Como exemplo, a variável livid será utilizada para este fim. Configurando o Hidden Field Field id id e e o título da da página página
Volte ao Design da página. Selecione na janela Navigator a página Publicar. Vá à janela Properties e clique no botão com três pontos em Title. Altere como mostrado no trecho a seguir, na caixa de diálogo Title:
Publicar livro #{admin$Publicar.titulo} Seu exemplo deverá ser similar ao da Figura 18 .
Figura 18 – Alteração da propriedade Title da página
Faça o mesmo com o campo oculto (Hidden Field) id. Selecione-o através da janela Navigator e na propriedade text clique no botão de três pontos. Em Use bind, selecione Bind to an Object e expanda admin/Publicar. Selecione livid e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
154
Desenvolvendo Aplicações Web com NetBeans IDE 6 Configurando faces-config.xml para trabalhar com GET
Para capturar um valor transmitido pelo método GET no framework JavaServer Faces, utilizamos o , que deve possuir em seu valor a expressão #{param.VARIAVEL} . Veja na Listagem 39 como ficará a alteração feita no arquivo faces-config.xml: Listagem 39. Alteração em faces-config.xml para a página Publicar admin$Publicarbr.com.integrator.admin.Publicarrequest
livid #{param.livid}
A página de publicações Crie uma nova página Visual Web JSF Page chamada de Publicados. Adicione os componentes da Figura 19 a seguir.
Figura 19 – Design da página Publicados
Esta página também tem grandes diferenças com relação ao exemplo utilizado com SQL. Primeiro porque precisamos retornar objetos de diferentes entidades e estes precisam ter seus nomes reconhecidos pelo Visual Web JSF. Evidentemente, se estivéssemos trabalhando com JavaServer Faces “puro”, seria mais fácil. Como será preenchido o componente Table da página Publicados
O controller desenvolvido na Listagem 25 possui um método chamado de todasPublicacoes() . Este utiliza o método pesq(), em que você elabora uma query JPQL especial e determina qual seu resultado – tal como feito no caso da verificação de usuário. public List todasPublicacoes () { return publicacaoDao.pesq("SELECT p.id, l.titulo, e.editora FROM " + "Publicacao p JOIN p.editora e " + "JOIN p.livro l").getResultList() ; }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
155
Desenvolvendo Aplicações Web com NetBeans IDE 6 A diferença aqui é que não estamos passando um parâmetro e estamos no caso recuperando um List, através do método getResultList(). Observando a query elaborada, temos três campos que serão retornados de três tabelas diferentes, o que no caso será três atributos diferentes de três entidades que partem de Publicacao: SELECT p.id , l.titulo, e.editora FROM Publicacao p JOIN p.editora e JOIN p.livro l
O resultado deste List, é um conjunto de objetos de diferentes tipos. Somente para ilustrar, em um componente JavaServer Faces comum, recuperaríamos estes valores através de um array, sendo a primeira coluna #{item[0]} , a segunda #{item[1]} e etc. Porém, ocorre que não estamos utilizando JavaServer Faces e sim Visual Web JavaServer Faces, que utiliza um componente diferente para renderizar uma tabela, devido a sua capacidade visual integrada ao NetBeans. Criando um JavaBean especial
Para trabalhar visualmente, com o Visual Web JSF, no componente Table, precisamos determinar os tipos dos campos. Para fazer isso, vamos criar um bean. Crie uma nova classe no pacote br.com.integrator (crie outro pacote se preferir). Chame esta classe de PublicacoesBean . Listagem 40. O bean PublicacoesBean package br.com.integrator; import java.io.Serializable; public class PublicacoesBean implements Serializable{ private Integer id; private String titulo; private String editora; private String autor; public PublicacoesBean (Integer id, String titulo, String editora, String autor) { this.id = id; this.titulo = titulo; this.editora = editora; this.autor = autor; } public PublicacoesBean (Integer id, String titulo, String editora) { this.id = id; this.titulo = titulo; this.editora = editora; } public PublicacoesBean () { } public Integer getId () { return id; } public void setId (Integer id) { this.id = id; } public String getTitulo () { return titulo; } public void setTitulo (String titulo) { this.titulo = titulo; }
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
156
Desenvolvendo Aplicações Web com NetBeans IDE 6 public String getEditora () { return editora; } public void setEditora (String editora) { this.editora = editora; }
O bean desenvolvido possui atributos que unem informações que virão de diversas entidades. Seu propósito é organizar o array de objetos em somente um objeto com tipos bem definidos. Isso facilitará o seu uso pelo Visual Web. Alterando a classe SessionBean1 para utilizar o JavaBean
O componente Table agora precisará ter os seus dados sendo alimentados pela classe SessionBean1 . Altere a classe como mostra a Listagem 41 a seguir. Listagem 41. Alterações na classe SessionBean1 //...omitido por não haver alterações
private PublicacoesBean[] publicacoes; public PublicacoesBean[] getPublicacoes () { return publicacoes; } public void setPublicacoes (PublicacoesBean[] publicacoes) { this.publicacoes = publicacoes; } public void todasPublicacoes () { //cria um ArrayList para adicionar PublicacoesBean
ArrayList pubs = new ArrayList(); //pega o List retornado por todasPublicacoes()...
List todasPubs = getPublicacaoController(). todasPublicacoes (); //... separa em um loop for
for (Iterator iter = todasPubs.iterator(); iter.hasNext();) { Object[] o = (Object[]) iter.next(); //e adiciona no ArrayList os novos objetos preenchidos PublicacoesBean
}
pubs.add( new PublicacoesBean((Integer) o[0], (String) o[1], (String) o[2]));
//depois cria um array de PublicacoesBean do ArrayList //isso o torna acessível pelo componente Table
O que será feito é bem simples. Você está adicionando um array de PublicacoesBean . Esse array será preenchido com valores alimentados pelo resultado do método todasPublicacoes() de Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
157
Desenvolvendo Aplicações Web com NetBeans IDE 6 PublicacaoController . Como sabe, este devolve objetos, que serão separados através de um loop for e depois adicionados em um ArrayList através de novos objetos PublicacoesBean : for (Iterator iter = todasPubs.iterator(); iter.hasNext();) { Object[] o = (Object[]) iter.next(); pubs.add(new PublicacoesBean((Integer) o[0], (String) o[1], (String) o[2])); }
Por fim, este ArrayList é transformado em array de objetos PublicacoesBean : publicacoes = (PublicacoesBean[]) pubs.toArray( new PublicacoesBean[0]);
Novamente, será necessário o Build para depois ser reconhecido pelo Design das páginas. Alterando Publicados
Na classe Publicados.java (da página Publicados), será necessário adicionar no método prerender() a chamada ao método todasPublicacoes() criado em SessionBean1 . Esta alteração fará com que seja executado o método quando a página for chamada, antes de ser renderizada, alimentando o componente Table. A Listagem 42 exibe esta adição. Listagem 42. Alterações do método prerender() public void prerender() { getSessionBean1().todasPublicacoes (); }
Voltando ao Design, é hora de adicionar as colunas ao componente Table. Vá em Table Layout e selecione publicacoes em Get Data From. Selecione os campos mostrados na Figura 20 e crie uma nova coluna. Nesta coluna, digite Excluir em Header Text e Value Expression, selecione Hyperlink em Component Type e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
158
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 20 – Table Layout do componente Table de Publicacoes
Selecione o link Excluir, do componente Table, e dê a ele o id excluir em Properties. Dê um duplo clique sobre este link e altere seu método como mostrado na Listagem 43. Listagem 43. Alterações em Publicacoes.java protected PublicacaoController getPublicacaoController () { return (PublicacaoController) getBean("PublicacaoController"); } public String excluir_action () { try { //captura a linha atual do link de exclusão clicado
RowKey rowKey = tableRowGroup1.getRowKey(); if (rowKey != null) { PublicacoesBean[] pubs = getSessionBean1().getPublicacoes(); Integer id = Integer.parseInt(rowKey.getRowId()); //seleciona somente o que será removido
PublicacoesBean pubean = pubs[id]; //cria a publicação
Publicacao publicacao = new Publicacao(); //envia o ID do que será excluído
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
159
Desenvolvendo Aplicações Web com NetBeans IDE 6
publicacao.setId(pubean.getId()); //chama o controller para excluir a editora selecionada
getPublicacaoController().excluir(publicacao); } //informa ao administrador a exclusão
info("Publicação excluída!"); } catch (Exception ex) { error("Erro encontrado: " + ex); } //retorna nulo pois não muda a página
}
return null;
Diferente do exemplo criado no Capítulo Extra 5 , neste caso, você está possibilitando a exclusão das publicações. Se necessário, retorne ao Design e adicione um componente Message Group para exibição das mensagens retornadas por uso desta operação.
Adicionando autores a livros A página mostrada na Figura 21 é a mesma criada no Capítulo Extra 5 , portanto será omitida sua montagem de componentes visuais.
Figura 21 – Vinculando o livro aos autores
Transportando o código do livro
Diferente do link Gerar, que foi transmitido via método GET, o link que será criado na página de cadastro de Livros transmitirá via método POST, usando sessão para simplificar. Na classe SessionBean1 temos, já pronto, um atributo chamado id, que está sendo exibido na Listagem 44 apenas para ilustração: Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
160
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 44. Alteração na classe SessionBean1 //...
trecho já criado na Listagem 25
private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; }
Alterando a classe LivroAutor.java
Coloque no código Java da sua página LivroAutor e altere o método prerender() (Listagem 45), crie o atributo autorOptions ( Listagem 46) e adicione uma chamada à classe AutorController (Listagem 47). Listagem 45. Alterações no método prerender() public void prerender() { List autorList = null; autorList = getAutorController ().todos(); autorOptions = new Option[autorList.size()]; Iterator iter = autorList.iterator(); for (int i = 0; iter.hasNext(); i++) { Autor autor = (Autor) iter.next(); Option opt = new Option("" + autor.getId(),autor.getNome()); }
autorOptions[i] = opt;
}
Listagem 46. Declaração do atributo autorOptions private Option[] autorOptions; public Option[] getAutorOptions () { return autorOptions; } public void setAutorOptions (Option[] autorOptions) { this.autorOptions = autorOptions; }
Listagem 47. Chamando a classe AutorController protected AutorController getAutorController () { return (AutorController) getBean("AutorController"); }
Retorne ao design e com o direito do mouse sobre o componente Drop Down List autores, selecione Bind to Data no menu de contexto. Na caixa de diálogo Bind to Data , expanda o item admin/LivroAutor, na guia Bind to an Object e selecione autorOptions. Confirme a caixa de diálogo.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
161
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 22 – Seleção de autorOptions
Diferente do que fora feito na página Publicar, neste caso você não colocou as opções do componente Drop Down List na classe SessionBean1 . Na realidade, nem o outro era necessário, a menos que você vá utilizar em outros locais, o recomendado é colocar na página em que irá desfrutar de seus benefícios. Alterando a página Livros
Na página de cadastro de Livros ( Livros.jsp), em admin, adicione mais uma coluna no componente Table, mova para antes da coluna de Publicações (veja na Figura 23).
Figura 23 – Nova coluna Autor na tabela da página Livros
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
162
Desenvolvendo Aplicações Web com NetBeans IDE 6 Selecione o link Adicionar da coluna Autor, do componente Table, e altere a propriedade id para adicionar (Figura 24).
Figura 24 – Propriedade id alterada do link Adicionar do componente Table
Adicionando código ao link Adicionar
Dê um duplo clique no link Adicionar, do componente Table, da página Livros (em admin) e adicione o código mostrado a seguir na Listagem 48: Listagem 48. Código do link Adicionar public String adicionar_action() { //captura a linha atual do link de adição clicado
TableRowDataProvider rowData = (TableRowDataProvider) getBean("currentRow"); //o coloca no bean SessionBean1 para que possa transmitir //o valor para a página LivroAutor
Livro[] livros = getSessionBean1().getLivros();
//seleciona somente o livro que será transmitido
Livro livro = livros[Integer.parseInt(rowData.getTableRow().getRowId())]; //transmite para SessionBean através de id
getSessionBean1().setId(livro.getId()); }
return "adlivroautor";
O código deste link simplesmente adicionará o ID do livro selecionado, no componente Table, a lid de SessionBean1, no qual irá vincular o autor ao livro.
Adicionando o autor a seu livro
Voltando a página LivroAutor.jsp, dê um duplo clique no botão Adicionar ao Livro e adicione o código da Listagem 49. Em seguida, adicione o apresentado pela Listagem 50.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
163
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 49. Código do botão Adicionar ao Livro public String btAdLivro_action () { Integer livid = getSessionBean1().getId(); try { Livro livro = new Livro(); Autor autor = new Autor(); //pesquisa o livro que sera adicionado em livro_autor
livro = getLivroController().pesquisarLivro(livid); Integer autorId = Integer.parseInt(autores.getValue().toString()); //busca o Autor ao qual pertencerá o livro
autor = getAutorController().pesquisarAutor(autorId); //Adiciona autor na coleção
livro.getAutores().add(autor); //adiciona o livro a coleção
autor.getLivros().add(livro); //grava as informações no banco de dados
getLivroController().salvar(livro); getAutorController().salvar(autor); //retorna a string autlivros
return "autlivros";
} catch (Exception e) { error("Erro: " + e.getMessage()); } //não vai a página alguma caso haja um erro return null; }
O exemplo apresentado pela Listagem 49 é com certeza um dos maiores problemas de quem está iniciando no desenvolvimento com Hibernate. Como temos um relacionamento Many-To-Many, já explicado no princípio deste capítulo, implica em tomarmos certos cuidados para que não ocorram problemas na hora de persistir os dados. Se observar, verá que foram feitas duas pesquisas resultando em duas coleções – Autor e Livro. Isso foi feito porque estamos usando um relacionamento bidirecional. Porém, vale lembrar que temos um atributo mappedBy na anotação da entidade Livro : @ManyToMany( mappedBy = "livros")
Estamos indicando ao Hibernate que devemos ter vários autores para um determinado livro, mas que não haverá repetição do mesmo autor para o mesmo livro. Se isso ocorrer, o Hibernate exclui a linha e a recria. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
164
Desenvolvendo Aplicações Web com NetBeans IDE 6 A maior questão a ser respondida aqui é: por que estamos fazendo uma pesquisa ao invés de simplesmente passar os valores e persisti-los? Há três estados possíveis para um objeto. O entendimento destes estados e as ações que os modificam, são muito importantes quando nos deparamos com algum problema: • •
•
Transient – O objeto está em memória, porém, não foi salvo ainda; Persistent – O objeto já está salvo, porém, em cache na EntityManager, mas pode ser que ainda não esteja no banco de dados; Detached – O objeto já persistido no banco de dados;
Como o atributo id de Autor está anotado com @GeneratedValue , o Hibernate percebe que há um id “setado” e imagina que provavelmente esse objeto já deve existir no banco de dados (ele é autoincrementado e por dedução, não é feito um select), o que o leva a gerar uma exceção ao usuário: org.hibernate.PersistentObjectException: br.com.integrator.entities.Autor
detached
entity
passed
to
persist:
Se não existir o id , a mesma exceção ocorrerá. O método persist() não aceita objetos “detached”, somente “transient” e “managed”. Esta exceção não ocorreria se o id não fosse @GeneratedValue , ou se utilizarmos o método find(), de EntityManager . Bom, como estamos usando a primeira opção, resta apenas a segunda para evitar esta exceção. Portanto, temos as duas pesquisas que resultam nos objetos que desejamos: livro = getLivroController().pesquisarLivro(livid); autor = getAutorController().pesquisarAutor(autorId);
Estes valores são colocados em coleção: livro.getAutores().add(autor); autor.getLivros().add(livro);
As mudanças feitas somente de um lado da associação não são persistidas. Isto significa que o Hibernate tem duas representações na memória para cada associação bidirecional, uma associação de Autor para Livro e outra de Livro para Autor. Os dados são persistidos então: getLivroController().salvar(livro); //Não será salvo getAutorController().salvar(autor); //Será salvo
Aqui, Livro é usado para salvar a representação em memória no banco de dados.
A página de autores publicados A última página Visual Web JSF Page a ser criada no administrador será AutoresPublicados. Sua aparência será similar a Figura 25.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
165
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 25 – Design da página AutoresPublicados Criando um JavaBean para AutoresPublicados
Novamente, para exibir visualmente dados vindos de mais de uma entidade, será necessário criar um JavaBean, concentrando seus respectivos tipos em um só lugar. Crie uma nova classe no seu pacote principal (br.com.integrator) e altere-a como apresentado na Listagem 51. Listagem 51. Código de AutoresLivroBean package br.com.integrator; public class AutoresLivroBean { private Integer id; private String autor; private String titulo; public AutoresLivroBean () { } public AutoresLivroBean (Integer id, String autor, String titulo) { this.id = id; this.autor = autor; this.titulo = titulo; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAutor() { return autor; } public void setAutor(String autor) { this.autor = autor; } public String getTitulo() { return titulo; } Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
166
Desenvolvendo Aplicações Web com NetBeans IDE 6 public void setTitulo(String titulo) { this.titulo = titulo; } }
Utilizando o JavaBean AutoresPublicados
Vá até a classe SessionBean1 e adicione o trecho mostrado na Listagem 52. Listagem 52. Trecho do código de SessionBean1 //... omitido por não haver alterações private AutoresLivroBean[] autoresLivro; public AutoresLivroBean[] getAutoresLivro () { return autoresLivro; } public void setAutoresLivro (AutoresLivroBean[] autoresLivro) { this.autoresLivro = autoresLivro; } public void todosAutoresLivros () { ArrayList autoresLivros = new ArrayList(); List autoresPub = getAutorController().todosAutorLivro(); for (Iterator iter = autoresPub.iterator(); iter.hasNext();) { Object[] o = (Object[]) iter.next(); autoresLivros.add( new AutoresLivroBean((Integer) o[0], (String) o[1], (String) o[2]) ); } autoresLivro = (AutoresLivroBean[]) autoresLivros.toArray(new AutoresLivroBean[0]); }
Este código segue a mesma regra do criado para exibir as publicações. A diferença está no bean que será usado e na pesquisa executada para que o mesmo seja preenchido e colocado em um array. Em AutorController , como foi mostrado anteriormente na Listagem 21, há um método chamado de todosAutorLivro() que retorna um List: public List todosAutorLivro () { return autorDao.pesq("SELECT a.id, a.nome, l.titulo " + "FROM Autor a JOIN a.livros l" ).getResultList(); }
Observe a query JPQL elaborada, ao qual temos o relacionamento Many-To-Many: SELECT a.id , a.nome, l.titulo FROM Autor a JOIN a.livros l
O resultado deste List, é um conjunto de objetos de diferentes tipos, o que explica o uso de um JavaBean novamente. Alterando AutoresPublicados
Na classe AutoresPublicados.java (da página AutoresPublicados), será necessário adicionar no método prerender() , como feito em exemplo anterior, na página Publicados , a chamada ao método todosAutoresLivros() criado em SessionBean1 . A Listagem 53 exibe esta adição. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
167
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 53. Alterações do método prerender() public void prerender() { getSessionBean1().todosAutoresLivros (); }
Voltando ao Design, é hora de adicionar as colunas ao componente Table. Altere o componente Table como o quadro “ Exibindo os Autores Publicados” descreve.
Exibindo os Aut ores Publicados Siga estes passos para o componente Table da página AutoresPublicados, conforme visto na Figura 25: 1. No Design, clique com o direito do mouse sobre o componente Table; 2. Selecione no menu de contexto o item Table Layout; 3. Ao surgir a caixa de diálogo Table Layout , selecione autoresLivro em Get Data From, na parte superior da janela. Deixe em Selected todos os campos (veja na Figura 26); 4. Deixe a ordem dos títulos em Header Text na seqüência: ID, Autor e Título; 5. Na guia Options digite no campo Title “ Autores e Livros” e no campo Empty Data Message “ Não há autores com livros cadastrados ”. Se desejar, marque Enable Pagination e confirme.
Figura 26 – Table Layout do componente Table de AutoresPublicados Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
168
Desenvolvendo Aplicações Web com NetBeans IDE 6 Pesquisando livros na página principal Exatamente como feito no livro, através do Capítulo 8, você irá implementar uma busca no site. Embora iremos utilizar outra forma de acesso aos dados, muitas coisas serão semelhantes. Para facilitar e não haver dúvidas será repetido os passos aqui. Adicionando Código a SessionBean1
A classe SessionBean1 será responsável por captar a string de pesquisa lançada pelo Text Field que existe no topo da página e transportará para a página Pesquisado.jsp . Abra a SessionBean1 e adicione um atributo chamado de pesquisado , e crie os métodos getters e setters, como mostra a Listagem 54 a seguir. Listagem 54. Alterações na classe SessionBean1 //... omitido por não haver alterações private String pesquisado=""; public String getPesquisado () { return pesquisado; } public void setPesquisado (String pesquisado) { if(pesquisado==null) pesquisado=""; this.pesquisado = pesquisado; }
Alterando o Page Fragment responsável pela pesquisa
Abra o arquivo topo.jspf e dê um duplo clique no botão btBuscar (ou o id que deu ao botão). Adicione o código mostrado na Listagem 55. Listagem 55. Código no botão Buscar de topo.jspf public String btBuscar_action () { //chama pesquisado em SessionBean1 e atribui o valor //digitado no Text Field busca getSessionBean1().setPesquisado((String)busca.getText());
}
//retorna a string pesquisar para chegar a página Pesquisado return "pesquisar";
No código, observe que foi chamado da classe SessionBean1 a variável pesquisado e transmitido para ela o valor digitado no Text Field busca (encontrado também em topo.jspf).
Alterando a página Pesquisado
Como feito no Capítulo Extra 5, em Pesquisado.java , será recebido o valor a ser pesquisado, encontrado em SessionBean1 , no qual utilizará o método pesquisar() de LivroController . Em Pesquisado , chame LivroController (Listagem 56) e depois vá até o método prerender() e adicione o código mostrado na Listagem 57.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
169
Desenvolvendo Aplicações Web com NetBeans IDE 6 Listagem 56 – Chamada de LivroController na classe Pesquisado protected LivroController getLivroController() { return (LivroController) getBean("LivroController"); }
Listagem 57 – Código do método prerender() na classe Pesquisado public void prerender() { //captura o valor pesquisado String pesquisado = getSessionBean1().getPesquisado(); //transporta para o método pesquisar() de LivroController //e atribui o resultado ao array livros livros = (Livro[]) getLivroController(). pesquisar(pesquisado).toArray(new Livro[0]); }
Como o método prerender() é chamado no início, antes da página ser renderizada, o valor pesquisado deve ser transferido para o método pesquisar() de LivroController e seu resultado deve ser atribuído a um array de objetos Livro (veja Listagem 58). Sua criação deverá ser feita em Pesquisado.java , o que não interfere no mesmo array existente em SessionBean1 . Listagem 58 – Criação do array livros na classe Pesquisado private Livro[] livros; public Livro[] getLivros () { return livros; } public void setLivros (Livro[] livros) { this.livros = livros; }
Retornando ao Design da página, execute os passos existentes no quadro “ Alterando o componente Table de Pesquisado ”.
Alterando o componente Table de Pesquisado Siga estes passos para o componente Table da página Pesquisado: 1. No Design, clique com o direito do mouse sobre o componente Table; 2. Selecione no menu de contexto o item Table Layout; 3. Ao surgir a caixa de diálogo Table Layout , selecione livros (Pesquisado) em Get Data From, na parte superior da janela. Deixe em Selected os campos mostrados na Figura 27; 4. Deixe a ordem dos títulos em Header Text na seqüência: Título, Edição, Publicação e Imagem; 5. Na guia Options digite no campo Title “ Resultados da Pesquisa Realizada ” e no campo Empty Data Message “ Não foram encontrados livros no nome pesquisado ”. Se desejar, marque Enable Pagination e confirme.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
170
Desenvolvendo Aplicações Web com NetBeans IDE 6
Figura 27 – Table Layout do componente Table de Pesquisado Formulários virtuais para a pesquisa
Um problema que este sistema de pesquisa possui é o fato de estar fora de um formulário, o que impede de criar um formulário virtual, já que é um fragmento de página e não uma página completa. Para páginas que possuem formulário, como de Contato e Admin, ao fazer uma busca um erro ocorrerá, onde haverá a validação dos campos destes formulários. Para evitá-los, tanto na página Contato.jsp como em Admin.jsp, você irá adicionar o formulário virtual manualmente, como mostrado na Listagem 59 seguir: Listagem 59 – Criação do array livros na classe Pesquisado ... org.springframework.web.jsf.DelegatingVariableResolver UsuarioController br.com.integrator.controller.UsuarioController sessionusuarioDao#{usuarioDao}LivroController br.com.integrator.controller.LivroController sessionlivroDao#{livroDao}EditoraController br.com.integrator.controller.EditoraController sessioneditoraDao#{editoraDao}AutorController br.com.integrator.controller.AutorController sessionautorDao#{autorDao}PublicacaoController br.com.integrator.controller.PublicacaoController sessionpublicacaoDao#{publicacaoDao}SessionBean1 Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
/admin/* cadliv/admin/Livros.jsp cadaut/admin/Autores.jsp caded/admin/Editoras.jsp pubs/admin/Publicados.jsp logout/Admin.jsp autlivros/admin/AutoresPublicados.jsp admin$Autoresbr.com.integrator.admin.Autoresrequestadmin$Publicadosbr.com.integrator.admin.Publicadosrequestadmin$Publicarbr.com.integrator.admin.Publicarrequestlivid#{param.livid}Livrosbr.com.integrator.Livrosrequestadmin$LivroAutorbr.com.integrator.admin.LivroAutorrequestadmin$AutoresPublicados br.com.integrator.admin.AutoresPublicados Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
Alterando os menus Para melhor esclarecimento, será mostrado nas Listagens 61 e 62 os menus da página principal e da área administrativa. Listagem 61. Os métodos dos links do menu Principal public String livros_action () { // navega para os livros cadastrados
}
return "livroscads";
public String autores_action () { // navega para os autores cadastrados
}
return "autores";
public String admin_action () { // navega para a página de login para o administrador
}
return "admin";
public String contato_action () { // navega para a página de contato
}
return "contato";
Listagem 62. Os métodos dos links do menu Administrativo public String cadaut_action () { //torna nulo o valor de id
}
getSessionBean1().setId(null); return "cadaut";
public String cadliv_action () { //torna nulo o valor de id
}
getSessionBean1().setId(null); return "cadliv";
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
177
Desenvolvendo Aplicações Web com NetBeans IDE 6 public String logout_action () { FacesContext fc = FacesContext.getCurrentInstance(); HttpSession session = (HttpSession) fc.getExternalContext().getSession(false); //expira a sessão
}
session.invalidate(); return "logout";
public String caded_action () { //torna nulo o valor de id
}
getSessionBean1().setId(null); return "caded";
public String publicacoes_action () { //torna nulo o valor de id
}
getSessionBean1().setId(null); return "pubs";
public String autpub_action () { //torna nulo o valor de id
Configurando um Pool para a conexão Podemos adicionar as configurações do arquivo persistence.xml , uma espécie de “pool” de conexões para o uso com o Hibernate, ao qual melhora o desempenho de nossa aplicação. Para o caso, será utilizado é o C3P0 (veja a Listagem 63 para mais detalhes).
Para configurar o c3p0, você deverá incluir a biblioteca c3p0-0.9.1.1.jar em sua aplicação. Este arquivo, com esta versão, está junto com as bibliotecas encontradas no Spring Framework 2.5. Para melhor compreender o que foi feito, há uma breve descrição dos novos elementos adicionados no arquivo, listados a seguir: • •
•
• •
•
hibernate.cache.provider_class - Configura a classe do provedor de cache; hibernate.c3p0.min_size - A quantidade mínima de conexões com o banco de dados do pool; hibernate.c3p0.max_size - A quantidade máxima de conexões com o banco de dados do pool; hibernate.c3p0.timeout - O tempo máximo de duração de um comando ao banco; hibernate.c3p0.max_statements - Número máximo de comandos simultâneos em execução; hibernate.c3p0.idle_test_period - Intervalo de tempo para que o pool teste se a conexão continua ativa;
O resultado final de seu arquivo persistence.xml, será similar ao da Listagem 63, mais adiante. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
178
Desenvolvendo Aplicações Web com NetBeans IDE 6 Trabalhando com cache de objetos Frameworks ORM como o Hibernate, se preocupam com o desempenho das aplicações, ao qual podemos contar com um esquema de cache de objetos, evitando idas desnecessárias ao banco de dados a cada consulta semelhante. Os caches de objetos, quando bem montados, podem tornar a aplicação ainda mais rápida do que a mesma aplicação feita com o uso direto de JDBC. Na JPA, e com o Hibernate, há um sistema de cache automático e não configurado de EntityManager, ao qual é conhecido como “ cache de primeiro nível ”. O cache de primeiro nível é um cache relacionado a uma única sessão (EntityManager) do Hibernate, onde esse cache garante que você vai acessar sempre os mesmos objetos dentro da mesma. Esse cache não tem nenhuma preocupação com performance, o seu objetivo é de apenas garantir a integridade das informações dentro de uma mesma sessão. Felizmente, possuímos uma alternativa de ter um “ cache de segundo nível ”, que é opcional e é o que nós veremos aqui. Para utilizar o cache de segundo nível, você deve levar em conta algumas considerações, onde uma das mais importantes é que, se houverem outras aplicações fazendo inserções e atualizações no mesmo banco de dados, ao qual o Hibernate está conectado, é melhor nem utilizar o cache, porque outra aplicação pode atualizar informações que podem não ser refletidas pelo Hibernate, uma vez que estas se encontram em cache. Um detalhe importante é que sua aplicação deve ter mais envolvimento com leituras do que com atualizações ou inserções de dados. Do contrário, o cache pode até mesmo diminuir a performance da aplicação. Como o objetivo do exemplo é mostrar na prática seu uso, vamos apenas levar em consideração que a aplicação será muito usada para leitura e, como foi concebido, não há níveis hierárquicos de administradores, o que indica ser um sistema pequeno e de poucas mudanças. Configurando o cache
O arquivo persistence.xml teve uma pequena alteração com relação ao mostrado pelo Capítulo 10 do livro, adicionando agora o cache de segundo nível com EhCache. Listagem 63. O arquivo persistence.xml org.hibernate.ejb.HibernatePersistence
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
179
Desenvolvendo Aplicações Web com NetBeans IDE 6
name="hibernate.c3p0.min_size" value="5" /> name="hibernate.c3p0.max_size" value="20" /> name="hibernate.c3p0.timeout" value="300" /> name="hibernate.c3p0.max_statements" value="50" /> name="hibernate.c3p0.idle_test_period" value="3000"/>
O EhCache
Hibernate tem alguns métodos úteis que podem ajudar a testar e afinar seu cache. Enquanto que EntityManager fornece um cache de primeiro nível, podemos adicionar um segundo nível a aplicação. Isso é possível através de hibernate.cache.use_second_level_cache, você obtém um cache de segundo nível. O EhCache é o framework padrão de cache do Hibernate. O plugin do Spring, utilizado no projeto, já o tem colocado em sua biblioteca. O que vamos fazer agora é configurá-lo. Listagem 64. O arquivo persistence.xml completo org.hibernate.ejb.HibernatePersistence
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
180
Desenvolvendo Aplicações Web com NetBeans IDE 6 value="read-write" />
Para trabalhar com o cache, é necessário configurar o arquivo persistence.xml, conforme a Listagem 64 completa apresenta.
Para habilitar o cache na aplicação, é necessário escolher uma implementação da interface CacheProvider e adicioná-la a configuração do Hibernate. A implementação usada é EhCacheProvider , uma implementação não-clusterizável(não deve ser utilizada em um ambiente de cluster) da interface CacheProvider para o Hibernate. Isso é indicado na seguinte linha:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
181
Desenvolvendo Aplicações Web com NetBeans IDE 6 O segundo nível de cache no projeto
Para configurar as propriedades do cache para a aplicação, é necessário adicionar o arquivo ehcache.xml no classpath da aplicação (veja a Figura 30). Crie o arquivo da Listagem 65: Listagem 65. O arquivo ehcache.xml completo
O arquivo de configuração do EhCache é simples, iniciando com o primeiro elemento , que contém a localização de onde deve ficar o arquivo que está utilizando o cache (se algum objeto não estiver sido guardado na memória). Neste elemento, você possui o atributo path, que pode indicar um diretório ou usar os seguintes valores: user.home – Este valor indica o diretório raiz do usuário; user.dir – Este valor indica o diretório corrente para aplicação; java.io.tmpdir – Este valor indica o diretório temporário pra a máquina virtual; • • •
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
182
Desenvolvendo Aplicações Web com NetBeans IDE 6 Olhando a Listagem 65, temos no elemento (que contém as informações específicas de cada região de cache), o atributo name que, neste caso, possui como nome do cache o nome completo da classe. Caso o nome do cache não seja encontrado, o cache padrão será utilizado. Este cache também é configurado no arquivo ehcache.xml com ao elemento . Os principais elementos utilizados são apresentados a seguir: maxElementsInMemory – Determina o número máximo de objetos que podem ficar armazenados em memória; eternal – Quando configurado com o valor true, significa que o cache nunca vai expirar; timeToIdleSeconds – O tempo em segundos que um objeto pode permanecer inutilizado no cache; timeToLiveSeconds – O tempo em segundos que um objeto pode ficar em cache; overflowToDisk – Quando configurado com o valor true e, caso o limite de objetos em memória, seja superior ao definido pela propriedade maxElementsInMemory, as informações serão armazenadas em disco. •
• •
• •
Figura 30 – Destaque para a localização do arquivo ehcache.xml
Em seguida, você deve adicionar a anotação do cache nas entidades que deseja colocar em segundo nível. Para isso, altere as entidades como mostra as Listagens de 66 a 70 a seguir: Listagem 66. A entidade Autor package br.com.integrator.entities; import java.io.Serializable; import java.util.Date; import java.util.Set; import javax.persistence.*; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "autores") Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
183
Desenvolvendo Aplicações Web com NetBeans IDE 6 @Cache(usage = CacheConcurrencyStrategy. READ_WRITE ) public class Autor implements Serializable { //... omitido por não haver alterações
Listagem 67. A entidade Livro package br.com.integrator.entities; import java.io.Serializable; import java.util.Collection; import java.util.Set; import javax.persistence.*; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "livros") @Cache(usage = CacheConcurrencyStrategy. READ_WRITE ) public class Livro implements Serializable { //... omitido por não haver alterações
Listagem 68. A entidade Editora package br.com.integrator.entities; import java.io.Serializable; import java.util.Collection; import javax.persistence.*; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "editoras") @Cache(usage = CacheConcurrencyStrategy. READ_WRITE ) public class Editora implements Serializable { //... omitido por não haver alterações
Listagem 69. A entidade Publicacao package br.com.integrator.entities; import java.io.Serializable; import javax.persistence.*; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "publicacao") Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
184
Desenvolvendo Aplicações Web com NetBeans IDE 6 @Cache(usage = CacheConcurrencyStrategy. READ_WRITE ) public class Publicacao implements Serializable { //... omitido por não haver alterações
Listagem 70. A entidade Usuario package br.com.integrator.entities; import java.io.Serializable; import javax.persistence.*; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name = "usuarios") @Cache(usage = CacheConcurrencyStrategy. READ_WRITE ) public class Usuario implements Serializable { //... omitido por não haver alterações
Ao adicionar a anotação @Cache, de org.hibernate.annotations.Cache , você ativa o cache para a CacheConcurrencyStrategy.READ_WRITE, entidade. A anotação possui de org.hibernate.annotations.CacheConcurrencyStrategy , indicando que vamos utilizar o tipo readwrite (leitura-escrita), ao qual permite a leitura e gravação de novas informações. Há outros tipos, como READ_ONLY, para informações que não nunca serão atualizadas. Há outros valores possíveis para o atributo usage, que determina a estratégia do cache concorrente. Estes valores podem ser: NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL. Veja mais detalhes no quadro “ Detalhes da utilização do cache no Hibernate ”.
Detalhes da uti lização do cache no Hibernate Utilizar corretamente o cache pelo Hibernate determina como controlar o acesso e o comportamento dos objetos cacheados, definidos pelo atributo usage da anotação @Cache: READ_ONLY – Utilizado quando a aplicação não atualiza as informações, apenas a lê; READ_WRITE – Deve ser utilizado quando a aplicação faz atualizações nos objetos que estão no cache, mas não deve ser utilizado se o nível de isolamento das transações for ISOLATION_SERIALIZABLE; NONSTRICT_READ_WRITE – Utilizado quando a quantidade de atualizações dos objetos é pequena e quando é pouco provável que duas transações vão tentar atualizar o mesmo objeto; TRANSACTIONAL – só pode ser utilizado em um ambiente com suporte a JTA (como um servidor de aplicações como o GlassFish ou Gerônimo). Esse tipo de cache é totalmente transacional e pode ser utilizado com qualquer nível de isolamento das transações. O cache suportado oficialmente pelo Hibernate 3.x é o JBoss TreeCache; • •
•
•
Para sua sorte, na maioria das vezes será utilizado os modos READ_WRITE ou NONSTRICT_READ_WRITE, mas para o uso, é recomendável avaliar o comportamento das transações do seu sistema. Em vários casos, o cache de segundo nível não é recomendado.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
185
Desenvolvendo Aplicações Web com NetBeans IDE 6
Apêndice Extra B O MySQL MySQL é um sistema de gerenciamento de banco de dados relacional, multiencadeado, de códigofonte aberto e nível corporativo. O MySQL foi desenvolvido por uma empresa de consultoria na Suécia chamada inicialmente de TcX, depois, com a popularidade do MySQL, passou a se chamar MySQL AB. Seu desenvolvimento ocorreu quando estavam precisando de um sistema de banco de dados que fosse extremamente rápido e flexível. Foi, assim então, que eles criaram o MySQL, que é vagamente baseado em outro sistema de gerenciamento de banco de dados chamado de mSQL. O MySQL é rápido, flexível e confiável. É utilizado em muitos lugares por todo o mundo. Recentemente, esta empresa foi adquirida pela Sun Microsystems.
Obs.: A propósito, à parte ''AB'' do nome da companhia é o acrônimo para a palavra sueca ''aktiebolag'', ou ''sociedade anônima''. Ela é traduzida para ''MySQL, Inc.'' De fato, MySQL Inc. e MySQL GmbH são exemplos de subsidiárias da MySQL AB. Elas estão localizadas nos EUA e Alemanha, respectivamente. O que é um banco de dados relacional?
Um banco no mundo de cimento e tijolo é o lugar onde guardamos dinheiro. Um banco de dados também guarda, só que neste caso são dados. Chamamos de dados tudo que possamos inserir no computador, números, letras, caracteres, imagens e etc. Um banco de dados relacional é uma composição de tabelas e colunas que se relacionam entre si. Esses relacionamentos são baseados em um valor-chave que é contido em cada tabela, em uma coluna.
Instalando o banco de dados O MySQL tem diferentes formas de instalação quando se trata de sistemas operacionais. No caso do Windows, você pode baixar a última distribuição através do site:
http://www.mysql.com/downloads
Instalando no Windows Procure pelo formato executável. O arquivo vem compactado no formato . zip. Descompacte e instale. A instalação, como não poderia deixar de ser, é feita por um assistente. Siga os passos até a finalização. Caso sua máquina tenha o sistema operacional Windows pertencente a família NT( NT, 2000 ou XP), o MySQL é instalado como serviço. Então basta iniciar ou parar o serviço, encontrado no Painel de Controle>Ferramentas Administrativas>Serviços . Você também pode utilizar o comando pelo prompt, desde que você saiba o nome do serviço do seu MySQL:
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
186
Desenvolvendo Aplicações Web com NetBeans IDE 6 Para iniciar o serviço: net start mysql
Para parar o serviço: net stop mysql
Instalando o MySQL no Linux O MySQL Server pode ser instalado no Linux de várias formas. A forma recomendada é a que está em formato RPM. Você deve baixar dois arquivos para instalar o MySQL na sua máquina. Esses arquivos são:
MySQL-server-[versão].i386.rpm – para instalar o servidor mysqld no Linux MySQL-client-[versão].i386.rpm – para instalar o cliente mysql para executar os comandos no Linux. A instalação poderá ser feita através do comando rpm, no Shell do seu Linux. Um exemplo seria:
Shell> rpm –ivh MySQL-server-5.0.1.i386.rpm MySQL-client-5.0.1.i386.rpm A versão RPM já vem com pré-configurações e assim que ocorrer a instalação, para iniciar ou parar o servidor, a seguinte sintaxe poderá ser feita:
Shell>/etc/init.d/./mysql start – para iniciar o servidor MySQL Shell>/etc/init.d/./mysql stop – para parar o servidor MySQL
Acessando o banco de dados MySQL No Windows
Se você estiver usando o sistema operacional Windows e utilizou a instalação padrão do programa, abra o prompt de comando e digite a seqüência:
cd\mysql\bin Lembrando que você deve estar no drive em que o MySQL está instalado. Por padrão você o instala no drive C. Digitando o comando a seguir você entra no MySQL.
mysql –u root -p Tecle ENTER e receberá o pedido de senha: password Digite a senha que você configurou na instalação e tecle ENTER novamente.
Nota: Versões mais modernas do MySQL para o sistema operacional Windows não necessitam de tantos passos para iniciar, bastando ir até o atalho encontrado no menu Iniciar do sistema e no atalho do MySQL iniciar o prompt de comando encontrado neste local. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
187
Desenvolvendo Aplicações Web com NetBeans IDE 6 No Linux
Se você utilizou a instalação binária, em rpm (recomendado), basta abrir o terminal e digitar a seqüência:
shell>mysql –u root -p Se já estiver logado como root, no seu sistema operacional, não há necessidade de colocar o –u root -p depois do comando mysql. Somente –p caso haja uma senha.
Comandos essenciais para o uso do MySQL Muitos são as instruções SQL para que você venha a dominar um banco de dados. Porém, alguns comandos são imprescindíveis para que você possa trabalhar. Estes comandos são descritos a seguir. O comando CREATE
Há muitas maneiras diferentes de criar banco de dados no MySQL. Ao criar um banco de dados, você normalmente terá o layout inteiro pronto. Normalmente adicionaria as tabelas imediatamente depois de criar o banco de dado, mas, teremos uma etapa por vez. A primeira etapa para criar um banco de dados no MySQL é inserir o comando CREATE DATABASE nome_banco_de_dados da SQL (Structured Query Language) no monitor MySQL, onde nome_banco_de_dados é o nome do banco de dados que você está criado. No prompt de comando, no monitor do MySQL, insira o seguinte comando:
mysql> CREATE DATABASE relatorios; Note que não foi utilizado acentuação e em casos de palavras compostas não insira espaços, se for o caso insira sublinhado “ _ ” . O comando USE
Depois de confirmado a criação do banco de dados, você deverá utilizar o comando USE para utilizar o banco de dados relatorios.
USE relatorios; Um ponto importante é que o MySQL não torna ativo o banco de dados que você criou, isso deve ser implícito. O comando DROP
O comando DROP é semelhante ao comando CREATE. Enquanto o último cria um banco de dados, o primeiro exclui. O comando DROP do SQL é imperdoável. Não há caixas de confirmação para ver se você tem certeza. Este comando exclui o banco de dados e tudo o que estiver nele. É só ir até o prompt de comando e no monitor do MySQL e digitar: mysql> DROP DATABASE relatorios; Isso excluirá o banco de dados veículos e tudo o que estiver nele. Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
188
Desenvolvendo Aplicações Web com NetBeans IDE 6 Criando tabelas
Criar tabela no MySQL é uma tarefa relativamente fácil. Para se criar uma tabela basta usar a seqüência: shell>mysql –u root –p shell> DIGITE AQUI SUA SENHA
Após estar no monitor do MySQL digite a seguinte seqüência: mysql> CREATE DATABASE relatorios; mysql> USE relatorios; mysql> CREATE TABLE categorias ( -> CategoriaID int(11) NOT NULL auto_increment, -> categoria varchar(40) NOT NULL, -> descricao longtext, -> PRIMARY KEY (CategoriaID), -> KEY categoria (categoria) -> ) ENGINE=InnoDB O comando SHOW
Assim que criada sua primeira tabela. Para ver o resultado basta digitar a seqüência:
SHOW TABLES FROM relatorios; Para ver as colunas que existem na sua tabela digite:
SHOW COLUMNS FROM categorias; O comando DESCRIBE
Se preferir, o comando DESCRIBE faz a mesma coisa que SHOW, mostrando as colunas existentes em sua tabela.
DESCRIBE categorias; Ou simplesmente: DESC categorias;
Alterando tabelas existentes Agora que você criou a sua tabela o que aconteceria se você precisasse alterar algo que fez? Confira os seguintes exemplos para alterar o nome da tabela, tipo de dados e o nome da coluna: Alterando o nome da coluna
Usando a cláusula CHANGE você pode alterar o nome da coluna da sua tabela:
ALTER TABLE produtos CHANGE prod_nome produto_nome VARCHAR(150); Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
189
Desenvolvendo Aplicações Web com NetBeans IDE 6 Alterando o tipo de coluna
O tipo pode ser alterado usando a cláusula MODIFY:
ALTER TABLE categorias MODIFY CategoriaID VARCHAR(200) NOT NULL; Renomeando uma tabela
Renomear o nome de uma tabela, também se usa ALTER TABLE, mas com a cláusula RENAME:
ALTER TABLE produtos RENAME tb_categorias; Excluindo / adicionando colunas e tabelas
Como você pode ver quando uma coluna é criada ou uma tabela estas não são escritas na pedra e podem ser alteradas facilmente. Isso também implica em adicionar colunas em uma tabela existente ou excluí-la. Eliminando tabelas e colunas
O comando DROP também é utilizado para eliminar as colunas de uma tabela. Para excluir uma tabela existente execute a seguinte seqüência:
DROP TABLE categorias; Para excluir somente uma coluna execute a seguinte seqüência:
ALTER TABLE categorias DROP descricao ; Isso excluirá a coluna e todas as informações que você armazenou. Adicionando colunas
O comando ADD é o responsável pela inserção de uma nova coluna.
ALTER TABLE categorias ADD descricao TEXT; Adicionando colunas após outra determinada coluna
O comando AFTER adiciona a nova coluna na tabela após o nome mencionado.
ALTER TABLE categorias ADD descricao TEXT AFTER categoria; Utilizando índices
Um índice é um arquivo estruturado que facilita o acesso a dados. Isso significa que um índice na coluna correta aumentará a velocidade de uma consulta consideravelmente. Um índice trabalha da mesma forma que pastas com separador alfabético em um gabinete de arquivo ele permite pular para a parte do alfabeto que você está procurando.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
190
Desenvolvendo Aplicações Web com NetBeans IDE 6 Decidindo quais colunas incluir no índice
Você deve colocar um índice na(s) coluna(s) que utilizará com mais freqüência como filtro em suas consultas. Os índices também funcionam melhor em colunas que contêm dados únicos. Essa é uma das razões pela as quais chaves são normalmente suas melhores escolhas para índices. Essa também pode ser uma das razões que as pessoas confundem chaves e índices. Uma chave ajuda a definir a estrutura de um banco de dados, ao passo que índice apenas aprimora o desempenho. Um índice pode ser composto de uma ou mais colunas. Você também pode ter mais de um índice em uma tabela. Criando um índice
Por padrão, o MySQL cria um índice se você declara uma coluna como uma chave primária. Não há necessidade de criar um índice nessa coluna; caso contrário você teria dois índices em uma mesma coluna. A sintaxe para criar um índice em uma coluna:
ALTER TABLE categorias ADD INDEX idx_cat(categoria); Excluindo índices
Excluir um índice é tão simples quanto criar. A sintaxe é a mesma que excluir uma coluna ou uma tabela:
DROP INDEX nomedoindice ON nomedatabela; Ou...
ALTER TABLE nomedatabela DROP INDEX nomedoindice; Para alterar uma tabela eliminando uma chave primária, utilize a seguinte sintaxe:
ALTER TABLE nomedatabela DROP PRIMARY KEY; Nota: Se você estiver usando uma coluna com AUTO_INCREMENT, você não excluirá a chave primária enquanto não retirar esse modificador. Tipos de tabelas
O MySQL possui uma característica um pouco diferente dos outros sistemas gerenciadores de banco de dados, uma vez que no MySQL é possível escolher o tipo da tabela no momento da criação. O formato de armazenamento dos dados, bem como alguns recursos do banco de dados são dependentes do tipo de tabela escolhido. A definição do tipo de tabela pode ser feita na criação da tabela, como você pode ver a seguir:
CREATE TABLE teste ( id INT NOT NULL, nome VARCHAR(30) NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM; Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
191
Desenvolvendo Aplicações Web com NetBeans IDE 6 No comando criado, o tipo da tabela, indicado em TYPE=MyISAM, significa que você está criando uma tabela com o tipo MyISAM, que é o padrão das tabelas, caso não seja informado o TYPE. A partir da versão 4.0.18 você pode utilizar ENGINE como sinônimo de TYPE. Os tipos mais comuns de tabelas criadas são o MyISAM (padrão) e o InnoDB(suporta transações): O tipo MyISAM
Este é o tipo de tabela padrão do MySQL. Caso não seja informado o tipo de tabela, o MySQL criará a tabela do tipo MyISAM. O tipo de tabela padrão pode ser alterado incluindo-se no arquivo de configuração, chamado de my.cnf (no Linux) ou my.ini (no Windows), a opção a seguir:
default-storage-engine=INNODB As tabelas MyISAM são armazenadas em 3 arquivos, com o mesmo nome da tabela, mas com extensões diferentes: • • •
.FRM que armazena a definição da tabela. .MYD que contém os dados. .MYI contendo os índices.
Estas tabelas são de grande desempenho para leitura, uma vez que os seus índices são armazenados em árvores binárias balanceadas, o que provê um ganho para o acesso às informações. O MyISAM não trabalha com transações (commit ou rollback) e também não possui integridade referencial, isto é, ao incluir uma chave estrangeira com alguns constraints, esta servirá apenas como documentação, mas as restrições não serão respeitadas pelo banco. O tipo InnoDB
O tipo InnoDB é do tipo de tabela transacional, desenvolvido pela InnoDBase Oy. A partir da versão 4.0 do MySQL ele passa a ser parte integrante das distribuições do MySQL. O InnoDB apresenta, além da capacidade transacional, outros recursos que são realmente úteis na utilização de tabelas: Integridade referencial, com implementação dos constraints SET NULL , SET DEFAULT , RESTRICT e CASCADE; Ferramenta de backup on-line (ferramenta comercial, não GPL); Lock de registro, como Oracle, DB2, etc; Níveis de isolamento; Armazenamentos de dados em tablespace. •
• • • •
Por se tratar de um tipo de tabela com recursos mais avançados, requer mais espaço em memória e disco, além de se apresentar, em determinadas situações, um pouco mais lento que tabelas do tipo MyISAM. Apesar disto, o tipo InnoDB tem se mostrado extremamente rápido se comparado com outros SGBDs transacionais.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
192
Desenvolvendo Aplicações Web com NetBeans IDE 6 Alterando o tipo de uma tabela
Com o comando ALTER TABLE não é possível alterar o tipo da tabela, por isso, você pode alterar da seguinte maneira:
ALTER TABLE departamentos ENGINE=INNODB;
Tipo de dados
Como a maioria dos sistemas de gerenciamento de banco de dados relacional (Relational Database Management Systems – RDBMS), o MySQL tem tipos de dados específicos de coluna. O MySQL tem vários tipos de dados que suportam funções diferentes. Um tipo de dados é a definição das informações que uma coluna armazenará. Pode haver muitos tipos de dados em uma tabela, mas cada coluna armazenará seu próprio tipo de informações específicas. Há quatro tipos de grupos de formatos de dados. O primeiro é o numérico. O segundo tipo é o formato de caractere ou string. Esse formato consiste em letras e números ou qualquer coisa que você coloque entre aspas. O terceiro grupo é formado por datas e horas. O tipo final é uma forma de miscelânea. Ele consiste em tudo que não se encaixa em quaisquer uma das outras categorias.
Tipos numéricos
Os tipos numéricos destinam-se somente a números. Os diferentes tipos de números ocupam uma quantidade diferente de espaço na memória. Um bom exemplo é você tentando comprar um chocolate em uma loja e ao passar no caixa a você descobre que deve pagar pela caixa inteira. Você diz que não precisa de tudo, mas é atacado e só e vendido de caixa. Se você vai utilizar 3 números, por que ocupar um espaço na memória como se estivesse utilizando 100? Lembre-se: você só deve pagar pelo que vai usar.
Tabela B.1 - Armazenamento numérico Nome do tipo Espaço na memória 1 byte TINYINT SMALLINT 2 bytes MEDIUMINT 3 bytes 4 bytes INT BIGINT 8 bytes FLOAT(Inteiro,Decimal) 4 bytes 8 bytes DOUBLE(Inteiro,Decimal) DECIMAL(Inteiro,Decimal) O valor de bytes Inteiro + 2
Se a coluna é numérica e declarada UNSIGNED, o intervalo dobra para o tipo dado. Por exemplo, se você declara que uma coluna que é UNSIGNED TINYINT , o intervalo dessa coluna é de 0 a 255. Declarando dessa forma você faz com que essa coluna tenha somente valores positivos.
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
193
Desenvolvendo Aplicações Web com NetBeans IDE 6 Tabela B.2 -Tipos numéricos Nome do tipo Intervalo de valor TINYINT SMALLINT MEDIUMINT INT BIGINT FLOAT(Inteiro,Decimal) DOUBLE(Inteiro,Decimal) DECIMAL(Inteiro,Decimal)
-128 a 127 -32768 a 32767 -8388608 a 83888607 -2147483648 a 2147483647 -9223372036854775808 a 9223372036854775807 Varia dependendo dos valores Varia dependendo dos valores Varia dependendo dos valores
FLOATs, DOUBLEs e DECIMALs são tipos numéricos que podem armazenar frações. Os outros não. Utilize DECIMAL para números realmente grandes. DECIMALs são armazenados de maneira diferente e não têm limites. Modificadores AUTO_INCREMENT, UNSIGNED e ZEROFILL
Esses modificadores só podem ser utilizados com tipos de dados numéricos. Eles utilizam operações que somente podem ser feitas com números.
AUTO_INCREMENT
O modificador de coluna AUTO_INCREMENT automaticamente aumenta o valor de uma coluna adicionando 1 ao valor máximo atual. Ele fornece um contador que é ótimo para criar valores únicos. Você também pode incluir um número. Se quiser que uma coluna AUTO_INCREMENT inicie com 9.000, por exemplo, é só declarar explicitamente um ponto inicial utilizando a seguinte sintaxe: mysql> CREATE TABLE teste ( -> id INT NOT NULL PRIMARY KEY AUTO_INCREMENT -> ) AUTO_INCREMENT=9000;
UNSIGNED
UNSIGNED depois de um tipo inteiro significa que ele só pode ter um zero ou valor positivo. ZEROFILL
O modificador de coluna ZEROFILL é utilizado para exibir zeros à esquerda de um número com base na largura de exibição. Como todos os tipos de dados numéricos têm uma largura de exibição opcional, se você declara um INT(8) ZEROFILL e o valor armazenado é 23, ele será exibido como 00000023. Para isso utilize a seguinte sintaxe:
CREATE TABLE teste (id INT(4) ZEROFILL);
Parte integrante do livro Desenvolvendo Aplicações Web com NetBeans IDE 6 – não pode ser vendido ou distribuído separadamente
194
Desenvolvendo Aplicações Web com NetBeans IDE 6 Tipos de caractere ou de dados de string
O outro grupo importante de tipo de dados são os tipos de strings ou de caractere. Uma string é um conjunto de caracteres. Um tipo de string pode armazenar dados como São Paulo ou Avenida São João, n.º 255. Qualquer valor pode ser armazenado em um tipo de dados de string.
Tabela B.3 - Tipos string Nome de tipo Tamanho máximo CHAR(X) 255 bytes VARCHAR(X) 255 bytes TINYTEXT 255 bytes TINYBLOB 255 bytes TEXT 65.535 bytes BLOB 65.535 bytes MEDIUMTEXT 1,6 MB MEDIUMBLOB 1,6 MB LONGTEXT 4,2 GB 4,2 GB LONGBLOB
Espaço de armazenamento X bytes X + 1 byte X + 1 byte X + 2 bytes X + 2 bytes X + 2 bytes X + 3 bytes X + 3 bytes X + 4 bytes X + 4 bytes
CHAR e VARCHAR
Fora todos esses tipos, os tipos VARCHAR e CHAR são os mais utilizados. A diferença entre eles é que o VARCHAR tem um comprimento variável e o CHAR não. Os tipos CHAR são utilizados para comprimentos fixos. Você utilizará esse tipo quando os valores não variam muito. Se você declara um CHAR(10), todos os valores armazenados nessa coluna terão 10 bytes de comprimento, mesmo se ele tiver 3 bytes de comprimento. O MySQL preenche esse valor para ajustar o tamanho que foi declarado. O tipo VARCHAR faz o contrário. Se você declara um VARCHAR(10) e armazena um valor que tem somente 3 caracteres de comprimento, a quantidade total de espaço de armazenamento é de 4 bytes (o comprimento mais um). A vantagem de utilizar os tipos CHAR é que as tabelas que contêm esses valores fixos são processadas mais rapidamente que aquelas que são compostas pelo tipo VARCHAR. A desvantagem de utilizar o tipo CHAR é o espaço desperdiçado. De um modo geral não se pode utilizar os dois na mesma tabela, pois quando feito o MySQL converte automaticamente uma coluna com o tipo CHAR em VARCHAR. A única exceção é quando você declara uma coluna como VARCHAR(3), o MySQL converte automaticamente em CHAR(3). Isso acontece porque valores de 4 caracteres ou menores são muito pequenos para o tipo VARCHAR. TEXT e BLOB
TEXT e BLOB(Binary Large Object) são tipos variáveis de comprimento que podem armazenar grandes quantidades de dados. Você utilizará esses tipos quando quiser armazenar imagens, sons ou grandes quantidades de textos, como páginas da Web ou documentos. Um bom exemplo é se você estiver querendo armazenar valores de uma