Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
15 de abril de 2013
Sumrio Sobre a K19 Seguro Treinamento Termo de Uso Cursos 1 Enterprise JavaBeans 1.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 EJB Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stateless Session Beans 2.1 Session Beans . . . . . . . . . . 2.2 Caracterizando os SLSBs . . . . 2.3 SLSB - EJB 3.0 . . . . . . . . . . 2.4 SLSB - EJB 3.1 . . . . . . . . . . 2.5 Cliente Java Web Local - EJB 3.0 2.6 Exerccios de Fixao . . . . . . 2.7 Cliente Java Web Local - EJB 3.1 2.8 Exerccios de Fixao . . . . . . 2.9 Cliente Java SE Remoto . . . . . 2.10 Exerccios de Fixao . . . . . . 2.11 Ciclo de Vida . . . . . . . . . . . 2.12 Escalabilidade e Pool . . . . . . 2.13 Callbacks . . . . . . . . . . . . . 2.14 Exerccios de Fixao . . . . . . 2.15 Mtodos Assncronos . . . . . . 2.16 Exerccios de Fixao . . . . . . Stateful Session Beans
www.facebook.com/k19treinamentos
i 1 2 3 4 1 1 1 1 13 13 13 14 15 16 17 25 25 30 31 35 36 37 37 39 41 43
i
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
S UMRIO
ii
Caracterizando os SFSBs SFSB - EJB 3.0 . . . . . . SFSB - EJB 3.1 . . . . . . Exerccios de Fixao . . Ciclo de Vida . . . . . . . Callbacks . . . . . . . . . Exerccios de Fixao . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
43 44 46 46 50 52 54 63 63 64 66 70 72 73 75 81 81 81 87 88 88 89 95 95 96 101 101 101 101 102 104 105 113 113 113 119 119 130 132 135 135 136 136 138 138
Singleton Session Beans 4.1 Caracterizando os Singleton Session Beans 4.2 Implementao . . . . . . . . . . . . . . . . 4.3 Exerccios de Fixao . . . . . . . . . . . . . 4.4 Ciclo de Vida . . . . . . . . . . . . . . . . . . 4.5 Exerccios de Fixao . . . . . . . . . . . . . 4.6 Concorrncia . . . . . . . . . . . . . . . . . . 4.7 Exerccios de Fixao . . . . . . . . . . . . . Persistncia 5.1 Data Sources . . . . . . . . . . 5.2 Exerccios de Fixao . . . . . 5.3 persistence.xml . . . . . . . . 5.4 Entity Beans . . . . . . . . . . 5.5 Entity Classes e Mapeamento 5.6 Exerccios de Fixao . . . . . 5.7 Entity Managers . . . . . . . . 5.8 Entity Manager Factories . . . 5.9 Exerccios de Fixao . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
Transaes 6.1 ACID . . . . . . . . . . . . . . . . . . . . . 6.2 Transao Local ou Distribuda . . . . . 6.3 JTA e JTS . . . . . . . . . . . . . . . . . . . 6.4 Container Managed Transactions - CMT 6.5 Bean Managed Transactions - BMT . . . 6.6 Exerccios de Fixao . . . . . . . . . . . Segurana 7.1 Realms . . . . . . . . . . . . . . . 7.2 Exerccios de Fixao . . . . . . 7.3 Autenticao - Aplicaes Web 7.4 Exerccios de Fixao . . . . . . 7.5 Autorizao - Aplicaes EJB . . 7.6 Exerccios de Fixao . . . . . . Interceptadores 8.1 Interceptor Methods . . . 8.2 Internal Interceptors . . . 8.3 External Interceptors . . . 8.4 Excluindo Interceptadores 8.5 Invocation Context . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
ii
www.k19.com.br
iii
S UMRIO
8.6 8.7 9
Ordem dos Interceptadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Exerccios de Fixao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 147 147 147 148 149 157 157 158 158 159 160 164 165 166
Scheduling 9.1 Timers . . . . . . . . . 9.2 Mtodos de Timeout 9.3 Timers Automticos . 9.4 Exerccios de Fixao
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
10 Contexts and Dependency Injection - CDI 10.1 Managed Beans . . . . . . . . . . . . . 10.2 Producer Methods and Fields . . . . . 10.3 EL Names . . . . . . . . . . . . . . . . . 10.4 beans.xml . . . . . . . . . . . . . . . . . 10.5 Exerccios de Fixao . . . . . . . . . . 10.6 Escopos e Contextos . . . . . . . . . . 10.7 Injection Points . . . . . . . . . . . . . 10.8 Exerccios de Fixao . . . . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
www.facebook.com/k19treinamentos
iii
S UMRIO
iv
iv
www.k19.com.br
S UMRIO
Sobre a K19
A K19 uma empresa especializada na capacitao de desenvolvedores de software. Sua equipe composta por prossionais formados em Cincia da Computao pela Universidade de So Paulo (USP) e que possuem vasta experincia em treinamento de prossionais para rea de TI. O principal objetivo da K19 oferecer treinamentos de mxima qualidade e relacionados s principais tecnologias utilizadas pelas empresas. Atravs desses treinamentos, seus alunos se tornam capacitados para atuar no mercado de trabalho. Visando a mxima qualidade, a K19 mantm as suas apostilas em constante renovao e melhoria, oferece instalaes fsicas apropriadas para o ensino e seus instrutores esto sempre atualizados didtica e tecnicamente.
www.facebook.com/k19treinamentos
S UMRIO
Seguro Treinamento
Na K19 o aluno faz o curso quantas vezes quiser! Comprometida com o aprendizado e com a satisfao dos seus alunos, a K19 a nica que possui o Seguro Treinamento. Ao contratar um curso, o aluno poder refaz-lo quantas vezes desejar mediante a disponibilidade de vagas e pagamento da franquia do Seguro Treinamento. As vagas no preenchidas at um dia antes do incio de uma turma da K19 sero destinadas ao alunos que desejam utilizar o Seguro Treinamento. O valor da franquia para utilizar o Seguro Treinamento 10% do valor total do curso.
www.k19.com.br
S UMRIO
Termo de Uso
Termo de Uso
Todo o contedo desta apostila propriedade da K19 Treinamentos. A apostila pode ser utilizada livremente para estudo pessoal . Alm disso, este material didtico pode ser utilizado como material de apoio em cursos de ensino superior desde que a instituio correspondente seja reconhecida pelo MEC (Ministrio da Educao) e que a K19 seja citada explicitamente como proprietria do material. proibida qualquer utilizao desse material que no se enquadre nas condies acima sem o prvio consentimento formal, por escrito, da K19 Treinamentos. O uso indevido est sujeito s medidas legais cabveis.
www.facebook.com/k19treinamentos
S UMRIO
TR
www.k19.com.br/cursos
www.k19.com.br
CAPTULO
Introduo
Muitos sistemas corporativos so desenvolvidos seguindo a arquitetura denida pelo padro Enterprise JavaBeans (EJB). Ao utilizar essa arquitetura, diversos recursos so disponibilizados a esses sistemas. Transaes: A arquitetura EJB dene um suporte sosticado para utilizao de transaes. Esse suporte integrado com a Java Transaction API (JTA) e oferece inclusive a possibilidade de realizar transaes distribudas. Segurana: Suporte para realizar autenticao e autorizao de forma transparente. Os desenvolvedores das aplicaes no precisam implementar a lgica de segurana pois ela faz parte da arquitetura EJB. Remotabilidade: Aplicaes EJB podem ser acessadas remotamente atravs de diversos protocolos de comunicao. Consequentemente, possvel desenvolver aplicaes clientes de diversos tipos. Por exemplo, aplicaes EJB podem ser como Web Services. Multithreading e Concorrncia: A arquitetura EJB permite que as aplicaes sejam acessados por mltiplos usurios simultaneamente de maneira controlada para evitar problemas de concorrncia. Persistncia: Facilidades para utilizar os servios dos provedores de persistncia que seguem a especicao JPA. Gerenciamento de Objetos: Mecanismos de injeo de dependncias e controle de ciclo de vida so oferecidos aos objetos de uma aplicao EJB. O mecanismo de controle de ciclo de vida pode garantir a escalabilidade de uma aplicao. Integrao: A arquitetura EJB fortemente integrada com os componentes da plataforma Java EE. Podemos, por exemplo, facilmente integrar os recursos do JSF em uma aplicao EJB.
EJB Container
Toda aplicao EJB executada e gerenciada por um EJB Container. H diversas opes de EJB Container disponveis. Os servidores de aplicao Java EE como o Glasssh e o JBoss possuem um EJB Container. Portanto, podemos utiliz-los para executar as nossas aplicaes EJB.
Exerccios de Fixao
www.facebook.com/k19treinamentos
Copie o arquivo glasssh-VERSAO-with-hibernate.zip da pasta K19-Arquivos para a sua rea de Trabalho e descompacte-o.
1
Importante
Voc tambm pode obter o arquivo glasssh-VERSAO-with-hibernate.zip atravs do site da K19: www.k19.com.br/arquivos.
Copie o arquivo jboss-as-VERSAO-Final.zip da pasta K19-Arquivos para a sua rea de Trabalho e descompacte-o.
2
Importante
Voc tambm pode obter o arquivo jboss-as-VERSAO-Final.zip atravs do site da K19: www.k19.com.br/arquivos.
www.k19.com.br
www.facebook.com/k19treinamentos
www.k19.com.br
www.facebook.com/k19treinamentos
www.k19.com.br
www.facebook.com/k19treinamentos
Siga as imagens abaixo para congurar e testar o JBoss. Pare o Glasssh antes de testar o JBoss No Eclipse. . .
www.k19.com.br
www.facebook.com/k19treinamentos
10
10
www.k19.com.br
11
www.facebook.com/k19treinamentos
11
12
12
www.k19.com.br
CAPTULO
Session Beans
Um sistema corporativo composto por muitos processos ou tarefas. Por exemplo, um sistema bancrio possui processos especcos para realizar transferncias, depsitos, saques, emprstimos, cobranas, entre outros. Esses procedimentos so chamados de regras de negcio. Cada aplicao possui as suas prprias regras de negcio j que elas so consequncia imediata do contexto da aplicao. Utilizando a arquitetura EJB, as regras de negcio so implementadas em componentes especcos que so chamados de Session Beans. O EJB Container administra esses componentes oferecendo diversos recursos a eles.
Caracterizando os SLSBs
Stateless Session Bean o primeiro tipo de Session Bean. Muitas vezes, utilizaremos a sigla SLSB para fazer referncia a esse tipo de componente. A caracterstica fundamental dos SLSBs que eles no armazenam estado conversacional. Vejamos alguns exemplos a seguir.
Servio de Cmbio
Considere um sistema de converso monetria. Esse sistema capaz de converter valores monetrios de uma moeda para outra. Por exemplo, converter 100 reais para o valor correspondente em dlar americano. Poderamos, implementar essa regra de negcio atravs do mtodo a seguir.
1 2 3 public double converte ( double valor , String moedaOrigem , String moedaDestino ) { // lgica da converso monetria }
A execuo do mtodo converte() no depende das suas execues anteriores. Em outras palavras, o mtodo converte() no precisa manter estado conversacional.
Dicionrio
Considere a implementao de um dicionrio digital de portugus. Dado uma palavra, o dicionrio digital deve devolver a denio dela. Podemos criar um mtodo para implementar essa regra de negcio.
1 2 3 public String getDefinicao ( String palavra ) { // lgica do dicionario }
www.facebook.com/k19treinamentos
13
14
As chamadas ao mtodo getDefinicao() so totalmente independentes. Dessa forma, no necessrio guardar informaes referentes s chamadas anteriores. Ou seja, no necessrio manter estado conversacional.
Consulta de CEP
Considere um sistema de consulta de CEP. Esse sistema capaz de informar o CEP de uma determinada localidade. Podemos criar um mtodo para implementar essa regra de negcio.
1 2 3 public String consultaCEP ( String estado , String cidade , String logradouro , Integer numero ) { // lgica da consulta do CEP }
Como cada consulta de CEP independe das consultas anteriores, no necessrio manter dados entre uma consulta e outra. Em outras palavras, no necessrio manter estado conversacional.
Os mtodos contidos na interface Calculadora so chamados de mtodos de negcio. Depois da interface, o segundo passo seria implementar as operaes do SLSB atravs de uma classe.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 public class CalculadoraBean implements Calculadora { public double soma ( double a , double b ) { return a + b ; } public double subtrai ( double a , double b ) { return a - b ; } public double multiplica ( double a , double b ) { return a * b ; } public double divide ( double a , double b ) { return a / b ; } }
Cdigo Java 2.5: CalculadoraBean.java
14
www.k19.com.br
15
Observe que a classe CalculadoraBean implementa a interface Calculadora. O terceiro passo especicar o tipo de Session Bean que queremos utilizar. No caso da calculadora, o tipo seria SLSB. Essa denio realizada atravs da anotao @Stateless.
1 2 3 4 @Stateless public class CalculadoraBean implements Calculadora { ... }
Cdigo Java 2.6: CalculadoraBean.java
Por m, necessrio denir se o acesso do SLSB local ou remoto. Quando o acesso local, apenas quem est dentro do servidor de aplicao no qual se encontra o SLSB pode acess-lo. Quando o acesso remoto, tanto quem est dentro quanto quem est fora do servidor de aplicao no qual se encontra o SLSB pode acess-lo. A denio do tipo de acesso pode ser realizada atravs das anotaes: @Local e @Remote.
1 2 3 4 5 @Stateless @Remote ( Calculadora . class ) public class CalculadoraBean implements Calculadora { ... }
Cdigo Java 2.7: CalculadoraBean.java
1 2 3 4 5
@Stateless @Local ( Calculadora . class ) public class CalculadoraBean implements Calculadora { ... }
Cdigo Java 2.8: CalculadoraBean.java
Nas anotaes @Local e @Remote, devemos informar as interfaces que denem os mtodos de negcio do nosso SLSB. A classe CalculadoraBean poderia implementar diversas interfaces. Contudo, apenas os mtodos das interfaces declaradas nessas anotaes sero considerados mtodos de negcio.
www.facebook.com/k19treinamentos
15
16
Os mtodos pblicos dos objetos da classe CalculadoraBean sero considerados mtodos de negcio.
Depois de denir a interface, devemos implementar as operaes do SLSB atravs de uma classe java com as anotaes apropriadas.
1 2 3 4 5 6 7 @Stateless @Local ( Calculadora . class ) public class CalculadoraBean implements Calculadora { public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 2.11: CalculadoraBean.java
Perceba que o acesso local foi denido para esse SLSB pois ele ser acessado por uma camada web no mesmo servidor de aplicao. Nesse momento, o SLSB est pronto. O prximo passo implementar a camada web. A interface Calculadora que dene as operaes do SLSB precisa estar no classpath da camada web diferentemente da classe CalculadoraBean que implementa as operaes.
16
www.k19.com.br
17
Suponha que a camada web da nossa aplicao utiliza apenas Servlets. Podemos injetar, atravs da anotao @EJB, o SLSB em uma Servlet.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 @WebServlet ( " / soma " ) public class SomaServlet extends HttpServlet { @EJB private Calculadora calculadora ; protected void service ( HttpServletRequest req , HttpServletResponse res ) { double a = Double . parseDouble ( request . getParameter ( " a " ) ) ; double b = Double . parseDouble ( request . getParameter ( " b " ) ) ; double resultado = this . calculadora . soma (a , b ) ; PrintWriter out = response . getWriter () ; out . println ( " < html > < body > <p > " ) ; out . println ( " Soma : " + resultado ) ; out . println ( " </p > </ body > </ html > " ) ; } }
Agora, suponha que a camada web utilize JSF. Podemos injetar o SLSB em um managed bean tambm atravs da anotao @EJB.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 @ManagedBean public class CalculadoraMB { @EJB private Calculadora calculadora ; private double a ; private double b ; private double resultado ; public void soma () { this . resultado = this . calculadora . soma (a , b ) ; } // GETTERS AND SETTERS }
Exerccios de Fixao
Crie um EJB project no eclipse. Voc pode digitar CTRL+3 em seguida new EJB project e ENTER. Depois, siga exatamente as imagens abaixo.
1
www.facebook.com/k19treinamentos
17
18
18
www.k19.com.br
19
calculadora: As classes que implementam os SLSB devem ser colocadas nesse projeto.
calculadoraClient: As interfaces que denem as operaes dos SLSB devem ser colocadas nesse projeto.
Crie um Dynamic Web Project no eclipse para implementar a camada web. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
www.facebook.com/k19treinamentos
19
20
20
www.k19.com.br
21
Adicione o projeto calculadoraClient como dependncia do projeto calculadoraWeb. Abra as propriedades do projeto calculadoraWeb. Voc pode selecionar o projeto calculadoraWeb e digitar ALT+ENTER. Depois, siga as imagens abaixo.
3
www.facebook.com/k19treinamentos
21
22
22
www.k19.com.br
23
No projeto calculadoraClient, crie uma interface java chamada Calculadora em um pacote chamado br.com.k19.sessionbeans.
4
1 2 3 4 5
package br . com . k19 . sessionbeans ; public interface Calculadora { double soma ( double a , double b ) ; }
Cdigo Java 2.14: Calculadora.java
5 No projeto calculadora, crie uma classe java chamada CalculadoraBean em um pacote chamado br.com.k19.sessionbeans.
1 2 3 4 5 6 7 8 9 1 11 12
package br . com . k19 . sessionbeans ; import javax . ejb . Local ; import javax . ejb . Stateless ; @Stateless @Local ( Calculadora . class ) public class CalculadoraBean implements Calculadora { public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 2.15: CalculadoraBean.java
www.facebook.com/k19treinamentos
23
24
No projeto calculadoraWeb, crie uma classe java chamada CalculadoraMB em um pacote chamado br.com.k19.managedbeans.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 package br . com . k19 . managedbeans ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . sessionbeans . Calculadora ; @ManagedBean public class CalculadoraMB { @EJB private Calculadora calculadora ; private double a ; private double b ; private double resultado ; public void soma () { this . resultado = this . calculadora . soma (a , b ) ; } // GETTERS AND SETTERS }
7 Crie uma simples tela na aplicao web para utilizar o managed bean. Adicione o arquivo soma.xhtml na pasta WebContent do projeto calculadoraWeb com o seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " > <h : head > < title > Calculadora - Soma </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Valor A : " / > <h : inputText value = " #{ calculadoraMB . a } " / > <h : outputLabel value = " Valor B : " / > <h : inputText value = " #{ calculadoraMB . b } " / > <h : commandButton action = " #{ calculadoraMB . soma } " value = " soma " / > <h : outputLabel value = " Resultado : " / > <h : outputText value = " #{ calculadoraMB . resultado } " / > </ h : form > </ h : body > </ html >
24
www.k19.com.br
25
8
Adicione o projeto calculadoraEAR no Glasssh 3.1.2. Clique com o boto direito no Glasssh 3.1.2 da view Servers e escolha a opo Add and Remove. Depois, siga as imagens abaixo.
Certique-se que o JBoss 7.1 Runtime Server est parado. Inicie o Glasssh 3.1.2. Acesse a url
Exerccios de Fixao
Para no confunr, feche os projetos calculadora, calculadoraClient, calculadoraEAR e calculadoraWeb. Para isso, clique com o boto direito do mouse sobre esses projetos e selecione a opo Close Project.
10
Crie um Dynamic Web Project no eclipse para implementar a camada web. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens
11
www.facebook.com/k19treinamentos
25
26
abaixo.
26
www.k19.com.br
27
www.facebook.com/k19treinamentos
27
28
No projeto dadoWeb, adicione um pacote chamado br.com.k19.sessionbeans e acrescente nele uma classe chamada LancadorDeDadoBean.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 package br . com . k19 . sessionbeans ; import java . util . Random ; import javax . ejb . Stateless ; @Stateless public class LancadorDeDadoBean { private Random gerador = new Random () ; public int lanca () { return this . gerador . nextInt (6) + 1; } }
Cdigo Java 2.17: LancadorDeDadoBean.java
No projeto dadoWeb, adicione um pacote chamado br.com.k19.managedbeans acrescenta nele uma classe chamada DadoMB.
13
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26
package br . com . k19 . managedbeans ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . sessionbeans . LancadorDeDadoBean ; @ManagedBean public class DadoMB { @EJB private LancadorDeDadoBean lancadorDeDadoBean ; private int resultado ; public void lancaDado () { this . resultado = this . lancadorDeDadoBean . lanca () ; } public int getResultado () { return resultado ; } public void setResultado ( int resultado ) { this . resultado = resultado ; } }
Cdigo Java 2.18: DadoMB.java
Crie uma simples tela na aplicao web para utilizar o managed bean. Adicione o arquivo dado.xhtml na pasta WebContent do projeto dadoWeb com o seguinte contedo.
14
1 2 3 4 5 6 7
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " > <h : head >
28
www.k19.com.br
29
8 9 1 11 12 13 14 15 16 17 18 19 < title > Lanador de dado </ title > </ h : head >
<h : body > <h : form > <h : commandButton action = " #{ dadoMB . lancaDado } " value = " Lana o Dado " / > <h : outputLabel value = " Resultado : " / > <h : outputText value = " #{ dadoMB . resultado } " / > </ h : form > </ h : body > </ html >
15 Remova o projeto calculadoraEAR e adicione o projeto dadoWeb no Glasssh 3.1.2. Clique com o boto direito no Glasssh 3.1.2 da view Servers e escolha a opo Add and Remove. Depois, siga as imagens abaixo.
www.facebook.com/k19treinamentos
29
30
16
30
www.k19.com.br
31
2 3
Uma vez com a referncia do SLSB, a aplicao pode chamar as operaes normalmente como se o Session Bean estivesse local. Contudo, importante ressaltar que as chamadas so remotas e portanto mais demoradas.
Exerccios de Fixao
1 2 3 4 5
18
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16
Crie um Java project no eclipse. Voc pode digitar CTRL+3 em seguida new Java project e ENTER. Depois, siga exatamente as imagens abaixo.
19
www.facebook.com/k19treinamentos
31
32
Adicione as bibliotecas do Glasssh 3.1.2 necessrias para a consulta ao servio de nomes. Abra as propriedades do projeto dadoJavaSE. Voc pode selecionar o projeto dadoJavaSE e digitar ALT+ENTER. Depois, siga as imagens abaixo.
20
32
www.k19.com.br
33
Adicione o projeto dadoWeb como dependncia do projeto dadoJavaSE. Abra as propriedades do projeto dadoJavaSE. Voc pode selecionar o projeto dadoJavaSE e digitar ALT+ENTER. Depois, siga as imagens abaixo
21
www.facebook.com/k19treinamentos
33
34
34
www.k19.com.br
35
22
No projeto dadoJavaSE, adicione um pacote chamado br.com.k19.testes acrescenta nele uma classe chamada TesteDeAcesso.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 package br . com . k19 . testes ; import javax . naming . InitialContext ; import br . com . k19 . sessionbeans . LancadorDeDado ; public class TesteDeAcesso { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () ; LancadorDeDado lancadorDeDado = ( LancadorDeDado ) ic . lookup ( " java : global / dadoWeb / LancadorDeDadoBean " ) ; System . out . println ( lancadorDeDado . lanca () ) ; } }
Cdigo Java 2.22: TesteDeAcesso.java
Ciclo de Vida
As instncias dos SLSBs so administradas pelo EJB Container. Devemos entender o ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB. Trs aspectos fundamentais dos SLSBs nos ajudam a entender o ciclo de vida das instncias.
1. Uma nica instncia de um SLSB pode atender chamadas de diversos clientes. 2. Uma instncia de um SLSB no atende duas chamadas ao mesmo tempo. Em outras palavras, ela processa uma chamada de cada vez. 3. O EJB Container pode criar vrias instncias do mesmo SLSB para atender mais rapidamente as chamadas dos clientes.
Estados
O ciclo de vida das instncias de um SLSB possui apenas dois estados.
1. NO EXISTE 2. PRONTO
35
36
Escalabilidade e Pool
As caractersticas dos SLSBs favorecem a escalabilidade da aplicao pois, de acordo com a demanda, o EJB Container cria novas instncias e cada instncia pode atender vrios clientes. O EJB Container administra as instncias criadas atravs de um Pool. Cada servidor de aplicao oferece conguraes especcas para melhorar a ecincia no atendimento das chamadas. Por exemplo, o Glasssh permite que uma quantidade mxima de instncias de um determinado SLSB seja denida pela aplicao.
36
www.k19.com.br
37
Callbacks
Podemos associar lgicas especcas nas transies de estado no ciclo de vida dos SLSBs.
@PostConstruct
Podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia logo aps ela ser criada. Esse registro realizado atravs da anotao @PostConstruct.
1 2 3 4 5 6 7 8 9 1 @Stateless public class CalculadoraBean { @PostConstruct public void inicializando () { System . out . println ( " Mais uma calculadora criada ... " ) } // METODOS DE NEGOCIO }
Cdigo Java 2.23: CalculadoraBean.java
O EJB Container utiliza o construtor sem argumentos para criar uma instncia de um SLSB. Depois de chamar o construtor sem argumentos, o EJB Container injeta eventuais dependncias na instncia criada. Por m, os mtodos anotados com @PostConstruct so executados.
@PreDestroy
Tambm podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia imediatamente antes dela ser destruda. Esse registro realizado atravs da anotao @PreDestroy.
1 2 3 4 5 6 7 8 9 1 @Stateless public class CalculadoraBean { @PreDestroy public void destruindo () { System . out . println ( " Mais uma calculadora ser destruda ... " ) } // METODOS DE NEGOCIO }
Cdigo Java 2.24: CalculadoraBean.java
Exerccios de Fixao
23
1 2 3 4
www.facebook.com/k19treinamentos
37
38
@Stateless @Remote ( LancadorDeDado . class ) public class LancadorDeDadoBean implements LancadorDeDado { private Random gerador = new Random () ; private static int contador ; @PostConstruct public void inicializando () { synchronized ( LancadorDeDadoBean . class ) { LancadorDeDadoBean . contador ++; System . out . println ( " Criando um lanador de dados ... " ) ; System . out . println ( " Total : " + + LancadorDeDadoBean . contador ) ; } } @PreDestroy public void destruindo () { synchronized ( LancadorDeDadoBean . class ) { LancadorDeDadoBean . contador - -; System . out . println ( " Destruindo um lanador de dados ... " ) ; System . out . println ( " Total : " + + LancadorDeDadoBean . contador ) ; } } public int lanca () { return this . gerador . nextInt (6) + 1; } }
Cdigo Java 2.25: LancadorDeDadoBean.java
Adicione um teste no pacote br.com.k19.testes do projeto dadoJavaSE para fazer consultas em paralelo ao SLSB que lana moedas.
24
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27
package br . com . k19 . testes ; import javax . naming . InitialContext ; import br . com . k19 . sessionbeans . LancadorDeDado ; public class TesteCicloDeVidaSLSB { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () ; for ( int i = ; i < 1 ; i ++) { final LancadorDeDado lancadorDeDado = ( LancadorDeDado ) ic . lookup ( " java : global / dadoWeb / LancadorDeDadoBean " ) ; Thread thread = new Thread ( new Runnable () { @Override public void run () { for ( int i = ; i < 1 ; i ++) { System . out . println ( lancadorDeDado . lanca () ) ; } } }) ; thread . start () ; } } }
38
www.k19.com.br
39
25 Reinicie o Glasssh 3.1.2. Depois, execute a classe TesteCicloDeVidaSLSB observe o log do servidor para conferir as mensagens dos mtodos de callback. Chame o instrutor caso no consiga visualizar o log do glasssh.
26 Altere as conguraes do pool de SLSB do Glasssh 3.1.2. Acesse a interface de administrao do Glasssh 3.1.2 no endereo http://localhost:4848/. Faa as modicaes indicadas na imagem abaixo.
Reinicie o Glasssh 3.1.2. Depois, execute a classe TesteCicloDeVidaSLSB observe o log do servidor para conferir as mensagens dos mtodos de callback. Observe que o servidor tentar manter no Pool de SLSB com apenas 5 instncias do LancadorDeDadoBean. Observe tambm que depois de 10 segundos de ociosidade as instncias so destrudas. Chame o instrutor caso no consiga visualizar o log do glasssh.
27
Mtodos Assncronos
www.facebook.com/k19treinamentos
39
40
A partir da verso 3.1 do EJB, podemos denir mtodos assncronos nos session beans. Geralmente, mtodos assncronos so utilizados para implementar tarefas demoradas. Para denir um mtodo assncrono, basta utilizar a anotao @Asynchronous. Se essa anotao for aplicada na classe que dene um session bean, todos os mtodos de negcio desse session bean sero assncronos. Por outro lado, podemos aplicar essa anotao somentes nos mtodos de negcio que devem ser assncronos.
1 2 3 4 5 6 7 8 @Stateless @Asynchronous public class MeuSessionBean { public Future < Integer > metodoAssincrono1 () {...} public Future < String > metodoAssincrono2 () {...} }
1 2 3 4 5 6 7 8 9 1 11 12 13
@Stateless public class MeuSessionBean { @Asynchronous public Future < Integer > metodoAssincrono1 () {...} @Asynchronous public Future < String > metodoAssincrono2 () {...} public String metodoSincrono1 () {...} public Integer metodoSincrono2 () {...} }
Observe que o retorno dos mtodos assncronos utiliza a interface java.util.concurrent.Future. Essa interface permite vericar se a tarefa j foi concluda atravs do mtodo isDone().
1 2 3 4 5 6 7 8 MeuSessionBean bean = ... Future < String > future = bean . metodoAssincrono1 () ; // executa alguma coisa enquanto o session bean trabalha // verifica se a tarefa terminou if ( future . isDone () ) { }
A interface Future tambm permite que o resultado seja recuperado atravs do mtodo get().
1 2 3 4 5 6 7 8 MeuSessionBean bean = ... Future < String > future = bean . metodoAssincrono1 () ; // executa alguma coisa enquanto o session bean trabalha // verifica se a tarefa terminou if ( future . isDone () ) { String resultado = future . get () ; }
40
www.k19.com.br
41
Exerccios de Fixao
28
Acrescente o mtodo calculaFrequencia() na classe LancadorDeDadoBean do projeto dadoWeb. Obs: Faa o importe dos seguintes itens: java.util.Map java.util.HashMap java.util.concurrent.Future
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
... @Asynchronous public Future < Map < Integer , Integer > > calculaFrequencia () { Map < Integer , Integer > map = new HashMap < Integer , Integer >() ; map . put (1 , ) ; map . put (2 , ) ; map . put (3 , ) ; map . put (4 , ) ; map . put (5 , ) ; map . put (6 , ) ; for ( int i = ; i < 5 ; i ++) { int v = this . gerador . nextInt (6) + 1; map . put (v , map . get ( v ) + 1) ; try { Thread . sleep (1 ) ; } catch ( InterruptedException e ) { } System . out . println ( i ) ; } return new AsyncResult < Map < Integer , Integer > >( map ) ; } ...
Cdigo Java 2.31: LancadorDeDadoBean.java
29
Adicione o mtodo calculaFrequencia() na interface LancadorDeDado do projeto dadoWeb. Obs: Faa o importe dos seguintes itens: java.util.Map java.util.concurrent.Future
1 2 3
... Future < Map < Integer , Integer > > calculaFrequencia () ; ...
Cdigo Java 2.32: LancadorDeDado.java
30
1 2 3
www.facebook.com/k19treinamentos
41
42
31
42
www.k19.com.br
CAPTULO
Caracterizando os SFSBs
Stateful Session Bean o segundo tipo de Session Bean. Muitas vezes, utilizaremos a sigla SFSB para fazer referncia a esse tipo de componente. A ideia fundamental por trs dos SFSBs a necessidade de manter estado conversacional.
Carrinho de Compras
Para exemplicar, suponha o funcionamento de um carrinho de compras de uma loja virtual. As regras de negcio do carrinho podem ser implementas atravs de alguns mtodos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 class CarrinhoBean { public void adiciona ( Produto produto ) { // lgica para adicionar produto } public void remove ( Produto produto ) { // lgica para remover produto } public void finalizaCompra () { // lgica para finalizar a compra } }
Cdigo Java 3.1: CarrinhoBean.java
H duas necessidades fundamentais no exemplo do carrinho de compras que devemos observar. Primeiro, uma instncia da classe CarrinhoBean no deve atender vrios clientes para no misturar produtos escolhidos por clientes diferentes. Segundo, os produtos adicionados devem ser mantidos entre as chamadas dos mtodos da classe CarrinhoBean. Em outras palavras, necessrio manter estado conversacional. Provavelmente, o estado do carrinho, ou seja, os produtos adicionados seria mantido em uma lista ou em um conjunto.
1 2 3 4 5 6 7 8 9 1 11 class CarrinhoBean { private Set < Produto > produtos = new HashSet < Produto >() ; public void adiciona ( Produto produto ) { this . produtos . add ( produto ) ; } public void remove ( Produto produto ) { this . produtos . remove ( produto ) ; }
www.facebook.com/k19treinamentos
43
44
Prova Digital
Outro exemplo, suponha o funcionamento de um sistema para aplicar provas que permita que os usurios respondam as questes em qualquer ordem ou modiquem respostas j realizadas antes de nalizar a prova. As resposta poderiam ser mantidas em um mapa.
1 2 3 4 5 6 7 8 9 1 11 class ProvaBean { private Map < Integer , Character > respostas = new HashMap < Integer , Character >() ; public void responde ( Integer questao , Character resposta ) { this . respostas . put ( questao , resposta ) ; } public void finaliza () { // lgica para finalizar a prova } }
Cdigo Java 3.3: ProvaBean.java
Uma instncia da classe ProvaBean no pode atender dois clientes para no misturar as respostas de dois usurios diferentes. Alm disso, as respostas j realizadas devem ser mantidas entre as chamadas.
TrackList
Mais um exemplo, suponha o funcionamento de um player de vdeo que permite que os usurios selecionem um conjunto de vdeos para assistir.
1 2 3 4 5 6 7 8 9 1 11 class ListaDeVideos { private List < Video > videos = new ArrayList < Video >() ; public void adiciona ( Video video ) { this . videos . add ( video ) ; } public void embaralha () { Collections . shuffle ( this . videos ) ; } }
Cdigo Java 3.4: ListaDeVideos.java
Novamente, cada instncia da classe ListaDeVideos deve ser exclusiva de um cliente e os vdeos adicionados devem ser mantidos entre as chamadas dos mtodos.
45
O primeiro passo para implementar um SFSB denir a sua interface de utilizao atravs de uma interface java. Por exemplo, considere um SFSB que implemente o funcionamento do carrinho de compras. Uma possvel interface de utilizao para esse session bean seria:
1 2 3 4 public interface Carrinho { void adiciona ( Produto produto ) ; void remove ( Produto produto ) ; }
Cdigo Java 3.5: Carrinho.java
Aps denir a interface de utilizao, o segundo passo seria implementar as operaes do SFSB atravs de uma classe java.
1 2 3 4 5 6 7 8 9 1 11 12 public class CarrinhoBean implements Carrinho { private Set < Produto > produtos = new HashSet < Produto >() ; public void adiciona ( Produto produto ) { this . produtos . add ( produto ) ; } public void remove ( Produto produto ) { this . produtos . remove ( produto ) ; } }
Cdigo Java 3.6: CarrinhoBean.java
O terceiro passo especicar o tipo de session bean que queremos utilizar. No caso do carrinho, o tipo seria SFSB. Essa denio realizada atravs da anotao @Stateful.
1 2 3 4 @Stateful public class CarrinhoBean implements Carrinho { ... }
Cdigo Java 3.7: CarrinhoBean.java
Por m, necessrio denir se o SFSB poder ser acessado remotamente ou apenas localmente. Quando o acesso a um SLSB local, ele s pode ser acessado por aplicaes que estejam no mesmo servidor de aplicao que ele. Caso contrrio, quando o acesso a um SLSB remoto, ele pode ser acessado tanto por aplicaes que estejam no mesmo servidor de aplicao quanto aplicaes que no estejam. A denio do tipo de acesso realizada atravs das anotaes: @Local e @Remote.
1 2 3 4 5 @Stateful @Remote ( Carrinho . class ) public class CarrinhoBean implements Carrinho { ... }
Cdigo Java 3.8: CarrinhoBean.java
1 2 3 4 5
@Stateful @Local ( Carrinho . class ) public class CarrinhoBean implements Carrinho { ... }
www.facebook.com/k19treinamentos
45
46
Exerccios de Fixao
Para no confunr, feche os projetos dadoWeb e dadoJavaSE. Para isso, clique com o boto direito do mouse sobre esses projetos e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse para implementar o funcionamento do carrinho de compras. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
46
www.k19.com.br
47
www.facebook.com/k19treinamentos
47
48
1 2 3 4
48
www.k19.com.br
49
5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24
import javax . ejb . Stateful ; @Stateful public class CarrinhoBean { private Set < String > produtos = new HashSet < String >() ; public void adiciona ( String produto ) { this . produtos . add ( produto ) ; } public void remove ( String produto ) { this . produtos . remove ( produto ) ; } public Set < String > getProdutos () { return produtos ; } }
Cdigo Java 3.11: CarrinhoBean.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39
www.facebook.com/k19treinamentos
49
50
Adicione o arquivo produtos.xhtml na pasta WebContent do projeto carrinhoWeb com o seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : h = " http :// java . sun . com / jsf / html " > <h : head > < title > Carrinho de Compras </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Produto : " / > <h : inputText value = " #{ carrinhoMB . produto } " / > <h : commandButton action = " #{ carrinhoMB . adiciona } " value = " Adiciona no carrinho " / > < hr / > <h : outputLabel value = " Produtos no carrinho : " / > <h : dataTable value = " #{ carrinhoMB . produtos } " var = " p " > <h : column > <h : outputText value = " #{ p } " / > </ h : column > <h : column > <h : commandLink action = " #{ carrinhoMB . remove ( p ) } " value = " remove " / > </ h : column > </ h : dataTable > </ h : form > </ h : body > </ html >
Cdigo XHTML 3.1: produtos.xhtml
Remova o projeto dadoWeb do Glasssh 3.1.2. Adicione o projeto carrinhoWeb no JBoss 7.1 Runtime Server. Certique-se que o Glasssh 3.1.2 esteja parado. Execute o JBoss 7.1 Runtime Server e teste a aplicao acessando a url http://localhost:8 8 /carrinhoWeb/produtos.xhtml.
6
Ciclo de Vida
As instncias dos SFSBs so administradas pelo EJB Container. Devemos entender o ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB. Para entender mais facilmente o ciclo de vida das instncias dos SFSBs, devemos sempre ter em mente que cada instncia atende apenas um cliente.
Estados
O ciclo de vida das instncias de um SFSB possui trs estados.
51
www.facebook.com/k19treinamentos
51
52
Callbacks
Podemos associar lgicas especcas nas transies de estado no ciclo de vida dos SFSBs.
@PostConstruct
Podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia logo aps ela ser criada. Esse registro realizado atravs da anotao @PostConstruct.
1 2 3 @Stateful public class CarrinhoBean {
52
www.k19.com.br
53
4 5 6 7 8 9 1 @PostConstruct public void inicializando () { System . out . println ( " Mais um carrinho criado ... " ) ; } // METODOS DE NEGOCIO }
Cdigo Java 3.14: CarrinhoBean.java
O EJB Container utiliza o construtor sem argumentos para criar uma instncia de um SLSB. Depois de chamar o construtor sem argumentos, o EJB Container injeta eventuais dependncias na instncia criada. Por m, os mtodos anotados com @PostConstruct so executados.
@PreDestroy
Tambm podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia imediatamente antes dela ser destruda. Esse registro realizado atravs da anotao @PreDestroy.
1 2 3 4 5 6 7 8 9 1 @Stateful public class CarrinhoBean { @PreDestroy public void destruindo () { System . out . println ( " Mais um carrinho ser destrudo ... " ) ; } // METODOS DE NEGOCIO }
Cdigo Java 3.15: CarrinhoBean.java
@PrePassivate
Tambm podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia imediatamente antes dela ser passivada. Esse registro realizado atravs da anotao @PrePassivate.
1 2 3 4 5 6 7 8 9 1 @Stateful public class CarrinhoBean { @PrePassivate public void passivando () { System . out . println ( " Mais um carrinho ser passivado ... " ) ; } // METODOS DE NEGOCIO }
Cdigo Java 3.16: CarrinhoBean.java
@PostActivate
Tambm podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia imediatamente depois dela ser ativada. Esse registro realizado atravs da anotao @PostActivate.
1 @Stateful
www.facebook.com/k19treinamentos
53
54
Exerccios de Fixao
1 2 3 4 5 6 7 8 9 1 11 12 13 14
package br . com . k19 . sessionbeans ; import java . util . Set ; public interface Carrinho { void adiciona ( String produto ) ; void remove ( String produto ) ; Set < String > getProdutos () ; void finalizaCompra () ; }
Cdigo Java 3.18: Carrinho.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24
@Stateful @Remote ( Carrinho . class ) public class CarrinhoBean implements Carrinho { private private private private Set < String > produtos = new HashSet < String >() ; static int contadorTotal ; static int contadorAtivos ; int id ;
54
www.k19.com.br
55
25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 72 73 74 75 76 77 78 79 8 81 82 83 84 85 86 87 88 89 } public void remove ( String produto ) { this . produtos . remove ( produto ) ; } public Set < String > getProdutos () { return produtos ; } @Remove public void finalizaCompra () { System . out . println ( " Finalizando a compra " ) ; } @PostConstruct public void postContruct () { synchronized ( CarrinhoBean . class ) { CarrinhoBean . contadorTotal ++; CarrinhoBean . contadorAtivos ++; this . id = CarrinhoBean . contadorTotal ;
System . out . println ( " PostConstruct " ) ; System . out . println ( " ID : " + this . id ) ; System . out . println ( " ContatorTotal : " + CarrinhoBean . contadorTotal ) ; System . out . println ( " ContatorAtivos : " + CarrinhoBean . contadorAtivos ) ; } } @PrePassivate public void prePassivate () { synchronized ( CarrinhoBean . class ) { CarrinhoBean . contadorAtivos - -; System . out . println ( " PrePassivate " ) ; System . out . println ( " ID : " + this . id ) ; System . out . println ( " ContatorTotal : " + CarrinhoBean . contadorTotal ) ; System . out . println ( " ContatorAtivos : " + CarrinhoBean . contadorAtivos ) ; } } @PostActivate public void postActivate () { synchronized ( CarrinhoBean . class ) { CarrinhoBean . contadorAtivos ++; System . out . println ( " PostActivate " ) ; System . out . println ( " ID : " + this . id ) ; System . out . println ( " ContatorTotal : " + CarrinhoBean . contadorTotal ) ; System . out . println ( " ContatorAtivos : " + CarrinhoBean . contadorAtivos ) ; } } @PreDestroy public void preDestroy () { synchronized ( CarrinhoBean . class ) { CarrinhoBean . contadorAtivos - -; System . out . println ( " PreDestroy " ) ; System . out . println ( " ID : " + this . id ) ; System . out . println ( " ContatorTotal : " + CarrinhoBean . contadorTotal ) ; System . out . println ( " ContatorAtivos : " + CarrinhoBean . contadorAtivos ) ; } } }
www.facebook.com/k19treinamentos
55
56
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21
10
Utilize o script add-user.sh para adicionar o usurio k19 no JBoss. Siga os passos abaixo.
cosen@k19 :~/ Desktop / jboss - as -7.1.1. Final / bin$ ./ add - user . sh What type of user do you wish to add ? a) Management User ( mgmt - users . properties ) b) Application User ( application - users . properties ) (a ): b Enter the details of the new user to add . Realm ( ApplicationRealm ) : Username : k19 Password : Re - enter Password : What roles do you want this user to belong to ? ( Please enter a comma separated list , or leave blank for none ) : About to add user k19 for realm ApplicationRealm Is this correct yes / no ? yes Added user k19 to file / home / cosen / Desktop / jboss - as -7.1.1. Final / standalone / configuration / application - users . properties Added user k19 to file / home / cosen / Desktop / jboss - as -7.1.1. Final / domain / configuration / application - users . properties
56
www.k19.com.br
57
1 2 3 4 5 6 7 8 9 1
12 Crie um Java project no eclipse. Voc pode digitar CTRL+3 em seguida new Java project e ENTER. Depois, siga exatamente as imagens abaixo.
www.facebook.com/k19treinamentos
57
58
58
www.k19.com.br
59
www.facebook.com/k19treinamentos
59
60
13
1 2 3 4 5 6
Crie uma classe chamada TesteCicloDeVisaSFSB em um pacote chamado br.com.k19.testes no projeto carrinhoJavaSE.
14
1 2 3 4 5 6 7 8 9 1 11 12 13
package br . com . k19 . testes ; import java . util . Properties ; import javax . naming . Context ; import javax . naming . InitialContext ; import br . com . k19 . sessionbeans . Carrinho ; public class TesteCicloDeVisaSFSB { public static void main ( String [] args ) throws Exception { Properties props = new Properties () ; props . put ( Context . INITIAL_CONTEXT_FACTORY ,
60
www.k19.com.br
61
14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 " org . jboss . naming . remote . client . InitialContextFactory " ) ; props . put ( Context . PROVIDER_URL , " remote ://127. . .1:4447 " ) ; props . put ( Context . SECURITY_PRINCIPAL , " k19 " ) ; props . put ( Context . SECURITY_CREDENTIALS , " 1234 " ) ; InitialContext ic = new InitialContext ( props ) ; Carrinho [] carrinhos = new Carrinho [6];
for ( int i = ; i < carrinhos . length ; i ++) { carrinhos [ i ] = ( Carrinho ) ic . lookup ( " carrinhoWeb / CarrinhoBean ! br . com . k19 . sessionbeans . Carrinho " ) ; carrinhos [ i ]. adiciona ( " Chaveiro - K19 " ) ; carrinhos [ i ]. adiciona ( " Caneta - K19 " ) ; Thread . sleep (1 ); } carrinhos [ ]. adiciona ( " Borracha - K19 " ) ; Thread . sleep (5 );
carrinhos [ ]. finalizaCompra () ; } }
Cdigo Java 3.21: TesteCicloDeVisaSFSB.java
15 Reinicie o JBoss 7.1 Runtime Server. Depois, execute a classe TesteCicloDeVisaSFSB e observe o console do servidor.
www.facebook.com/k19treinamentos
61
62
62
www.k19.com.br
CAPTULO
Uma nica instncia da classe ContadorDeUsuariosBean deve ser criada para contabilizar corretamente o nmero de usurios conectados. Alm disso, o contador de usurios conectados no precisa ser persistido entre duas execues da aplicao.
Sistema de chat
Outro exemplo, suponha o funcionamento de um sistema de chat no qual as salas so criadas dinamicamente pelos usurios durante a execuo. Podemos denir alguns mtodos para implementar esse sistema.
1 2 3 4 5 6 7 8 9 1 11 class ChatBean { private Set < String > salas = new HashSet < String >() ; public void criaSala ( String sala ) { this . salas . add ( sala ) ; } public List < String > listaSalas () { return new ArrayList < String >( this . salas ) ; } }
www.facebook.com/k19treinamentos
63
64
As salas so criadas dinamicamente e todos os usurios compartilham todas as salas. Se o sistema cair por qualquer que seja o motivo no necessrio guardar as salas pois na prxima execuo novas salas sero criadas pelos usurios. Uma nica instncia da classe ChatBean deve ser criada j que as salas sero compartilhadas entre todos os usurios.
Trnsito Colaborativo
Mais um exemplo, suponha um sistema colaborativo para informar o grau de congestionamento nas vias de uma cidade. As regras desse sistema poderiam ser implementadas atravs de alguns mtodos.
1 2 3 4 5 6 7 8 9 1 11 12 13 class TransitoBean { private Map < String , List < Integer > > vias = new HashMap < String , List < Integer > >() ; public void registra ( String via , Integer velocidade ) { if ( this . vias . containsKey ( via ) ) { this . vias . get ( via ) . add ( velocidade ) ; } } public List < Integer > getVelocidadesRegistradas ( String via ) { return this . vias . get ( via ) ; } }
Cdigo Java 4.3: TransitoBean.java
Os dados sobre o trnsito so fornecidos pelos usurios e todos podem consultar as mesmas informaes. A princpio, no necessrio manter esses dados persistidos.
Implementao
Para implementar um Singleton Session Bean podemos denir uma interface java com as assinaturas dos mtodos de negcio. Por exemplo, suponha que um Singleton Session Bean ser utilizado para implementar um sistema de chat.
1 2 3 4 public interface Chat { void criaSala ( String sala ) ; List < String > listaSalas () ; }
Cdigo Java 4.4: Chat.java
Aps denir a interface de utilizao, o segundo passo seria implementar as operaes do session bean atravs de uma classe java.
1 2 3 4 5 6 7 public class ChatBean implements Chat { private Set < String > salas = new HashSet < String >() ; public void criaSala ( String sala ) { this . salas . add ( sala ) ; }
64
www.k19.com.br
65
8 9 1 11 12
public List < String > listaSalas () { return new ArrayList < String >( this . salas ) ; } }
Cdigo Java 4.5: ChatBean.java
O terceiro passo especicar o tipo de session bean que queremos utilizar. No caso do chat, o tipo seria Singleton. Essa denio realizada atravs da anotao @Singleton.
1 2 3 4 @Singleton public class ChatBean implements Chat { ... }
Cdigo Java 4.6: ChatBean.java
Por m, necessrio denir se o session bean poder ser acessado remotamente ou apenas localmente. Quando o acesso a um session bean local, ele s pode ser acessado por aplicaes que estejam no mesmo servidor de aplicao que ele. Caso contrrio, quando o acesso a um session bean remoto, ele pode ser acessado tanto por aplicaes que estejam no mesmo servidor de aplicao quanto aplicaes que no estejam. A denio do tipo de acesso realizada atravs das anotaes: @Local e @Remote.
1 2 3 4 5 @Singleton @Remote ( Chat . class ) public class ChatBean implements Chat { ... }
Cdigo Java 4.7: ChatBean.java
1 2 3 4 5
@Singleton @Local ( Chat . class ) public class ChatBean implements Chat { ... }
Cdigo Java 4.8: ChatBean.java
www.facebook.com/k19treinamentos
65
66
Exerccios de Fixao
Para no confunr, feche os projetos carrinhoWeb e carrinhoJavaSE. Para isso, clique com o boto direito do mouse sobre esses projetos e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse para implementar o funcionamento de um sistema de chat. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
66
www.k19.com.br
67
www.facebook.com/k19treinamentos
67
68
3 Crie um pacote chamado br.com.k19.sessionbeans no projeto chatWeb e adicione a seguinte classe nesse pacote.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22
package br . com . k19 . sessionbeans ; import import import import java . util . ArrayList ; java . util . HashSet ; java . util . List ; java . util . Set ;
import javax . ejb . Singleton ; @Singleton public class ChatBean { private Set < String > salas = new HashSet < String >() ; public void criaSala ( String sala ) { this . salas . add ( sala ) ; } public List < String > listaSalas () { return new ArrayList < String >( this . salas ) ; } }
68
www.k19.com.br
69
4
Adicione o arquivo chat.xhtml na pasta WebContent do projeto chatWeb com o seguinte contedo.
5
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Chat </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Nova Sala : " / > <h : inputText value = " #{ chatMB . sala } " / > <h : commandButton value = " Criar " action = " #{ chatMB . adicionaSala } " / > < hr / > <h : dataTable value = " #{ chatMB . salas } " var = " sala " > <h : column > <h : outputText value = " #{ sala } " / > </ h : column >
www.facebook.com/k19treinamentos
69
70
Remova o projeto carrinhoWeb do JBoss 7.1 Runtime Server. Adicione o projeto chatWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /chatWeb/chat.xhtml. Utilize pelo menos dois navegadores diferentes para acessar a aplicao e observe que as mesmas salas so apresentadas nesses navegadores.
6
Ciclo de Vida
As instncias dos Singleton Session Beans so administradas pelo EJB Container. Devemos entender o de ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB. Para entender mais facilmente o ciclo de vida das instncias dos Singleton Session Beans, devemos sempre ter em mente que o EJB Container cria apenas uma instncia de cada session bean desse tipo.
Estados
O ciclo de vida das instncias dos Singleton Session Beans possui dois estados.
1. NO EXISTE 2. PRONTO
70
www.k19.com.br
71
Quando a instncia de um Singleton Session Bean criada, ela passa para do estado NO EXISTE para o estado PRONTO e pode atender as chamadas dos clientes da aplicao.
Callbacks
Podemos associar lgicas especcas nas transies de estado no ciclo de vida dos Singleton Session Beans. @PostConstruct Podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia logo aps ela ser criada. Esse registro realizado atravs da anotao @PostConstruct.
1 2 3 4 5 6 @Singleton class ContadorDeUsuariosBean { @PostConstruct public void inicializando () { System . out . println ( " Contador de usurios criado ... " ) ;
www.facebook.com/k19treinamentos
71
72
O EJB Container utiliza o construtor sem argumentos para criar a instncia de um Singleton Session Bean. Depois de chamar o construtor sem argumentos, o EJB Container injeta eventuais dependncias na instncia criada. Por m, os mtodos anotados com @PostConstruct so executados. @PreDestroy Tambm podemos registrar um mtodo de instncia no EJB Container para que ele o execute em cada instncia imediatamente antes dela ser destruda. Esse registro realizado atravs da anotao @PreDestroy.
1 2 3 4 5 6 7 8 9 1 @Singleton class ContadorDeUsuariosBean { @PreDestroy public void destruindo () { System . out . println ( " Contador de usurios ser destrudo ... " ) ; } // METODOS DE NEGOCIO }
Cdigo Java 4.14: ContadorDeUsuariosBean.java
Exerccios de Fixao
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25
import javax . annotation . PostConstruct ; import javax . annotation . PreDestroy ; import javax . ejb . Singleton ; @Singleton public class ChatBean { private Set < String > salas = new HashSet < String >() ; public void criaSala ( String sala ) { this . salas . add ( sala ) ; } public List < String > listaSalas () { return new ArrayList < String >( this . salas ) ; } @PostConstruct
72
www.k19.com.br
73
26 27 28 29 3 31 32 33 34 public void postConstruct () { System . out . println ( " Criando o ChatBean ... " ) ; } @PreDestroy public void preDestroy () { System . out . println ( " Destruindo o ChatBean ... " ) ; } }
Cdigo Java 4.15: ChatBean.java
Teste os mtodos de callback seguindo os passos abaixo. Reinicie o Glasssh 3.1.2 e observe que a mensagem de criao no aparece no console; Acesse o endereo http://localhost:8 8 /chatWeb/chat.xhtml e observe que agora a mensagem aparece no console; Tente acessar o mesmo endereo atravs de outros navegadores e repare que a mensagem de criao no aparece novamente no console. Pare o Glasssh 3.1.2 e observe no console a mensagem de destruio.
1 2 3 4 5 6
10
Concorrncia
Um Singleton Session Bean suporta acesso concorrente. Em outras palavras, a instncia de um Singleton Session Bean pode processar diversas chamadas a mtodos de negcio simultaneamente. H dois modos de gerenciamento de acesso instncia de um Singleton Session Bean: Container Managed Concurrency (CMC) Bean Managed Concurrency (BMC) O modo padro de gerenciamento o CMC. Opcionalmente, podemos declarar o modo CMC atravs da anotao @ConcurrencyManagement. Mas, lembre-se que no necessarrio pois esse o modo padro.
1 2 @Singleton @ConcurrencyManagement ( ConcurrencyManagementType . CONTAINER )
www.facebook.com/k19treinamentos
73
74
CMC
No modo CMC, todo mtodo de negcio associado ao Read Lock ou ao Write Lock. Chamadas a mtodos associados ao Read Lock podem ser executadas simultaneamente. Por outro lado, chamadas a mtodos associados ao Write Lock so executadas uma de cada vez. Por padro, no CMC, os mtodos so associados ao Write Lock. Opcionalmente, podemos declarar o tipo de Lock atravs da anotao @Lock. Mas, lembre-se que no necessrio pois o Write Lock associado aos mtodos de negcio por padro.
1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton @Lock ( LockType . WRITE ) public class ContadorDeUsuariosBean { private int contador = ; public void adiciona () { this . contador ++; } public int getContador () { return this . contador ; } }
Cdigo Java 4.19: ContadorDeUsuariosBean.java
1 2 3 4 5 6 7 8 9 1 11 12 13
@Singleton public class ContadorDeUsuariosBean { private int contador = ; @Lock ( LockType . WRITE ) public void adiciona () { this . contador ++; } public int getContador () { return this . contador ; } }
Cdigo Java 4.20: ContadorDeUsuariosBean.java
A anotao @Lock pode ser aplicada na classe do session bean ou diretamente nos mtodos de negcio.
74
www.k19.com.br
75
Para associar o Read Lock aos mtodos de negcio, devemos utilizar a anotao @Lock na classe do session bean ou nos mtodos de negcio.
1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton @Lock ( LockType . READ ) public class ContadorDeUsuariosBean { private int contador = ; public void adiciona () { this . contador ++; } public int getContador () { return this . contador ; } }
Cdigo Java 4.21: ContadorDeUsuariosBean.java
1 2 3 4 5 6 7 8 9 1 11 12 13
@Singleton public class ContadorDeUsuariosBean { private int contador = ; public void adiciona () { this . contador ++; } @Lock ( LockType . READ ) public int getContador () { return this . contador ; } }
Cdigo Java 4.22: ContadorDeUsuariosBean.java
BMC
No modo BMC, o controle de concorrncia deve ser implementado dentro dos mtodos de negcio. Voc pode utilizar a instruo synchronized ou os recursos do pacote java.util.concurrent. Para isso, voc precisa ter bons conhecimento de programao concorrente.
Exerccios de Fixao
11
1 2 3 4 5 6 7 8
12
75
76
@Singleton @Lock ( LockType . READ ) @Remote ( Contador . class ) public class ContadorBean implements Contador { private int valor ; public void incrementa () { this . valor ++; } public int getValor () { return this . valor ; } }
Cdigo Java 4.24: ContadorBean.java
Crie um Java project no eclipse. Voc pode digitar CTRL+3 em seguida new Java project e ENTER. Depois, siga exatamente as imagens abaixo.
13
76
www.k19.com.br
77
www.facebook.com/k19treinamentos
77
78
78
www.k19.com.br
79
14 Crie uma classe chamada TesteDeAcessoConcorrente em um pacote chamado br.com.k19.testes no projeto contadorJavaSE.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28
package br . com . k19 . testes ; import javax . naming . InitialContext ; import br . com . k19 . sessionbeans . Contador ; public class TesteDeAcessoConcorrente { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () ; final Contador contador = ( Contador ) ic . lookup ( " java : global / chatWeb / ContadorBean " ) ; final Thread [] threads = new Thread [2 ]; System . out . println ( " Contador = " + contador . getValor () ) ; System . out . println ( " Incrementando " + threads . length * threads . length + " vezes " ) ; for ( int i = ; i < threads . length ; i ++) { threads [ i ] = new Thread ( new Runnable () { @Override public void run () { for ( int i = ; i < threads . length ; i ++) { contador . incrementa () ; } } }) ; threads [ i ]. start () ;
www.facebook.com/k19treinamentos
79
80
Execute alguns vezes a classe TesteDeAcessoConcorrente e observe que o valor do contador no estar correto.
15
16
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22
@Singleton @Remote ( Contador . class ) public class ContadorBean implements Contador { private int valor ; public void incrementa () { this . valor ++; } @Lock ( LockType . READ ) public int getValor () { return this . valor ; } }
Cdigo Java 4.26: ContadorBean.java
Reinicie o Glasssh 3.1.2. Execute alguns vezes a classe TesteDeAcessoConcorrente e observe que o valor do contador estar correto.
17
80
www.k19.com.br
CAPTULO
P ERSISTNCIA
Data Sources
Aplicaes Java se comunicam com banco de dados atravs de conexes JDBC. Para estabelecer uma conexo JDBC, algumas informaes como usurio, senha e base de dados so necessrias. As conguraes relativas s conexes JDBC podem ser denidas nas aplicaes ou nos servidores de aplicao. Quando denidas em uma aplicao sero utilizadas somente por essa aplicao. Quando denidas em um servidor de aplicao podem ser utilizadas em diversas aplicaes. Em um servidor de aplicao, as conguraes JDBC so denidas em componentes chamados Data Sources. A criao de Data Sources depende do servidor de aplicao utilizado. Em particular, no Glasssh, os Data Sources podem ser criados atravs da interface de administrao. Os Data Sources permitem que uma nica congurao JDBC seja utilizada por diversas aplicaes. Eles tambm permitem que outros tipos de conguraes sejam compartilhadas. Por exemplo, a congurao de um Connection Pool. Alm disso, atravs de Data Sources podemos utilizar facilmente o servio de transaes dos servidores de aplicao. Esse servio denido pela especicao Java Transaction API (JTA).
Exerccios de Fixao
1 Vamos congurar um Data Source no Glasssh. Copie o arquivo mysql-connector-java-VERSAObin.jar que se encontra na pasta K19-Arquivos/MySQL-Connector-JDBC da rea de Trabalho para a pasta glassshv3/glasssh/lib.
Importante
Voc tambm pode obter o driver JDBC do MySQL atravs do site da K19: www.k19. com.br/arquivos.
Acesse o MySQL Server atravs do MySQL Workbench ou atravs do cliente de linha de comando; apague a base de dados k22_glasssh caso ela exista; crie uma base de dados chamada k22_glasssh.
2
www.facebook.com/k19treinamentos
81
P ERSISTNCIA
3
82
Reinicie o Glasssh 3.1.2; abra a interface de administrao acessando a url localhost:4848. Siga os passos abaixo:
82
www.k19.com.br
83
P ERSISTNCIA
DatabaseName: k22_glasssh
Password: root
ServerName: localhost
URL: jdbc:mysql://localhost:3306/k22_glasssh
url: jdbc:mysql://localhost:3306/k22_glasssh
User: root
Depois, clique em nish. Para testar o Connection Pool K19, siga os passos abaixo:
www.facebook.com/k19treinamentos
83
P ERSISTNCIA
84
85
P ERSISTNCIA
www.facebook.com/k19treinamentos
85
P ERSISTNCIA
4
86
Agora, vamos congurar um Data Source no JBoss. Crie uma pasta chamada mysql dentro da pasta modules/com do JBoss. Dentro da pasta mysql crie uma pasta chamada main. Copie o arquivo mysql-connector-java-VERSAO-bin.jar que se encontra na pasta K19-Arquivos/MySQLConnector-JDBC da rea de Trabalho para a pasta main.
Importante
Voc tambm pode obter o driver JDBC do MySQL atravs do site da K19: www.k19. com.br/arquivos.
1 2 3 4 5 6 7 8 9
Na linha 4, indique corretamente o nome correspondente ao arquivo do driver que voc est utilizando. Acesse o MySQL Server atravs do MySQL Workbench ou atravs do cliente de linha de comando; apague a base de dados k22_jboss caso ela exista; crie uma base de dados chamada k22_jboss.
6
7 Altere o arquivo de congurao do JBoss (standalone/conguration/standalone.xml). Adicione dentro da tag <datadources> a congurao de um novo Data Source.
...
86
www.k19.com.br
87
2 3 4 5 6 7 8 9 1 11 < datasource jndi - name = " java: / jdbc / K19 " pool - name = " K19 " jta = " true " enabled = " true " use - java - context = " true " use - ccm = " true " > < connection - url > jdbc:mysql: // localhost:33 6 / k22_jboss </ connection - url > < driver > com . mysql </ driver > < security > < user - name > root </ user - name > < password > root </ password > </ security > </ datasource > ...
Cdigo XML 5.2: standalone.xml
P ERSISTNCIA
8 Pare o Glasssh 3.1.2. Inicie o JBoss 7.1 Runtime Server e observe se o Data Source foi criado corretamente. No console, deve aparecer uma mensagem semelhante a que apresentada abaixo.
persistence.xml
Em um ambiente Java EE, diversas conguraes relativas persistncia so realizadas nos Data Sources. Contudo, algumas conguraes ainda devem ser realizadas pelas aplicaes. A especicao JPA determina que cada aplicao contenha um arquivo de conguraes chamado persistence.xml dentro de uma pasta chamada META-INF no classpath da aplicao. No arquivo persistece.xml podemos denir qual Data Source ser utilizado pela aplicao.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
www.facebook.com/k19treinamentos
87
P ERSISTNCIA
88
Entity Beans
As regras de negcio de uma aplicao EJB so implementadas nos session beans. Por outro lado, os dados da aplicao que devem ser persistidos so armazenados em objetos chamados Entity Beans. So exemplos de entity beans que poderiam formar uma aplicao: clientes produtos pedidos funcionrios fornecedores
@Entity a principal anotao do JPA. Ela que deve aparecer antes do nome de uma classe. E deve ser denida em todas as classes que tero objetos persistidos no banco de dados. As classes anotadas com @Entity so mapeadas para tabelas. Por conveno, as tabelas possuem os mesmos nomes das classes. Mas, podemos alterar esse comportamento utilizando a anotao @Table. Os atributos declarados em uma classe anotada com @Entity so mapeados para colunas na tabela correspondente classe. Outra vez, por conveno, as colunas possuem os mesmos nomes dos atributos. E novamente, podemos alterar esse padro utilizando para isso a anotao @Column. @Id Utilizada para indicar qual atributo de uma classe anotada com @Entity ser mapeado para a chave primria da tabela correspondente classe. Geralmente o atributo anotado com @Id do tipo Long. @GeneratedValue Geralmente vem acompanhado da anotao @Id. Serve para indicar que o valor de um atributo que compe uma chave primria deve ser gerado pelo banco no momento em que um novo registro inserido.
Supondo uma aplicao que administra livros e autores. As seguintes classes so exemplos de Entity Classes mapeadas com anotaes que poderiam ser utilizadas no contexto dessa aplicao:
1 2 @Entity public class Livro {
88
www.k19.com.br
89
3 4 5 6 7 8 9 1 11 12
P ERSISTNCIA
@Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) private Long id ; private String nome ; private Double preco ; // GETTERS AND SETTERS }
1 2 3 4 5 6 7 8 9 1 11 12 13
@Entity public class Autor { @Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) private Long id ; private String nome ; @ManyToMany private List < Livro > livros ; // GETTERS AND SETTERS }
Consulte a apostila do curso K21 - Persistncia com JPA 2 e Hibernate para obter detalhes sobre o mapeamento das Entity Classes http://www.k19.com.br/downloads/apostilas-java.
Exerccios de Fixao
Para no confunr, feche os projetos chatWeb e contadorJavaSE. Para isso, clique com o boto direito do mouse sobre esses projetos e selecione a opo Close Project.
9
Crie um Dynamic Web Project no eclipse chamado persistenciaWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
10
www.facebook.com/k19treinamentos
89
P ERSISTNCIA
90
90
www.k19.com.br
91
P ERSISTNCIA
www.facebook.com/k19treinamentos
91
P ERSISTNCIA
92
92
www.k19.com.br
93
P ERSISTNCIA
11
12
INF.
1 2 3 4 5 6 7 8 9 1 11 12 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties >
www.facebook.com/k19treinamentos
93
P ERSISTNCIA
13 14 15 16 17 18 19 2 < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 5.5: persistence.xml
94
Crie um pacote chamado br.com.k19.entidades no projeto persistenciaWeb e adicione nesse pacote uma Entity Class para denir os livros de uma editora.
13
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19
package br . com . k19 . entidades ; import import import import javax . persistence . Entity ; javax . persistence . GeneratedValue ; javax . persistence . GenerationType ; javax . persistence . Id ;
@Entity public class Livro { @Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) private Long id ; private String nome ; private Double preco ; // GETTERS AND SETTERS }
Cdigo Java 5.3: Livro.java
Adicione no pacote br.com.k19.entidades uma Entity Class para denir autores dos livros de uma editora.
14
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24
package br . com . k19 . entidades ; import java . util . ArrayList ; import java . util . List ; import import import import import javax . persistence . Entity ; javax . persistence . GeneratedValue ; javax . persistence . GenerationType ; javax . persistence . Id ; javax . persistence . ManyToMany ;
@Entity public class Autor { @Id @GeneratedValue ( strategy = GenerationType . IDENTITY ) private Long id ; private String nome ; @ManyToMany private List < Livro > livros = new ArrayList < Livro >() ; // GETTERS AND SETTERS }
94
www.k19.com.br
95
P ERSISTNCIA
Entity Managers
Os Entity Managers so objetos que administram os Entity Beans. As principais responsabilidade dos Entity Managers so: Recuperar as informaes armazenadas no banco de dados. Montar Entity Beans com os dados obtidos do banco de dados atravs de consultas. Sincronizar o contedo dos Entity Beans com os registros das tabelas do banco de dados. Consulte a apostila do curso Persistncia com JPA 2 para obter detalhes sobre o funcionamento dos Entity Managers http://www.k19.com.br/downloads/apostilas-java.
manager . close () ;
Por outro lado, em um ambiente Java EE, o gerenciamento dos Entity Managers pode ser atribudo ao servidor de aplicao. Nesse caso, para uma aplicao Java EE obter um Entity Manager, ela pode utilizar o recurso de Injeo de Dependncia oferecido pelo servidor de aplicao. Por exemplo, dentro de um Session Bean, podemos pedir a injeo de um Entity Manager atravs da anotao @PersistenceContext.
1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceContext private EntityManager manager ; // Resto do cdigo }
Cdigo Java 5.7: CalculadoraBean.java
95
P ERSISTNCIA
96
O mtodo createEntityManagerFactory() deve ser chamado apenas uma vez a cada execuo da aplicao. No necessrio cham-lo mais do que uma vez porque a aplicao no necessita de mais do que uma Entity Manager Factory e o custo de criao desse objeto alto. Por outro lado, em um ambiente Java EE, o controle sobre a criao das Entity Manager Factories responsabilidade do servidor de aplicao. Inclusive, o servidor de aplicao evita a criao de fbricas desnecessrias. Se uma aplicao Java EE deseja obter a Entity Manager Factory criada pelo servidor de aplicao, ela deve utilizar a anotao @PersistenceUnit para pedir a injeo desse objeto.
1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceUnit private EntityManagerFactory factory ; // Resto do cdigo }
Cdigo Java 5.9: CalculadoraBean.java
Em geral, as aplicaes Java EE no necessitam interagir diretamente com as Entity Manager Factories. Na verdade, o comum utilizar diretamente os Entity Managers que so obtidos com a anotao @PersisteceContext.
1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceContext private EntityManager manager ; // Resto do cdigo }
Cdigo Java 5.10: CalculadoraBean.java
Exerccios de Fixao
Crie um pacote chamado br.com.k19.sessionbeans no projeto persistenciaWeb e adicione nesse pacote um SLSB para funcionar como repositrio de livros.
15
1 2 3 4 5 6
package br . com . k19 . sessionbeans ; import java . util . List ; import javax . ejb . Stateless ; import javax . persistence . EntityManager ;
96
www.k19.com.br
97
7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 import javax . persistence . PersistenceContext ; import javax . persistence . TypedQuery ; import br . com . k19 . entidades . Livro ; @Stateless public class LivroRepositorio { @PersistenceContext private EntityManager manager ; public void adiciona ( Livro livro ) { this . manager . persist ( livro ) ; } public List < Livro > getLivros () { TypedQuery < Livro > query = this . manager . createQuery ( " select x from Livro x " , Livro . class ) ; return query . getResultList () ; } }
Cdigo Java 5.11: LivroRepositorio.java
P ERSISTNCIA
16 Crie um pacote chamado br.com.k19.managedbeans no projeto persistenciaWeb e adicione nesse pacote um Managed Bean para oferecer algumas aes para as telas.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39
package br . com . k19 . managedbeans ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . entidades . Livro ; import br . com . k19 . sessionbeans . LivroRepositorio ; @ManagedBean public class LivroMB { @EJB private LivroRepositorio repositorio ; private Livro livro = new Livro () ; private List < Livro > livrosCache ; public void adiciona () { this . repositorio . adiciona ( this . livro ) ; this . livro = new Livro () ; this . livrosCache = null ; } public List < Livro > getLivros () { if ( this . livrosCache == null ) { this . livrosCache = this . repositorio . getLivros () ; } return this . livrosCache ; } public Livro getLivro () { return livro ; } public void setLivro ( Livro livro ) { this . livro = livro ;
www.facebook.com/k19treinamentos
97
P ERSISTNCIA
4 41 } }
Cdigo Java 5.12: LivroMB.java
98
Crie uma tela para cadastrar livros. Adicione na pasta WebContent um arquivo chamado livros.xhtml com o seguinte contedo.
17
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Livros </ title > </ h : head > <h : body > < h1 > Novo Livro </ h1 > <h : messages / > <h : form > <h : outputLabel value = " Nome : " / > <h : inputText value = " #{ livroMB . livro . nome } " / > <h : outputLabel value = " Preo : " / > <h : inputText value = " #{ livroMB . livro . preco } " / > <h : commandButton action = " #{ livroMB . adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Livros </ h1 > <h : dataTable value = " #{ livroMB . livros } " var = " livro " > <h : column > <h : outputText value = " #{ livro . nome } " / > </ h : column > <h : column > <h : outputText value = " #{ livro . preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 5.1: livros.xhtml
Remova o projeto chatWeb do Glasssh 3.1.2. Adicione o projeto persistenciaWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /persistenciaWeb/livros.xhtml.
18
Acesse o MySQL Server atravs do MySQL Workbench ou atravs do cliente de linha de comando; Verique as tabelas geradas na base de dados k22_glasssh e seus respectivos dados.
19
20 Remova o projeto persistenciaWeb do Glasssh 3.1.2. Adicione o projeto persistenciaWeb no JBoss 7.1 Runtime Server. Certique-se que o Glasssh 3.1.2 esteja parado. Inicie o JBoss 7.1 Runtime Server e teste a aplicao acessando a url http://localhost:8 8 /persistenciaWeb/ livros.xhtml.
98
www.k19.com.br
99
21
P ERSISTNCIA
Acesse o MySQL Server atravs do MySQL Workbench ou atravs do cliente de linha de comando; Verique as tabelas geradas na base de dados k22_jboss e seus respectivos dados.
www.facebook.com/k19treinamentos
99
P ERSISTNCIA
100
100
www.k19.com.br
CAPTULO
T RANSAES
Geralmente, uma aplicao realiza diversas tarefas diferentes. Tambm comum e muitas vezes necessrio dividir as tarefa em pequenos passos. Da surge o conceito de transao. Uma transao um conjunto de passos que devem ser executados em uma ordem especca para que uma determinada tarefa seja realizada. Tipicamente, as transaes modicam informaes armazenadas em resources (bases de dados, las de mensagens, sistemas corporativos de informao - EIS, entre outros).
ACID
Alm da restrio natural de ordem, as transaes possuem outras quatro propriedades fundamentais: Atomicidade, Consistncia, Isolamento e Durabilidade. A sigla ACID utilizada para indicar a existncia dessas propriedades.
Atomicidade: Todos os passos de uma transao devem ser executados com sucesso para que a prpria transao seja executada com sucesso. Se algum passo falhar a transao falhar e todos os passos realizados at o momento da falha sero desfeitos. Consistncia: No pode existir inconsistncia nos dados da aplicao nem antes nem depois da execuo de uma transao. Ou seja, uma transao leva a aplicao de um estado consistente para outro estado consistente. Isolamento: Alteraes realizadas por uma transao no nalizada no podem afetar operaes que no fazem parte da transao. Durabilidade: Aps a conrmao de uma transao, as modicaes realizadas por ela devem ser reetidas nos resources mesmo que acontea uma falha de hardware.
JTA e JTS
www.facebook.com/k19treinamentos
101
T RANSAES
102
Todo servidor de aplicao Java EE deve oferecer suporte para as aplicaes utilizarem transaes. As especicaes relacionadas a esse tpico so: Java Transaction API - JTA e Java Transaction Service - JTS. Os documentos dessas especicaes podem ser obtidos atravs do site: www.jcp.org. A especicao Enterprise Java Beans (EJB) fortemente integrada com as especicaes JTA e JTS, simplicando bastante o trabalho dos desenvolvedores de aplicao EJB que no precisam em momento nenhum lidar diretamente com JTS e muito pouco com JTA. Na arquitetura EJB, as aplicaes podem gerenciar as transaes de dois modos:
@TransactionManagement. Mas, podemos adicion-la com o intuito de explicitar a opo de gerenciamento transacional.
Atributo Transacional
O EJB Container abre, conrma, aborta ou suspende transaes de acordo com o atributo transacional de cada mtodo dos Session Beans em modo CMT. O atributo transacional de um mtodo pode ser denido com um dos seguintes valores: REQUIRED, REQUIRES_NEW, SUPPORTS, MANDATORY, NOT_SUPPORTED e NEVER. O comportamento do EJB Container o seguinte:
102
www.k19.com.br
103
T RANSAES
Atributo Transacional REQUIRED REQUIRED REQUIRES_NEW REQUIRES_NEW SUPPORTS SUPPORTS MANDATORY MANDATORY NOT_SUPPORTED NOT_SUPPORTED NEVER NEVER
J existia uma transao aberta? NO SIM NO SIM NO SIM NO SIM NO SIM NO SIM
O que o EJB Container faz? Abre uma nova transao Usa a transao que j estava aberta Abre uma nova transao Abre uma transao e Suspende a que estava aberta No faz nada Usa a transao que j estava aberta Lana EJBTransactionRequiredException Usa a transao que j estava aberta No faz nada Suspende a que estava aberta No faz nada Lana EJBException
Quando queremos que todos os mtodos de um Session Bean possuam o mesmo atributo transacional, devemos anotar a classe com @TransactionAttribute.
1 2 3 4 5 6 @Stateful @TransactionManagement ( TransactionManagementType . CONTAINER ) @TransactionAttribute ( TransactionAttributeType . REQUIRED ) public class CarrinhoBean { ... }
Caso nenhum atributo transacional seja denido explicitamente, o EJB Container utilizar por padro o REQUIRED.
www.facebook.com/k19treinamentos
103
T RANSAES
9 1 11 12 13 context . setRollbackOnly () ; } ... } }
Cdigo Java 6.4: CarrinhoBean.java
104
A mesma anotao pode alterar o comportamento padro para rollback das Application Exceptions.
1 2 3 4 @ApplicationException ( rollback = true ) public class ValorNegativoException extends RuntimeException { }
Cdigo Java 6.6: ValorNegativoException.java
104
www.k19.com.br
105
3 4 5 public class CarrinhoBean { ... }
T RANSAES
No modo BMT, devemos injetar um UserTransaction atravs da anotao @Resource. Esse objeto permite que a aplicao abra, conrme ou aborte transaes.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 @Stateful @TransactionManagement ( TransactionManagementType . BEAN ) public class CarrinhoBean { @Resource private UserTransaction ut ; public void adiciona ( Produto p ) { try { ut . begin () ; // IMPLEMENTACAO ut . commit () ; } catch ( ProdutoInvalidoException e ) { ut . rollback () ; } catch ( Exception e ) { e . printStackTrace () ; } } }
O modo BMT permite um controle maior sobre as transaes. Contudo, o modo CMT mais simples de utilizar e mais fcil de manter.
Exerccios de Fixao
Para no confunr, feche os projetos persistenciaWeb. Para isso, clique com o boto direito do mouse sobre esse projeto e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse chamado transacoesWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
www.facebook.com/k19treinamentos
105
T RANSAES
106
106
www.k19.com.br
107
T RANSAES
www.facebook.com/k19treinamentos
107
T RANSAES
3
108
INF.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 6.1: persistence.xml
Crie um pacote chamado br.com.k19.entidades no projeto transacoesWeb e adicione nesse pacote uma Entity Class para denir os produtos de uma loja.
5
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18
package br . com . k19 . entidades ; import javax . persistence . Entity ; import javax . persistence . GeneratedValue ; import javax . persistence . Id ; @Entity public class Produto { @Id @GeneratedValue private Long id ; private String nome ; private double preco ; // GETTERS AND SETTERS }
Cdigo Java 6.9: Produto.java
Crie um pacote chamado br.com.k19.sessionbeans no projeto transacoesWeb e adicione nesse pacote um SLSB para funcionar como repositrio de produtos.
6
1 2 3 4 5 6
package br . com . k19 . sessionbeans ; import java . util . List ; import javax . annotation . Resource ; import javax . ejb . SessionContext ;
108
www.k19.com.br
109
7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 import import import import javax . ejb . Stateless ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
T RANSAES
import br . com . k19 . entidades . Produto ; @Stateless public class ProdutoRepositorio { @PersistenceContext private EntityManager manager ; @Resource private SessionContext context ; public void adiciona ( Produto produto ) { this . manager . persist ( produto ) ; if ( produto . getPreco () < ) { this . context . setRollbackOnly () ; } } public List < Produto > getProdutos () { TypedQuery < Produto > query = this . manager . createQuery ( " select x from Produto x " , Produto . class ) ; return query . getResultList () ; } }
Cdigo Java 6.10: ProdutoRepositorio.java
7 Crie um pacote chamado br.com.k19.managedbeans no projeto transacoesWeb e adicione nesse pacote um Managed Bean para oferecer algumas aes para as telas.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31
package br . com . k19 . managedbeans ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . entidades . Produto ; import br . com . k19 . sessionbeans . ProdutoRepositorio ; @ManagedBean public class ProdutoMB { @EJB private ProdutoRepositorio repositorio ; private Produto produto = new Produto () ; private List < Produto > produtosCache ; public void adiciona () { this . repositorio . adiciona ( this . produto ) ; this . produto = new Produto () ; this . produtosCache = null ; } public List < Produto > getProdutos () { if ( this . produtosCache == null ) { this . produtosCache = this . repositorio . getProdutos () ; } return this . produtosCache ;
www.facebook.com/k19treinamentos
109
T RANSAES
32 33 34 35 36 37 38 39 4 41 } public void setProduto ( Produto produto ) { this . produto = produto ; } public Produto getProduto () { return produto ; } }
Cdigo Java 6.11: ProdutoMB.java
110
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Produtos </ title > </ h : head > <h : body > < h1 > Novo Produto </ h1 > <h : form > <h : outputLabel value = " Nome : " / > <h : inputText value = " #{ produtoMB . produto . nome } " / > <h : outputLabel value = " Preo : " / > <h : inputText value = " #{ produtoMB . produto . preco } " / > <h : commandButton action = " #{ produtoMB . adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Produtos </ h1 > <h : dataTable value = " #{ produtoMB . produtos } " var = " produto " > <h : column > <h : outputText value = " #{ produto . nome } " / > </ h : column > <h : column > <h : outputText value = " #{ produto . preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 6.1: produtos.xhtml
9 Remova o projeto persistenciaWeb do JBoss 7.1 Runtime Server. Adicione o projeto transacoesWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /transacoesWeb/produtos. xhtml.
Adicione o projeto transacoesWeb no glasssh. Clique com o boto direito no glasssh da view Servers e escolha a opo Add and Remove.
10
110
www.k19.com.br
111
T RANSAES
Adicione alguns produtos e observe que produtos com preo negativo no so persistidos devido ao rollback.
www.facebook.com/k19treinamentos
111
T RANSAES
112
112
www.k19.com.br
CAPTULO
S EGURANA
Para muitas aplicaes, a segurana um aspecto obrigatrio. Da segurana podemos extrair dois processos fundamentais: Autenticao e Autorizao. O processo de autenticao consiste na identicao dos usurios atravs de algum tipo de certicado (usurio e senha). J o processo de autorizao determina o que cada usurio autenticado pode acessar dentro da aplicao. Na plataforma Java, esses dois processos so padronizados pela especicao JAAS (Java Authentication and Authorization Service).
Realms
Em um ambiente Java EE, para realizar o processo de autenticao, devemos criar um ou mais Realms. Um Realm uma base de dados na qual os usurios de uma ou mais aplicaes esto cadastrados. Infelizmente, as conguraes necessrias para criar um Realm no so padronizadas, ou seja, cada servidor de aplicao as realiza da sua prpria maneira. Veremos no exerccio como criar um Realm no Glasssh.
Exerccios de Fixao
Com o Glasssh 3.1.2 executando, abra a interface de administrao acessando a url localhost:
113
S EGURANA
114
114
www.k19.com.br
115
2
S EGURANA
Adicione um usurio chamado K19 dentro de um grupo chamado admin com a senha K19. Siga os passos abaixo:
www.facebook.com/k19treinamentos
115
S EGURANA
116
116
www.k19.com.br
117
3
S EGURANA
Repita o processo do exerccio anterior e cadastre os seguintes usurios: Usurio keizo afk Grupo admin users Senha keizo afk
Acesse o MySQL Server atravs do MySQL Workbench ou atravs do cliente de linha de comando; crie tabelas chamadas Usuario, Grupo e Usuario_Grupo na base de dados k22_glasssh.
4
1 2 3 4 5
CREATE TABLE Usuario ( nome varchar (255) NOT NULL , senha varchar (255) NOT NULL , PRIMARY KEY ( nome ) ) ENGINE = InnoDB DEFAULT CHARSET = utf8
1 2 3 4
CREATE TABLE Grupo ( nome varchar (255) NOT NULL , PRIMARY KEY ( nome ) ) ENGINE = InnoDB DEFAULT CHARSET = utf8
1 2 3 4 5 6 7 8
CREATE TABLE Usuario_Grupo ( Usuario_nome varchar (255) NOT NULL , grupos_nome varchar (255) NOT NULL , KEY fk_Usuario_Grupo_1 ( Usuario_nome ) , KEY fk_Usuario_Grupo_2 ( grupos_nome ) , CONSTRAINT fk1 FOREIGN KEY ( Usuario_nome ) REFERENCES Usuario ( nome ) , CONSTRAINT fk2 FOREIGN KEY ( grupos_nome ) REFERENCES Grupo ( nome ) ) ENGINE = InnoDB DEFAULT CHARSET = utf8
1 2 3 4 5 6 7 8 9 1
Com o Glasssh 3.1.2 executando, abra a interface de administrao acessando a url localhost: 4848. Siga os passos abaixo:
6
www.facebook.com/k19treinamentos
117
S EGURANA
118
Importante: Na prxima tela preencha as seguintes propriedades. Name: K19-Realm-JDBC Class Name: com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm JAAS Context: jdbcRealm JNDI: jdbc/K19 User Table: Usuario User Name Column: nome Password Column: senha Group Table: Usuario_Grupo Group Table User Name Column: Usuario_nome Group Name Column: grupos_nome Digest Algorithm: MD5 Password Encryption Algorithm: MD5
118
www.k19.com.br
119
S EGURANA
Exerccios de Fixao
Para no confunr, feche os projetos transacoesWeb. Para isso, clique com o boto direito do mouse sobre esse projeto e selecione a opo Close Project.
7
Crie um Dynamic Web Project no eclipse chamado segurancaWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
8
www.facebook.com/k19treinamentos
119
S EGURANA
120
120
www.k19.com.br
121
S EGURANA
www.facebook.com/k19treinamentos
121
S EGURANA
9
122
Acrescente no arquivo WebContent/WEB-INF/sun-web.xml do projeto segurancaWeb o seguinte trecho de cdigo logo aps o elemento context-root.
1 2 3 4 5 6 7 8 9 1 11 ... < security - role - mapping > < role - name > ADMIN </ role - name > < group - name > admin </ group - name > </ security - role - mapping > < security - role - mapping > < role - name > USERS </ role - name > < group - name > users </ group - name > </ security - role - mapping > ...
Cdigo XML 7.1: sun-web.xml
Essa congurao especca do Glasssh. Os grupos so utilizados pelo Glasssh e os roles pela aplicao.
Acrescente no arquivo WebContent/WEB-INF/web.xml do projeto segurancaWeb o seguinte trecho de cdigo dentro do elemento web-app.
10
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27
... < welcome - file - list > < welcome - file >/ index . xhtml </ welcome - file > </ welcome - file - list > < login - config > < auth - method > FORM </ auth - method > < realm - name >K19 - Realm </ realm - name > < form - login - config > < form - login - page >/ login . xhtml </ form - login - page > < form - error - page >/ acesso - negado . xhtml </ form - error - page > </ form - login - config > </ login - config > < security - constraint > <web - resource - collection > <web - resource - name > resources </ web - resource - name > <url - pattern > /* </ url - pattern > < http - method > GET </ http - method > < http - method > POST </ http - method > </ web - resource - collection > < auth - constraint > < role - name > ADMIN </ role - name > < role - name > USERS </ role - name > </ auth - constraint > </ security - constraint > ...
Cdigo XML 7.2: web.xml
Adicione um arquivo chamado login.xhtml na pasta WebContent do projeto segurancaWeb com seguinte contedo.
11
1 2 3 4 5
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets "
122
www.k19.com.br
123
6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Segurana </ title > </ h : head > <h : body > < form method = " post " action = " j_security_check " > Usurio : < input type = " text " name = " j_username " / > Senha : < input type = " password " name = " j_password " / > < input type = " submit " value = " Login " / > </ form > </ h : body > </ html >
Cdigo XHTML 7.1: login.xhtml
S EGURANA
12 Adicione um arquivo chamado acesso-negado.xhtml na pasta WebContent do projeto segurancaWeb com seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Segurana </ title > </ h : head > <h : body > < h1 > Acesso Negado </ h1 > <h : link outcome = " / login " value = " Tentar novamente " / > </ h : body > </ html >
Cdigo XHTML 7.2: acesso-negado.xhtml
Adicione um arquivo chamado menu.xhtml em uma pasta chamada includes dentro de WebContent/WEB-INF no projeto segurancaWeb com seguinte contedo.
13
1 2 3 4 5 6 7 8 9 1 11 12
< ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ autenticadorMB . sair } " value = " Sair " / > </ h : panelGrid > </ h : form > </ ui : composition >
Cdigo XHTML 7.3: menu.xhtml
14
123
S EGURANA
124
Crie um pacote chamado br.com.k19.managedbeans no projeto segurancaWeb e adicione nesse pacote um Managed Bean.
15
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19
package br . com . k19 . managedbeans ; import import import import javax . faces . bean . ManagedBean ; javax . faces . context . ExternalContext ; javax . faces . context . FacesContext ; javax . servlet . http . HttpSession ;
@ManagedBean public class AutenticadorMB { public String sair () { FacesContext fc = FacesContext . getCurrentInstance () ; ExternalContext ec = fc . getExternalContext () ; HttpSession session = ( HttpSession ) ec . getSession ( false ) ; session . invalidate () ; return " / login " ; } }
Cdigo Java 7.1: AutenticadorMB.java
Remova o projeto transacoesWeb do Glasssh 3.1.2. Adicione o projeto segurancaWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /segurancaWeb.
16
125
17
S EGURANA
1 2 3 4 5 6 7 8 9 1 11 12
18
19 Adicione uma pasta chamada META-INF na pasta src do projeto segurancaWeb. Na pasta META-INF, crie o arquivo persistence.xml.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 7.4: persistence.xml
20 Crie uma classe chamada Grupo em um pacote chamado br.com.k19.entidades no projeto segurancaWeb.
1 2 3 4 5 6 7 8 9 1 11 12
package br . com . k19 . entidades ; import javax . persistence . Entity ; import javax . persistence . Id ; @Entity public class Grupo { @Id private String nome ; public String getNome () {
www.facebook.com/k19treinamentos
125
S EGURANA
13 14 15 16 17 18 19 2 21 22 23 24 return nome ; } public void setNome ( String nome ) { this . nome = nome ; } @Override public String toString () { return this . nome ; } }
Cdigo Java 7.2: Grupo.java
126
21
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
@Entity public class Usuario { @Id private String nome ; private String senha ; @ManyToMany ( fetch = FetchType . EAGER ) private List < Grupo > grupos = new ArrayList < Grupo >() ; // GETTERS AND SETTERS }
Cdigo Java 7.3: Usuario.java
Crie uma classe chamada GrupoRepositorio em um pacote chamado br.com.k19.sessionbeans no projeto segurancaWeb.
22
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import javax . ejb . Stateless ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
import br . com . k19 . entidades . Grupo ; @Stateless public class GrupoRepositorio { @PersistenceContext private EntityManager manager ;
126
www.k19.com.br
127
19 2 21 22 23 24 25 26 27 public void adiciona ( Grupo g ) { this . manager . persist ( g ) ; }
S EGURANA
public List < Grupo > buscaTodos () { TypedQuery < Grupo > query = this . manager . createQuery ( " select x from Grupo x " , Grupo . class ) ; return query . getResultList () ; } }
Cdigo Java 7.4: GrupoRepositorio.java
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import javax . ejb . Stateless ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
import br . com . k19 . entidades . Usuario ; @Stateless public class UsuarioRepositorio { @PersistenceContext private EntityManager manager ;
public void adiciona ( Usuario u ) { this . manager . persist ( u ) ; } public List < Usuario > buscaTodos () { TypedQuery < Usuario > query = this . manager . createQuery ( " select x from Usuario x " , Usuario . class ) ; return query . getResultList () ; } }
Cdigo Java 7.5: UsuarioRepositorio.java
Crie uma classe chamada UsuarioMB em um pacote chamado br.com.k19.managedbeans no projeto segurancaWeb.
24
1 2 3 4 5 6 7 8 9 1 11 12 13
package br . com . k19 . managedbeans ; import import import import java . math . BigInteger ; java . security . MessageDigest ; java . security . NoSuchAlgorithmException ; java . util . List ;
import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . entidades . Grupo ; import br . com . k19 . entidades . Usuario ; import br . com . k19 . sessionbeans . GrupoRepositorio ;
www.facebook.com/k19treinamentos
127
S EGURANA
14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 72 73 74 75 76 77 78 79 8 81 82 83 import br . com . k19 . sessionbeans . UsuarioRepositorio ; @ManagedBean public class UsuarioMB { @EJB private UsuarioRepositorio usuarioRepositorio ; @EJB private GrupoRepositorio grupoRepositorio ; private Usuario usuario = new Usuario () ; private List < String > nomesDosGrupos ; private List < Usuario > usuarios ; private List < Grupo > grupos ; public void adiciona () throws NoSuchAlgorithmException { // Associando os Grupos ao novo Usurio for ( String nomeDoGrupo : this . nomesDosGrupos ) { Grupo g = new Grupo () ; g . setNome ( nomeDoGrupo ) ; this . usuario . getGrupos () . add ( g ) ; } // Criptografando a senha do novo Usurio MessageDigest md = MessageDigest . getInstance ( " MD5 " ) ; // or " SHA -1" md . update ( this . usuario . getSenha () . getBytes () ) ; BigInteger hash = new BigInteger (1 , md . digest () ) ; String senhaCriptografada = hash . toString (16) ; while ( senhaCriptografada . length () < 32) { // 4 for SHA -1 senhaCriptografada = " " + senhaCriptografada ; } this . usuario . setSenha ( senhaCriptografada ) ; // Salvando o usurio this . usuarioRepositorio . adiciona ( this . usuario ) ; this . usuario = new Usuario () ; this . usuarios = null ; } public List < Grupo > getGrupos () { if ( this . grupos == null ) { this . grupos = this . grupoRepositorio . buscaTodos () ; } return this . grupos ; } public List < Usuario > getUsuarios () { if ( this . usuarios == null ) { this . usuarios = this . usuarioRepositorio . buscaTodos () ; } return this . usuarios ; } public Usuario getUsuario () { return usuario ; } public void setUsuario ( Usuario usuario ) { this . usuario = usuario ; } public List < String > getNomesDosGrupos () { return nomesDosGrupos ; }
128
128
www.k19.com.br
129
84 85 86 87 88
S EGURANA
public void setNomesDosGrupos ( List < String > nomesDosGrupos ) { this . nomesDosGrupos = nomesDosGrupos ; } }
Cdigo Java 7.6: UsuarioMB.java
Adicione um arquivo chamado usuarios.xhtml na pasta WebContent do projeto segurancaWeb com seguinte contedo.
25
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Segurana </ title > </ h : head > <h : body > < ui : include src = " / WEB - INF / includes / menu . xhtml " / > < h1 > Novo Usuario </ h1 > <h : messages / > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome " / > <h : inputText value = " #{ usuarioMB . usuario . nome } " required = " true " / > <h : outputLabel value = " Senha " / > <h : inputSecret value = " #{ usuarioMB . usuario . senha } " required = " true " / > <h : selectManyCheckbox value = " #{ usuarioMB . nomesDosGrupos } " required = " true " > <f : selectItems value = " #{ usuarioMB . grupos } " var = " g " itemLabel = " #{ g . nome } " itemValue = " #{ g . nome } " / > </ h : selectManyCheckbox > </ h : panelGrid > <h : commandButton value = " Salvar " action = " #{ usuarioMB . adiciona } " / > </ h : form > < hr / > <h : dataTable value = " #{ usuarioMB . usuarios } " var = " u " border = " 1 " > <h : column > <f : facet name = " header " > Nome do Usurio </ f : facet > <h : outputText value = " #{ u . nome } " / > </ h : column > <h : column > <f : facet name = " header " > Grupos </ f : facet > <h : outputText value = " #{ u . grupos } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 7.5: index.xhtml
www.facebook.com/k19treinamentos
129
S EGURANA
26
130
1 2 3 4 5 6 7 8 9 1 11 12
27
Reinicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /segurancaWeb. Obs: Os usurios cadastrados no K19-Realm-JDBC so: Usurio K19 keizo afk Grupo admin admin users Senha K19 keizo afk
28
usuarios.xhtml
@RolesAllowed
Restries de acesso podem ser denidas pela anotao @RolesAllowed que pode ser aplicada na classe ou nos mtodos de um Session Bean. Se aplicada na classe valer para todos os mtodos. Se aplicada ao mesmo tempo na classe e em algum mtodo, valer as restries denidas no mtodo.
1 2 3 4 @RolesAllowed ({ " administrador " , " moderador " }) public void adiciona ( Produto produto ) { this . manager . persist ( produto ) ; }
1 2 3 4 5
@RolesAllowed ({ " administrador " , " moderador " }) @Stateful class CarrinhoBean { ... }
130
www.k19.com.br
131
S EGURANA
@PermitAll
Podemos utilizar a anotao @PermitAll para permitir que qualquer tipo de usurio tenha acesso. Para conseguir o mesmo efeito com a anotao @RolesAllowed, teramos que listar todos os Roles. Alm disso, caso um Role fosse criado ou destrudo, alteraes seriam necessrias.
1 2 3 4 @PermitAll public void adiciona ( Produto produto ) { this . manager . persist ( produto ) ; }
1 2 3 4 5
@DenyAll
O funcionamento da anotao @DenyAll exatamente o oposto da @PermitAll. Podemos utilizar a anotao @DenyAll em aplicaes que so implantadas em ambientes diferentes. Sendo que em determinados ambientes certas funcionalidades devem ser desabilitadas.
1 2 3 4 @DenyAll public void adiciona ( Produto produto ) { this . manager . persist ( produto ) ; }
1 2 3 4 5
@RunAs
Eventualmente, um Session Bean chama outro Session Bean. Suponha, que os mtodos do primeiro possam ser executados por usurios moderadores e os mtodos do segundo por administradores. Para que o primeiro Session Bean possa chamar o Segundo, temos que denir o papel de administrador para o primeiro Session Bean atravs da anotao @RunAs.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 @Stateless @RunAs ( " administrador " ) class MensagemRepositorio { @PersistenceContext private EntityManager manager ; @EJB private TopicoRepositorio topicoRepositorio ; @RolesAllowed ({ " moderador " }) public void remove ( Long id ) { Mensagem m = this . manager . find ( Mensagem . class , id ) ; this . manager . remove ( m ) ;
www.facebook.com/k19treinamentos
131
S EGURANA
15 16 17 18 19 2 21 22
132
Exerccios de Fixao
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28
package br . com . k19 . sessionbeans ; import java . util . ArrayList ; import java . util . List ; import javax . annotation . security . RolesAllowed ; import javax . ejb . Singleton ; @Singleton public class TarefasBean { private List < String > tarefas = new ArrayList < String >() ; @RolesAllowed ({ " ADMIN " , " USERS " }) public void adiciona ( String tarefa ) { this . tarefas . add ( tarefa ) ; } @RolesAllowed ({ " ADMIN " , " USERS " }) public List < String > listaTarefas () { return this . tarefas ; } @RolesAllowed ({ " ADMIN " }) public void remove ( String tarefa ) { this . tarefas . remove ( tarefa ) ; } }
Cdigo Java 7.14: TarefaBean.java
1 2 3 4 5 6 7 8 9 1
package br . com . k19 . managedbeans ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . sessionbeans . TarefasBean ; @ManagedBean
132
www.k19.com.br
133
11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 public class TarefasMB { @EJB private TarefasBean tarefasBean ; private String tarefa ; public void adiciona () { this . tarefasBean . adiciona ( this . tarefa ) ; } public void remove ( String tarefa ) { this . tarefasBean . remove ( tarefa ) ; } public List < String > getTarefas () { return this . tarefasBean . listaTarefas () ; } // GETTERS AND SETTERS }
Cdigo Java 7.15: TarefaMB.java
S EGURANA
31
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33
32
www.facebook.com/k19treinamentos
133
S EGURANA
1 2 3 4 5 6 7 8 9 1 11 12 13 < ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ autenticadorMB . sair } " value = " Sair " / > <h : commandLink action = " / usuarios " value = " Usurios " / > <h : commandLink action = " / tarefas " value = " Tarefas " / > </ h : panelGrid > </ h : form > </ ui : composition >
Cdigo XHTML 7.8: menu.xhtml
134
33
134
www.k19.com.br
CAPTULO
I NTERCEPTADORES
Uma aplicao EJB pode denir, atravs de mtodos de callback, lgicas a serem executadas pelo EJB Container quando uma instncia de um Session Bean muda de estado. O mtodo de callback PostConstruct executado quando uma instncia de um Session Bean de qualquer tipo muda do estado NO EXISTE para o PRONTO. O mtodo de callback PreDestroy executado quando uma instncia de um Session Bean muda do estado PRONTO para o NO EXISTE. O mtodo de callback PrePassivate executado quando uma instncia de um Stateful Session Bean muda do estado PRONTO para o PASSIVADO. O mtodo de callback PostActivate executado quando uma instncia de um Stateful Session Bean muda do estado PASSIVADO para o PRONTO. H um mtodo de callback para cada uma das seguintes transies: NO EXISTE->PRONTO, PRONTO->PASSIVADO, PASSIVADO->PRONTO e PRONTO->NO EXISTE. Alm dessas transies, podemos considerar que toda vez que um mtodo de negcio chamado ocorre a transio PRONTO>PRONTO. No h mtodo de callback para essa transio especial. Contudo, na arquitetura EJB, podemos utilizar a ideia de interceptadores para conseguir executar lgicas antes ou depois da execuo de um mtodo de negcio. comum utilizar interceptadores para tarefas que no esto diretamente relacionadas s regras de negcio implementadas nos Session Beans. Por exemplo, podemos implementar logging ou controle de acesso com interceptadores.
Interceptor Methods
A lgica de um interceptador denida dentro de um mtodo anotado com @AroundInvoke ou registrado atravs de XML. No h restries em relao a visibilidade desse mtodo, ou seja, ele pode ser pblico, protegido, padro ou privado. Contudo, ele deve possuir uma assinatura compatvel com o seguinte formato:
1 Object < METODO >( InvocationContext ) throws Exception
www.facebook.com/k19treinamentos
135
I NTERCEPTADORES
9 1 11 12 // VOLTA System . out . println ( " DEPOIS DO MTODO DE NEGCIO " ) ; return retornoDoMetodoDeNegocio ; }
136
Internal Interceptors
Um interceptador interno criado quando um mtodo interceptador denido dentro de um Session Bean. Cada Session Bean pode ter no mximo um interceptador interno. Um interceptador interno atua em todos os mtodos de negcio do seu respectivo Session Bean.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 @Stateless class CalculadoraBean { // MTODOS DE NEGCIO // MTODOS DE CALLBACK // MTODO INTERCEPTADOR @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { // IDA System . out . println ( " ANTES DO MTODO DE NEGCIO " ) ; // CHAMANDO O MTODO DE NEGCIO E PEGANDO O SEU RETORNO Object retornoDoMetodoDeNegocio = ic . proceed () ; // VOLTA System . out . println ( " DEPOIS DO MTODO DE NEGCIO " ) ; return retornoDoMetodoDeNegocio ; } }
Cdigo Java 8.3: CalculadoraBean.java
External Interceptors
Os interceptadores externos so criados quando um mtodo interceptador denido fora de um Session Bean em uma classe comum. Novamente, no mais do que um mtodo interceptador pode ser denido em uma mesma classe.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 class LoggingInterceptor { @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { // IDA System . out . println ( " ANTES DO MTODO DE NEGCIO " ) ; // CHAMANDO O MTODO DE NEGCIO E PEGANDO O SEU RETORNO Object retornoDoMetodoDeNegocio = ic . proceed () ; // VOLTA System . out . println ( " DEPOIS DO MTODO DE NEGCIO " ) ; return retornoDoMetodoDeNegocio ; } }
Cdigo Java 8.4: LoggingInterceptor.java
136
www.k19.com.br
137
I NTERCEPTADORES
Method-Level Interceptors
Interceptadores externos podem ser associados a mtodos de negcio atravs da anotao @Interceptors.
1 2 3 4 5 6 7 8 @Stateless class CalculadoraBean { @Interceptors ({ LoggingInterceptor . class }) public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 8.5: CalculadoraBean.java
Vrios interceptadores externos podem ser associados a um mtodo de negcio atravs da anotao @Interceptors.
1 2 3 4 5 6 7 8 @Stateless class CalculadoraBean { @Interceptors ({ LoggingInterceptor . class , SegurancaInterceptor . class }) public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 8.6: CalculadoraBean.java
Class-Level Interceptors
Interceptadores externos tambm podem ser associados a Session Beans atravs da anotao @Interceptors. Quando associado a um Session Bean, um interceptador externo ser aplicado a todos os mtodos de negcio desse Session Bean.
1 2 3 4 5 6 7 8 @Stateless @Interceptors ({ LoggingInterceptor . class }) class CalculadoraBean { public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 8.7: CalculadoraBean.java
Vrios interceptadores externos podem ser associados a um Session Bean atravs da anotao
@Interceptors.
1 2 3 4 5 6 7 8 @Stateless @Interceptors ({ LoggingInterceptor . class , SegurancaInterceptor . class }) class CalculadoraBean { public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 8.8: CalculadoraBean.java
www.facebook.com/k19treinamentos
137
I NTERCEPTADORES
138
Default Interceptors
Interceptadores externos tambm podem ser associados a mtodos de negcio atravs de conguraes adicionadas no arquivo de congurao do EJB, o ejb-jar.xml. Esse arquivo deve ser colocado em uma pasta chamada META-INF dentro do mdulo EJB da aplicao. Por exemplo, suponha que o interceptador externo denido pela classe LoggingInterceptor tenha que ser aplicado em todos os mtodos de negcio de todos os Session Beans.
1 2 3 4 < interceptor - binding > <ejb - name >* </ ejb - name > < interceptor - class > interceptadores . LoggingInterceptor </ interceptor - class > </ interceptor - binding >
Excluindo Interceptadores
Podemos excluir os Default Interceptors e os Class-Level Interceptors atravs das anotaes @ExcludeDefaultInterceptors e @ExcludeClassInterceptors respectivamente. A anotao @ExcludeDefaultInterceptors pode ser aplicada em um mtodo de negcio ou no Session Bean.
1 2 3 4 5 6 7 8 @Stateless @ExcludeDefaultInterceptors class CalculadoraBean { public double soma ( double a , double b ) { return a + b ; } }
Cdigo Java 8.9: CalculadoraBean.java
Invocation Context
138
www.k19.com.br
139
I NTERCEPTADORES
Um mtodo interceptador recebe um Invocation Context como parmetro. Atravs dos Invocation Context, os mtodos interceptadores podem acessar a instncia do Session Bean que ser utilizada para atender a chamada, descobrir qual mtodo de negcio ser executado, quais parmetros foram passados e at mesmo trocar os parmetros antes de chegar no mtodo de negcio. Veja os mtodos disponveis nessa interface.
1 2 3 4 5 6 7 8 public interface InvocationContext { public Object getTarget () ; public Method getMethod () ; public Object [] getParameters () ; public void setParameters ( Object []) ; public java . util . Map < String , Object > getContextData () ; public Object proceed () throws Exception ; }
Cdigo Java 8.11: InvocationContext.java
Exerccios de Fixao
Para no confunr, feche os projetos segurancaWeb. Para isso, clique com o boto direito do mouse sobre esse projeto e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse chamado interceptadoresWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
www.facebook.com/k19treinamentos
139
I NTERCEPTADORES
140
140
www.k19.com.br
141
I NTERCEPTADORES
www.facebook.com/k19treinamentos
141
I NTERCEPTADORES
3
142
Congure a aplicao interceptadoresWeb para utilizar o data source jdbc/K19 criado no captulo 5, adicionando o arquivo persistence.xml na pasta META-INF dentro do src do projeto interceptadoresWeb.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http :// java . sun . com / xml / ns / persistence " xmlns : xsi = " http :// www . w3 . org /2 1/ XMLSchema - instance " xsi : schemaLocation = " http :// java . sun . com / xml / ns / persistence http :// java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XHTML 8.3: persistence.xml
4 Crie um pacote chamado br.com.k19.entidades no projeto interceptadoresWeb e adicione nesse pacote um Entity Bean para modelar mensagens.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16
package br . com . k19 . entidades ; import javax . persistence . Entity ; import javax . persistence . GeneratedValue ; import javax . persistence . Id ; @Entity public class Mensagem { @Id @GeneratedValue private Long id ; private String texto ; // GETTERS AND SETTERS }
Cdigo Java 8.12: Mensagem.java
Crie um pacote chamado br.com.k19.sessionbeans no projeto interceptadoresWeb e adicione nesse pacote um SLSB para funcionar como repositrio de mensagens
5
1 2 3 4 5 6 7 8 9 1
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import javax . ejb . Stateless ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
142
www.k19.com.br
143
11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28
I NTERCEPTADORES
@Stateless public class MensagemRepositorio { @PersistenceContext private EntityManager manager ; public void adiciona ( Mensagem mensagem ) { this . manager . persist ( mensagem ) ; } public List < Mensagem > getMensagens () { TypedQuery < Mensagem > query = this . manager . createQuery ( " select x from Mensagem x " , Mensagem . class ) ; return query . getResultList () ; } }
Cdigo Java 8.13: MensagemRepositorio.java
Crie um pacote chamado br.com.k19.managedbeans no projeto interceptadoresWeb e adicione nesse pacote um Managed Bean para oferecer algumas aes para as telas.
6
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41
package br . com . k19 . managedbeans ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . entidades . Mensagem ; import br . com . k19 . sessionbeans . MensagemRepositorio ; @ManagedBean public class MensagemMB { @EJB private MensagemRepositorio repositorio ; private Mensagem mensagem = new Mensagem () ; private List < Mensagem > mensagensCache ; public void adiciona () { this . repositorio . adiciona ( this . mensagem ) ; this . mensagem = new Mensagem () ; this . mensagensCache = null ; } public List < Mensagem > getMensagens () { if ( this . mensagensCache == null ) { this . mensagensCache = this . repositorio . getMensagens () ; } return this . mensagensCache ; } public Mensagem getMensagem () { return mensagem ; } public void setMensagem ( Mensagem mensagem ) { this . mensagem = mensagem ; } }
Cdigo Java 8.14: MensagemMB.java
www.facebook.com/k19treinamentos
143
I NTERCEPTADORES
7
144
Crie uma tela para cadastrar mensagens. Adicione na pasta WebContent do projeto interceptadoresWeb um arquivo chamado mensagens.xhtml com o seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Mensagens </ title > </ h : head > <h : body > < h1 > Nova Mensagem </ h1 > <h : form > <h : outputLabel value = " Mensagem : " / > <h : inputTextarea value = " #{ mensagemMB . mensagem . texto } " / > <h : commandButton action = " #{ mensagemMB . adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Mensagens </ h1 > <h : dataTable value = " #{ mensagemMB . mensagens } " var = " mensagem " > <h : column > <h : outputText value = " #{ mensagem . id } " / > </ h : column > <h : column > <h : outputText value = " #{ mensagem . texto } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 8.4: mensagens.xhtml
Implemente um interceptador externo para realizar o logging da aplicao. Crie um pacote chamado br.com.k19.interceptadores no projeto interceptadoresWeb e adicione nesse pacote a seguinte classe.
8
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17
package br . com . k19 . interceptadores ; import javax . interceptor . AroundInvoke ; import javax . interceptor . InvocationContext ; public class LoggingInterceptor { @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { System . out . println ( " CHAMANDO O MTODO : " + ic . getMethod () ) ; Object retornoDoMetodoDeNegocio = ic . proceed () ; System . out . println ( " MTODO " + ic . getMethod () + " FINALIZADO " ) ; return retornoDoMetodoDeNegocio ; } }
Cdigo Java 8.15: LoggingInterceptor.java
144
145
I NTERCEPTADORES
guinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 <? xml version = " 1. " encoding = " UTF -8 " ? > <ejb - jar version = " 3.1 " xmlns = " http :// java . sun . com / xml / ns / javaee " xmlns : xsi = " http :// www . w3 . org /2 1/ XMLSchema - instance " xsi : schemaLocation = " http :// java . sun . com / xml / ns / javaee http :// java . sun . com / xml / ns / javaee / ejb - jar_3_1 . xsd " > < interceptors > < interceptor > < interceptor - class > br . com . k19 . interceptadores . LoggingInterceptor </ interceptor - class > </ interceptor > </ interceptors > < assembly - descriptor > < interceptor - binding > <ejb - name >* </ ejb - name > < interceptor - class > br . com . k19 . interceptadores . LoggingInterceptor </ interceptor - class > </ interceptor - binding > </ assembly - descriptor > </ ejb - jar >
Cdigo XHTML 8.5: ejb-jar.xml
10 Remova o projeto segurancaWeb do Glasssh 3.1.2. Adicione o projeto interceptadoresWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /interceptadoresWeb/mensagens.xhtml. Verique o log do Glasssh 3.1.2 para observar as mensagens do interceptador.
Implemente um interceptador externo para eliminar palavras proibidas das mensagens adicionas o logging da aplicao. Adicione no pacote br.com.k19.interceptadores do projeto interceptadoresWeb a seguinte classe.
11
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25
package br . com . k19 . interceptadores ; public class CensuraInterceptor { private List < String > palavrasProibidas = new ArrayList < String >() ; public CensuraInterceptor () { this . palavrasProibidas . add ( " coca - cola " ) ; this . palavrasProibidas . add ( " fiat " ) ; this . palavrasProibidas . add ( " sony " ) ; } @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { Object [] parameters = ic . getParameters () ; Mensagem mensagem = ( Mensagem ) parameters [ ]; for ( String palavraProibida : this . palavrasProibidas ) { String textoOriginal = mensagem . getTexto () ; String textoCensurado = textoOriginal . replaceAll ( palavraProibida , " ! CENSURADO ! " ) ; mensagem . setTexto ( textoCensurado ) ; } return ic . proceed () ; } }
www.facebook.com/k19treinamentos
145
I NTERCEPTADORES
146
Associe o interceptador de censura ao mtodo de adicionar mensagens do session bean MensagemRepositorio. No esquea de adicionar o importe da anotao import javax.interceptor.Interceptors.
12
1 2 3 4 5 6
... @Interceptors ({ CensuraInterceptor . class }) public void adiciona ( Mensagem mensagem ) { this . manager . persist ( mensagem ) ; } ...
Cdigo Java 8.17: CensuraInterceptor.java
13
mensagens.xhtml.
146
www.k19.com.br
CAPTULO
* 6 * 1 , " info " ) ; * 6 * 1 , 3 * 6 * 1 , " info " ) ;
Cdigo Java 9.3: FolhaDePagamentoBean.java
S CHEDULING
Algumas aplicaes possuem a necessidade de agendar tarefas para serem executadas periodicamente ou uma nica vez aps um determinado tempo. Por exemplo, suponha uma aplicao que calcula o salrio dos funcionrios de uma empresa de acordo com as horas registradas. Possivelmente, esse clculo deve ser realizado uma vez por ms. Outro exemplo, suponha que uma empresa vende seus produtos atravs da internet. As entregas s so realizadas aps a conrmao dos pagamentos. Quando um cliente realiza um pedido, o sistema da empresa deve esperar alguns dias para vericar se o pagamento correspondente foi realizado para que a entrega possa ser liberada.
Timers
Para agendar tarefas, podemos criar alarmes (timers) atravs do TimerService. Por exemplo, suponha que seja necessrio executar uma tarefa uma nica vez depois de 30 minutos.
1 timerService . createTimer (3
O primeiro parmentro do mtodo createTimer() quantidade de tempo que ele deve esperar para disparar e o segundo uma informao que podemos associar ao timer. Tambm, podemos criar um alarme peridico que dispara a cada 30 minutos atravs do TimerService utilizando a sobrecarga do mtodo createTimer().
1 timerService . createTimer (3
Os alarmes no podem ser criados para Stateful Session Beans. Essa funcionalidade deve ser adicionada em verses futuras da especicao Enterprise Java Beans.
Mtodos de Timeout
www.facebook.com/k19treinamentos
147
S CHEDULING
148
Quando um alarme (timer) dispara, o EJB Container executa um mtodo de timeout no Bean que criou o alarme. Para denir um mtodo de timeout devemos utilizar a anotao @Timeout.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 @Stateless class PedidoBean { @Resource private TimerService timerService ; public void registraPedido ( Pedido pedido ) { this . timerService . createTimer (5 * 24 * 6 } @Timeout public void verificaPagamento ( Timer timer ) { Pedido pedido = ( Pedido ) timer . getInfo () ; // verifica o pagamento do pedido } }
Cdigo Java 9.4: PedidoBean.java
* 6
* 1
, pedido ) ;
Timers Automticos
Na verso 3.1 da especicao Enterprise Java Beans, os alarmes podem ser criados e automaticamente associados a mtodos de timeout atravs da anotao @Schedule.
1 2 3 4 5 6 7 8 @Stateless class FolhaDePagamentoBean { @Schedule ( dayOfMonth = " 1 " ) public void calculaSalarios () { // implementacao } }
Cdigo Java 9.5: FolhaDePagamentoBean.java
Os atributos da anotao @Schedule so: Atributo second minute hour dayOfMonth Valores [0 . . . 59] [0 . . . 59] [0 . . . 23] [1 . . . 31] [-7 . . . -1] quantidade de dias para o trmino do ms. [1st, 2nd, 3rd, 4th, 5th, Last ] [Sun, Mon, Tue, Wed, Thu, Fri, Sat] [1 . . . 12] [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec ] [0 . . . 7] [Sun, Mon, Tue, Wed, Thu, Fri, Sat] ano com 4 dgitos
148
www.k19.com.br
149
1 @Schedule ( minute = " , 15 , 3 , 45 " )
S CHEDULING
@Schedule.
1 @Schedule ( second = " * " , minute = " * " , hour = " * " )
1 2
Exerccios de Fixao
Para no confunr, feche os projetos interceptadoresWeb. Para isso, clique com o boto direito do mouse sobre esse projeto e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse chamado schedulingWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
www.facebook.com/k19treinamentos
149
S CHEDULING
150
150
www.k19.com.br
151
S CHEDULING
www.facebook.com/k19treinamentos
151
S CHEDULING
3
152
Congure a aplicao schedulingWeb para utilizar o data source jdbc/K19 criado no captulo 5, adicionando o arquivo persistence.xml na pasta META-INF dentro do src do projeto schedulingWeb.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML 9.1: persistence.xml
4 Crie um pacote chamado br.com.k19.entidades no projeto schedulingWeb e adicione nesse pacote um Entity Bean para modelar produtos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18
package br . com . k19 . entidades ; import javax . persistence . Entity ; import javax . persistence . GeneratedValue ; import javax . persistence . Id ; @Entity public class Produto { @Id @GeneratedValue private Long id ; private String nome ; private double preco ; // GETTERS AND SETTERS }
Cdigo Java 9.11: Produto.java
Crie um pacote chamado br.com.k19.sessionbeans no projeto schedulingWeb e adicione nesse pacote um SLSB para funcionar como repositrio de produtos.
5
1 2 3 4 5 6 7 8
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import javax . ejb . Stateless ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
152
www.k19.com.br
153
9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28
S CHEDULING
import br . com . k19 . entidades . Produto ; @Stateless public class ProdutoRepositorio { @PersistenceContext private EntityManager manager ; public void adiciona ( Produto produto ) { this . manager . persist ( produto ) ; } public List < Produto > getProdutos () { TypedQuery < Produto > query = this . manager . createQuery ( " select x from Produto x " , Produto . class ) ; return query . getResultList () ; } }
Cdigo Java 9.12: ProdutoRepositorio.java
Crie um pacote chamado br.com.k19.managedbeans no projeto schedulingWeb e adicione nesse pacote um Managed Bean para oferecer algumas aes para as telas.
6
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41
package br . com . k19 . managedbeans ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import br . com . k19 . entidades . Produto ; import br . com . k19 . sessionbeans . ProdutoRepositorio ; @ManagedBean public class ProdutoMB { @EJB private ProdutoRepositorio repositorio ; private Produto produto = new Produto () ; private List < Produto > produtosCache ; public void adiciona () { this . repositorio . adiciona ( this . produto ) ; this . produto = new Produto () ; this . produtosCache = null ; } public List < Produto > getProdutos () { if ( this . produtosCache == null ) { this . produtosCache = this . repositorio . getProdutos () ; } return this . produtosCache ; } public void setProduto ( Produto produto ) { this . produto = produto ; } public Produto getProduto () { return produto ; } }
www.facebook.com/k19treinamentos
153
S CHEDULING
154
Crie uma tela para cadastrar produtos. Adicione na pasta WebContent do projeto schedulingWeb um arquivo chamado produtos.xhtml com o seguinte contedo.
7
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Produtos </ title > </ h : head > <h : body > < h1 > Novo Produto </ h1 > <h : form > <h : outputLabel value = " Nome : " / > <h : inputText value = " #{ produtoMB . produto . nome } " / > <h : outputLabel value = " Preo : " / > <h : inputText value = " #{ produtoMB . produto . preco } " / > <h : commandButton action = " #{ produtoMB . adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Produtos </ h1 > <h : dataTable value = " #{ produtoMB . produtos } " var = " produto " > <h : column > <h : outputText value = " #{ produto . nome } " / > </ h : column > <h : column > <h : outputText value = " #{ produto . preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 9.1: produtos.xhtml
Remova o projeto interceptadoresWeb do Glasssh 3.1.2. Adicione o projeto schedulingWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /schedulingWeb/produtos.xhtml.
8
A cada minuto um produto cadastrado deve ser escolhido e colocado em destaque. Implemente essa lgica atravs dos recursos de scheduling. Adicione a seguinte classe no pacote br.com.k19.sessionbeans do projeto schedulingWeb.
9
1 2 3 4 5 6 7
package br . com . k19 . sessionbeans ; import java . util . List ; import java . util . Random ; import javax . ejb . EJB ; import javax . ejb . Schedule ;
154
www.k19.com.br
155
8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 import javax . ejb . Singleton ; import br . com . k19 . entidades . Produto ; @Singleton public class ProdutoDestaqueBean { @EJB private ProdutoRepositorio repositorio ; private Produto produtoDestaque ; @Schedule ( second = " */5 " , minute = " * " , hour = " * " ) public void trocaProdutoDestaque () { Random gerador = new Random () ; List < Produto > produtos = this . repositorio . getProdutos () ; int i = gerador . nextInt ( produtos . size () ) ; this . produtoDestaque = produtos . get ( i ) ; } public void setProdutoDestaque ( Produto produtoDestaque ) { this . produtoDestaque = produtoDestaque ; } public Produto getProdutoDestaque () { return produtoDestaque ; } }
Cdigo Java 9.14: ProdutoDestaqueBean.java
S CHEDULING
10
1 2 3 4
11
1 2 3 4 5
12
1 2 3 4 5 6 7 8
www.facebook.com/k19treinamentos
155
S CHEDULING
156
Acesse periodicamente a url http://localhost:8 8 /schedulingWeb/produtos.xhtml para vericar que o produto em destaque muda de tempos em tempos.
13
156
www.k19.com.br
CAPTULO
10
Aplicaes corporativas costumam utilizar tanto o container WEB para a camada de apresentao quanto o container EJB para a camada de negcio. A integrao entre o container WEB e o container EJB pode ser mais facilmente realizada atravs dos recursos denidos pela especicao Contexts and Dependency Injection - CDI. Dos recursos existentes na arquitetura CDI, podemos destacar o mecanismo de Injeo de Dependncia e o gerenciamento do ciclo de vida dos objetos atravs de contextos. De acordo com a especicao CDI, os seguintes tipos de objetos possuem suporte a esses dois recursos:
Managed Beans Session Beans Objetos criados por Producer Methods Objetos disponibilizados por Producer Fields Resources (Java EE resources, Persistence Contexts, Persistence Units, Remote EJBs e Web Services)
Managed Beans
Na arquitetura Java EE, os Managed Beans so objetos gerenciados pelo container Java EE. O container deve oferecer um pequeno conjunto de servios fundamentais aos Managed Beans. A denio bsica do conceito de Managed Beans est documentada na especicao Java EE 6 Managed Beans. Contudo essa especicao permite que outras especicaes estendam a idia original de Managed Beans. No devemos confundir o conceito de Managed Beans do Java EE com o conceito de Managed Bean do JSF. Na verdade, um Managed Bean do JSF um caso particular de um Managed Bean do Java EE. A especicao CDI estende a denio de Managed Beans Na arquitetura CDI, os Managed Beans so denidos por classes que devem respeitar certas restries. Na seo 3.1.1 da especicao CDI so denidas essas restries.
www.facebook.com/k19treinamentos
157
158
As classes que se encaixam nessas restries atuam como fonte de objetos que sero administrados pelo container CDI e podero ser injetados em outros objetos.
Atributos tambm podem ser utilizados como fonte de objetos para o container Java EE. Os Producer Fields devem ser anotados com @Produces.
1 2 @Produces public List < Produto > produtos ;
EL Names
Na arquitetura CDI, pginas JSP ou JSF podem acessar objetos atravs de EL. Somente objetos com um EL Name podem ser acessados por pginas JSP ou JSF. A princpio, os seguintes tipos de objetos podem possuir um EL Name:
Managed Beans
158
www.k19.com.br
159
Session Beans Objetos criados por Producer Methods Objetos disponibilizados por Producer Fields
Devemos aplicar a anotao @Named aos objetos que devem possuir um EL Name. Utilizando essa anotao, automaticamente, os objetos recebero um EL Name que determinado de acordo com o tipo de objeto.
1 2 3 4 @Named // Managed Bean - EL Name : geradorDeApostas public class GeradorDeApostas { // implementacao }
Cdigo Java 10.3: GeradorDeApostas.java
1 2 3 4 5
@Named @Stateless // Session Bean - EL Name : geradorDeApostas public class GeradorDeApostas { // implementacao }
Cdigo Java 10.4: GeradorDeApostas.java
1 2 3 4 5 6 7 8 9 1 11
@Named @Produces // Producer Method - EL Name : listaProdutos public List < Produto > listaProdutos () { // implementacao } @Named @Produces // Producer Method - EL Name : produtos public List < Produto > getProdutos () { // implementacao }
1 2 3
@Named @Produces // Producer Field - EL Name : produtos public List < Produto > produtos ;
beans.xml
Para habilitar os recursos do CDI para os objetos de uma aplicao, necessrio adicionar um arquivo chamado beans.xml na pasta META-INF no classpath.
1 <? xml version = " 1. " encoding = " UTF -8 " ? >
www.facebook.com/k19treinamentos
159
160
Exerccios de Fixao
Para no confunr, feche os projetos schedulingWeb. Para isso, clique com o boto direito do mouse sobre esse projeto e selecione a opo Close Project.
1
Crie um Dynamic Web Project no eclipse chamado cdiWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
2
160
www.k19.com.br
161
www.facebook.com/k19treinamentos
161
162
3 Habilite os recursos do CDI adicionando um arquivo chamado beans.xml na pasta WebContent/WEBINF do projeto cdiWeb
1 2 3 4 5 6 7
<? xml version = " 1. " encoding = " UTF -8 " ? > < beans xmlns = " http :// java . sun . com / xml / ns / javaee " xmlns : xsi = " http :// www . w3 . org /2 1/ XMLSchema - instance " xsi : schemaLocation = " http :// java . sun . com / xml / ns / javaee http :// java . sun . com / xml / ns / javaee / beans_1_ . xsd " > </ beans >
Cdigo XHTML 10.1: beans.xml
4 Crie um pacote chamado br.com.k19.sessionbeans no projeto cdiWeb e adicione nesse pacote um SLSB para funcionar como lanador de moeda.
1 2 3 4 5 6 7 8 9 1 11 12
package br . com . k19 . sessionbeans ; import javax . ejb . Stateless ; import javax . inject . Named ; @Named @Stateless public class LancadorDeMoedaBean { private String resultado ; public void lanca () {
162
www.k19.com.br
163
13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 if ( Math . random () < .5) { this . resultado = " CARA " ; } else { this . resultado = " COROA " ; } } public void setResultado ( String resultado ) { this . resultado = resultado ; } public String getResultado () { return resultado ; } }
5 Crie uma tela para utilizar o lanador de moedas. Adicione na pasta WebContent do projeto cdiWeb um arquivo chamado moeda.xhtml com o seguinte contedo.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Moeda </ title > </ h : head > <h : body > < h1 > Moeda </ h1 > <h : form > <h : commandButton action = " #{ lancadorDeMoedaBean . lanca } " value = " Jogar " / > </ h : form > < h2 > Resultado : <h : outputText value = " #{ lancadorDeMoedaBean . resultado } " / > </ h2 > </ h : body > </ html >
Cdigo XHTML 10.2: moeda.xhtml
Remova o projeto schedulingWeb do Glasssh 3.1.2. Adicione o projeto cdiWeb no Glasssh 3.1.2. Certique-se que o JBoss 7.1 Runtime Server esteja parado. Inicie o Glasssh 3.1.2 e teste a aplicao acessando a url http://localhost:8 8 /cdiWeb/moeda.xhtml.
6
Crie um pacote chamado br.com.k19.managedbeans no projeto cdiWeb e adicione nesse pacote uma classe para gerar nmeros aleatrios.
7
1 2 3 4 5 6 7 8 9 1
package br . com . k19 . managedbeans ; import java . util . ArrayList ; import java . util . List ; import javax . enterprise . inject . Produces ; import javax . inject . Named ; public class GeradorDeNumeros {
www.facebook.com/k19treinamentos
163
164
Crie uma tela para utilizar o gerador de nmeros. Adicione na pasta WebContent do projeto cdiWeb um arquivo chamado numeros.xhtml com o seguinte contedo.
8
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Nmeros </ title > </ h : head > <h : body > < h1 > Nmeros </ h1 > <h : dataTable value = " #{ numeros } " var = " numero " > <h : column > <h : outputText value = " #{ numero } " / > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML 10.3: numeros.xhtml
Escopos e Contextos
Os objetos administrados pelo container CDI so armazenados em contextos. Conceitualmente, um contexto uma coleo de objetos relacionados logicamente que devem existir durante um perodo de tempo especco. A especicao CDI dene quatro contextos padres.
Request Context: Quando se trata de aplicaes Java WEB, para cada requisio HTTP um novo Request Context criado pelo container CDI e destrudo no nal do processamento da mesma requisio. Mltiplos Request Contexts podem existir simultaneamente.
164
www.k19.com.br
165
Session Context: Um Session Context est sempre associado a uma HTTP Session. Quando uma HTTP Session criada pelo container WEB, o container CDI cria um Session Context associado a essa HTTP Session. Quando uma HTTP Session destruda pelo container WEB, o container CDI tambm destri o Session Context correspondente. Mltiplos Session Contexts podem existir simultaneamente. Application Context: O container CDI cria um Application Context quando a aplicao inicializada e o destri quando a aplicao nalizada. Mltiplos Application Contexts no podem existir simultaneamente. Conversation Context: H dois tipos de Coversation Context: transient e long-running. Um Conversation Context do tipo transient se comporta de maneira muito parecida com o Request Context. Basicamente, um Conversartion do tipo long-running criado na chamada do mtodo Conversation.begin() e destrudo quando o mtodo Conversation.end() executado. Mltiplos Conversation Contexts podem existir simultaneamente.
Todo objeto administrado pelo container CDI possui um escopo. O escopo de um objeto dene em qual contexto ele ser armazenado quando criado pelo container CDI. A especicao CDI dene cinco escopos padres: Request, Session, Application, Conversation e Dependent. Objetos com escopo Request, Session, Application e Conversation so armazenados no Request Context, Session Context, Application Context e Conversation Context respectivamente. Um objeto com escopo Dependent pertence a outro objeto. O objeto dependente armazenado indiretamente em algum contexto de acordo com o escopo do objeto a qual ele pertence. As anotaes: @RequestScoped, @SessionScoped, @ApplicationScoped, @ConversationScoped e @Dependent so utilizadas para denir o escopo dos objetos. Por padro, se nenhuma anotao for denida o escopo dos objetos o Dependent.
1 2 3 4 @RequestScoped public class GeradorDeApostas { // implementacao }
Cdigo Java 10.10: GeradorDeApostas.java
1 2 3 4 5
Injection Points
Quando um objeto criado pelo container CDI, todas as dependncias so injetados pelo container nesse objeto. As dependncias so outros objetos pertencentes ao mesmo contexto do objeto que est sendo criado. Se alguma dependncia no estiver criada o container se encarrega de cri-la antes.
www.facebook.com/k19treinamentos
165
166
As dependncias de um objeto so denidas atravs de Injection Points. H trs tipos de Injection Points:
Bean Constructors
As dependncias de um objeto podem ser denidas atravs de construtores com a anotao @Inject.
1 2 3 4 5 6 7 public class CarrinhoDeCompras { @Inject public CarrinhoDeCompras ( Usuario usuario ) { } }
Cdigo Java 10.12: CarrinhoDeCompras.java
Field
As dependncias de um objeto podem ser denidas atravs de atributos com a anotao @Inject.
1 2 3 4 5 public class CarrinhoDeCompras { @Inject private Usuario usuario ; }
Cdigo Java 10.13: CarrinhoDeCompras.java
Initializer methods
As dependncias de um objeto podem ser denidas atravs de mtodos inicializadores com a anotao @Inject.
1 2 3 4 5 6 7 8 9 public class CarrinhoDeCompras { private Usuario usuario ; @Inject public void setUsuario ( Usuario usuario ) { this . usuario = usuario ; } }
Cdigo Java 10.14: CarrinhoDeCompras.java
Exerccios de Fixao
Altere o mtodo getNumeros() da classe GeradorDeNumeros do projeto cdiWeb para que ele adicione uma mensagem no console toda vez que for chamado.
10
1 2 3
...]@Named@Producespublic List<Double> getNumeros()[* System . out . println ( " GERANDO NMEROS " ) ; List < Double > numeros = new ArrayList < Double >() ; for ( int i = ; i < 5; i ++) {
166
www.k19.com.br
167
4 5 6 7 8 numeros . add ( Math . random () ) ; } return numeros ; } ...]
Acesse a url http://localhost:8 8 /cdiWeb/numeros.xhtml e depois observe as mensagens impressas no log do Glasssh 3.1.2.
11
Para evitar que o mtodo getNumeros seja chamado mais do que uma vez por requisio HTTP , utilize o Resquet Scope. No esquea de importar a anotao import javax.enterprise.context.RequestScoped;.
12
1 2 3 4 5 6 7 8 9 1
...]@Named@Produces[*@RequestScoped public List < Double > getNumeros () { System . out . println ( " GERANDO NMEROS " ) ; List < Double > numeros = new ArrayList < Double >() ; for ( int i = ; i < 5; i ++) { numeros . add ( Math . random () ) ; } return numeros ; } ...]
Cdigo Java 10.16: GeradorDeNumeros.java
Acesse novamente a url http://localhost:8 8 /cdiWeb/numeros.xhtml e depois observe as mensagens impressas no console do eclipse.
13
www.facebook.com/k19treinamentos
167
168
168
www.k19.com.br
APNDICE
P ROJETO
Neste captulo, implementaremos um pequeno projeto para praticar os conceitos discutidos nos captulos anteriores. Criaremos um sistema simples de cadastro de bugs.
Exerccios de Fixao
Crie um Dynamic Web Project no eclipse chamado bugWeb. Voc pode digitar CTRL+3 em seguida new Dynamic Web Project e ENTER. Depois, siga exatamente as imagens abaixo.
1
www.facebook.com/k19treinamentos
169
P ROJETO
170
170
www.k19.com.br
171
P ROJETO
Congure a aplicao bugWeb para utilizar o data source jdbc/K19 criado no captulo 5, adicionando o arquivo persistence.xml na pasta META-INF dentro do src do projeto bugWeb.
2
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2
<? xml version = " 1. " encoding = " UTF -8 " ? > < persistence version = " 2. " xmlns = " http: // java . sun . com / xml / ns / persistence " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / persistence http: // java . sun . com / xml / ns / persistence / persistence_2_ . xsd " > < persistence - unit name = " K19 " transaction - type = " JTA " > < provider > org . hibernate . ejb . HibernatePersistence </ provider > <jta - data - source > jdbc / K19 </ jta - data - source > < properties > < property name = " hibernate . show_sql " value = " true " / > < property name = " hibernate . format_sql " value = " true " / > < property name = " hibernate . hbm2ddl . auto " value = " update " / > < property name = " hibernate . dialect " value = " org . hibernate . dialect . MySQL5InnoDBDialect " / > </ properties > </ persistence - unit > </ persistence >
Cdigo XML A.1: persistence.xml
Habilite os recursos do CDI adicionando o arquivo beans.xml na pasta WEB-INF do projeto bugWeb.
3
www.facebook.com/k19treinamentos
171
P ROJETO
1 2 3 4 5 6 7 <? xml version = " 1. " encoding = " UTF -8 " ? > < beans xmlns = " http: // java . sun . com / xml / ns / javaee " xmlns:xsi = " http: // www . w3 . org /2 1/ XMLSchema - instance " xsi:schemaLocation = " http: // java . sun . com / xml / ns / javaee http: // java . sun . com / xml / ns / javaee / beans_1_ . xsd " > </ beans >
Cdigo XML A.2: beans.xml
172
Congure a aplicao bugWeb para que ele utilize o Realm K19-Realm criado no captulo 7, adicionando no arquivo web.xml do projeto bugWeb as conguraes necessrias.
4
1 2 3 4 5
... < login - config > < realm - name >K19 - Realm </ realm - name > </ login - config > ...
Cdigo XML A.3: web.xml
1 2 3 4 5 6 7 8 9 1 11
Crie um pacote chamado br.com.k19.entities no projeto bugWeb. Adicione nesse pacote um Entity Bean para modelar projetos e outro para modelar bugs.
6
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19
package br . com . k19 . entities ; import javax . persistence . Entity ; import javax . persistence . GeneratedValue ; import javax . persistence . Id ; @Entity public class Project { @Id @GeneratedValue private Long id ; private String name ; private String description ; public Long getId () { return id ; }
172
www.k19.com.br
173
2 21 22
P ROJETO
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22
package br . com . k19 . entities ; import import import import javax . persistence . Entity ; javax . persistence . GeneratedValue ; javax . persistence . Id ; javax . persistence . ManyToOne ;
@Entity public class Bug { @Id @GeneratedValue private Long id ; private String description ; private String severity ; @ManyToOne private Project project ; // GETTERS AND SETTERS }
Cdigo Java A.2: Bug.java
7 Crie um pacote chamado br.com.k19.sessionbeans no projeto bugWeb. Adicione nesse pacote um SLSB para funcionar como repositrio de projetos e outro para funcionar como repositrio de bugs.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import import import import javax . annotation . security . RolesAllowed ; javax . ejb . Stateless ; javax . ejb . TransactionAttribute ; javax . ejb . TransactionAttributeType ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
import br . com . k19 . entities . Bug ; import br . com . k19 . entities . Project ; @Stateless @RolesAllowed ({ " ADMIN " , " USERS " }) public class ProjectRepository { @PersistenceContext private EntityManager manager ; public void add ( Project project ) { this . manager . persist ( project ) ; } public void edit ( Project project ) { this . manager . merge ( project ) ; }
www.facebook.com/k19treinamentos
173
P ROJETO
31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 @RolesAllowed ({ " ADMIN " }) public void removeById ( Long id ) { Project project = this . manager . find ( Project . class , id ) ; TypedQuery < Bug > query = this . manager . createQuery ( " select x from Bug x where x . project = : project " , Bug . class ) ; query . setParameter ( " project " , project ) ; List < Bug > bugs = query . getResultList () ; for ( Bug bug : bugs ) { this . manager . remove ( bug ) ; } this . manager . remove ( project ) ; } @TransactionAttribute ( TransactionAttributeType . NOT_SUPPORTED ) public List < Project > findAll () { TypedQuery < Project > query = this . manager . createQuery ( " select x from Project x " , Project . class ) ; return query . getResultList () ; } @TransactionAttribute ( TransactionAttributeType . NOT_SUPPORTED ) public Project findById ( Long id ) { return this . manager . find ( Project . class , id ) ; } }
Cdigo Java A.3: ProjectRepository.java
174
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39
package br . com . k19 . sessionbeans ; import java . util . List ; import import import import import import import javax . annotation . security . RolesAllowed ; javax . ejb . Stateless ; javax . ejb . TransactionAttribute ; javax . ejb . TransactionAttributeType ; javax . persistence . EntityManager ; javax . persistence . PersistenceContext ; javax . persistence . TypedQuery ;
import br . com . k19 . entities . Bug ; @Stateless @RolesAllowed ({ " ADMIN " , " USERS " }) public class BugRepository { @PersistenceContext private EntityManager manager ; public void add ( Bug bug ) { this . manager . persist ( bug ) ; } public void edit ( Bug bug ) { this . manager . merge ( bug ) ; } @RolesAllowed ({ " ADMIN " }) public void removeById ( Long id ) { Bug bug = this . manager . find ( Bug . class , id ) ; this . manager . remove ( bug ) ; } @TransactionAttribute ( TransactionAttributeType . NOT_SUPPORTED ) public List < Bug > findAll () { TypedQuery < Bug > query = this . manager . createQuery ( " select x from Bug x " , Bug . class ) ; return query . getResultList () ;
174
www.k19.com.br
175
4 41 42 43 44 45 46 } @TransactionAttribute ( TransactionAttributeType . NOT_SUPPORTED ) public Bug findById ( Long id ) { return this . manager . find ( Bug . class , id ) ; } }
Cdigo Java A.4: BugRepository.java
P ROJETO
8 Crie um pacote chamado br.com.k19.managedbeans no projeto bugWeb. Adicione ness pacote um Managed Bean CDI para oferecer para as telas JSF as funcionalidades de CRUD relacionadas aos projetos.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52
package br . com . k19 . managedbeans ; import java . util . List ; import javax . enterprise . context . RequestScoped ; import javax . inject . Inject ; import javax . inject . Named ; import br . com . k19 . entities . Project ; import br . com . k19 . sessionbeans . ProjectRepository ; @Named @RequestScoped public class ProjectMB { @Inject private ProjectRepository projectRepository ; private Project project = new Project () ; private List < Project > projects ; public void save () { if ( this . getProject () . getId () == null ) { this . projectRepository . add ( this . getProject () ) ; } else { this . projectRepository . edit ( this . getProject () ) ; } this . project = new Project () ; this . projects = null ; } public void delete ( Long id ) { this . projectRepository . removeById ( id ) ; this . projects = null ; } public void prepareEdit ( Long id ) { this . project = this . projectRepository . findById ( id ) ; } public Project getProject () { return project ; } public List < Project > getProjects () { if ( this . projects == null ) { this . projects = this . projectRepository . findAll () ; } return projects ; } }
www.facebook.com/k19treinamentos
175
P ROJETO
176
Adicione no pacote br.com.k19.managedbeans um Managed Bean CDI para oferecer para as telas JSF as funcionalidades de CRUD relacionadas aos bugs.
9
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6
package br . com . k19 . managedbeans ; import java . util . List ; import javax . enterprise . context . RequestScoped ; import javax . inject . Inject ; import javax . inject . Named ; import import import import br . com . k19 . entities . Bug ; br . com . k19 . entities . Project ; br . com . k19 . sessionbeans . BugRepository ; br . com . k19 . sessionbeans . ProjectRepository ;
@Named @RequestScoped public class BugMB { @Inject private BugRepository bugRepository ; @Inject private ProjectRepository projectRepository ; private Bug bug = new Bug () ; private Long projectId ; private List < Bug > bugs ; public void save () { Project project = this . projectRepository . findById ( this . projectId ) ; this . bug . setProject ( project ) ; if ( this . getBug () . getId () == null ) { this . bugRepository . add ( this . getBug () ) ; } else { this . bugRepository . edit ( this . getBug () ) ; } this . bug = new Bug () ; this . bugs = null ; } public void delete ( Long id ) { this . bugRepository . removeById ( id ) ; this . bugs = null ; } public void prepareEdit ( Long id ) { this . bug = this . bugRepository . findById ( id ) ; } public Bug getBug () { return bug ; } public List < Bug > getBugs () { if ( this . bugs == null ) { this . bugs = this . bugRepository . findAll () ; } return bugs ;
176
www.k19.com.br
177
61 62 63 64 65 66 67 68 69 7 } public void setProjectId ( Long projectId ) { this . projectId = projectId ; } public Long getProjectId () { return projectId ; } }
Cdigo Java A.6: BugMB.java
P ROJETO
10 Adicione no pacote br.com.k19.managedbeans um Managed Bean CDI para implementar o processo de login e logout.
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33
package br . com . k19 . managedbeans ; import import import import import javax . enterprise . context . RequestScoped ; javax . faces . context . FacesContext ; javax . inject . Named ; javax . servlet . ServletException ; javax . servlet . http . HttpServletRequest ;
@Named @RequestScoped public class AuthenticatorMB { private String username ; private String password ; public String login () throws ServletException { FacesContext context = FacesContext . getCurrentInstance () ; HttpServletRequest request = ( HttpServletRequest ) context . getExternalContext () . getRequest () ; request . login ( this . username , this . password ) ; return " / projects " ; } public String logout () throws ServletException { FacesContext context = FacesContext . getCurrentInstance () ; HttpServletRequest request = ( HttpServletRequest ) context . getExternalContext () . getRequest () ; request . logout () ; return " / login " ; } // GETTERS AND SETTERS }
Cdigo Java A.7: AuthenticatorMB.java
Crie um pacote chamado br.com.k19.lters no projeto bugWeb. Adicione nesse pacote um Filtro para vericar a autenticao dos usurios.
11
1 2 3 4 5 6 7 8
package br . com . k19 . filters ; import java . io . IOException ; import import import import javax . servlet . FilterChain ; javax . servlet . FilterConfig ; javax . servlet . ServletException ; javax . servlet . ServletRequest ;
www.facebook.com/k19treinamentos
177
P ROJETO
9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38 import import import import javax . servlet . ServletResponse ; javax . servlet . annotation . WebFilter ; javax . servlet . http . HttpServletRequest ; javax . servlet . http . HttpServletResponse ;
178
@WebFilter ( servletNames = { " Faces Servlet " }) public class AuthenticatorFilter implements javax . servlet . Filter { @Override public void doFilter ( ServletRequest request , ServletResponse response , FilterChain chain ) throws IOException , ServletException { HttpServletRequest req = ( HttpServletRequest ) request ; if ( req . getRemoteUser () == null && ! req . getRequestURI () . endsWith ( req . getContextPath () + " / login . xhtml " ) ) { HttpServletResponse res = ( HttpServletResponse ) response ; res . sendRedirect ( req . getContextPath () + " / login . xhtml " ) ; } else { chain . doFilter ( request , response ) ; } } @Override public void init ( FilterConfig filterConfig ) throws ServletException { } @Override public void destroy () { } }
Cdigo Java A.8: AuthenticatorFilter.java
Crie um menu para as telas da aplicao bugWeb. Adicione um arquivo chamado menu.xhtml na pasta WebContent do projeto bugWeb.
12
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15
< ui : composition xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ authenticatorMB . logout } " > logout </ h : commandLink > <h : outputLink value = " #{ request . contextPath }/ projects . xhtml " > Projects </ h : outputLink > <h : outputLink value = " #{ request . contextPath }/ bugs . xhtml " > Bugs </ h : outputLink > </ h : panelGrid > </ h : form > </ ui : composition >
Cdigo XHTML A.1: menu.xhtml
13 Crie um tela de login na aplicao bugWeb. Adicione um arquivo chamado login.xhtml na pasta WebContent do projeto bugWeb.
1 2 3 4
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml "
178
www.k19.com.br
179
5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Login </ title > </ h : head > <h : body > < h1 > Login </ h1 > <h : form > <h : panelGrid > <h : outputLabel value = " Username : " / > <h : inputText value = " #{ authenticatorMB . username } " / > <h : outputLabel value = " Password : " / > <h : inputSecret value = " #{ authenticatorMB . password } " / > <h : commandButton action = " #{ authenticatorMB . login } " value = " login " / > </ h : panelGrid > </ h : form > </ h : body > </ html >
Cdigo XHTML A.2: login.xhtml
P ROJETO
Crie uma tela para administrar os projetos. Adicione um arquivo chamado projects.xhtml na pasta WebContent do projeto bugWeb.
14
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 38
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Projects </ title > </ h : head > <h : body > < ui : include src = " / menu . xhtml " / > < hr / > < h1 > New Project </ h1 > <h : form > <h : panelGrid > <h : inputHidden value = " #{ projectMB . project . id } " / > <h : outputLabel value = " Name : " / > <h : inputText value = " #{ projectMB . project . name } " / > <h : outputLabel value = " Description : " / > <h : inputTextarea value = " #{ projectMB . project . description } " / > <h : commandButton action = " #{ projectMB . save } " value = " Save " / > </ h : panelGrid > </ h : form > < hr / > < h1 > Project List </ h1 > <h : dataTable value = " #{ projectMB . projects } " var = " project " rendered = " #{ not empty projectMB . projects } " border = " 1 " > <h : column >
www.facebook.com/k19treinamentos
179
P ROJETO
39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 <f : facet name = " header " > Id </ f : facet > #{ project . id } </ h : column > <h : column > <f : facet name = " header " > Name </ f : facet > #{ project . name } </ h : column > <h : column > <f : facet name = " header " > Description </ f : facet > #{ project . description } </ h : column >
180
<h : column > <f : facet name = " header " > Delete </ f : facet > <h : form > <h : commandLink action = " #{ projectMB . delete ( project . id ) } " > delete </ h : commandLink > </ h : form > </ h : column > <h : column > <f : facet name = " header " > Edit </ f : facet > <h : form > <h : commandLink action = " #{ projectMB . prepareEdit ( project . id ) } " > edit </ h : commandLink > </ h : form > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML A.3: projects.xhtml
Crie uma tela para administrar os bugs. Adicione um arquivo chamado bugs.xhtml na pasta WebContent do projeto bugWeb.
15
1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " > <h : head > < title > Bugs </ title > </ h : head > <h : body > < ui : include src = " / menu . xhtml " / > < hr / > < h1 > New Bug </ h1 > <h : form > <h : panelGrid > <h : inputHidden value = " #{ bugMB . bug . id } " / > <h : outputLabel value = " Severity : " / > <h : selectOneMenu value = " #{ bugMB . bug . severity } " > <f : selectItem itemValue = " LOW " / > <f : selectItem itemValue = " MEDIUM " / > <f : selectItem itemValue = " HIGH " / > </ h : selectOneMenu >
180
www.k19.com.br
181
31 32 33 34 35 36 37 38 39 4 41 42 43 44 45 46 47 48 49 5 51 52 53 54 55 56 57 58 59 6 61 62 63 64 65 66 67 68 69 7 71 72 73 74 75 76 77 78 79 8 81 82 83 <h : outputLabel value = " Description : " / > <h : inputTextarea value = " #{ bugMB . bug . description } " / > <h : outputLabel value = " Project : " / > <h : selectOneMenu value = " #{ bugMB . projectId } " > <f : selectItems value = " #{ projectMB . projects } " var = " project " itemLabel = " #{ project . name } " itemValue = " #{ project . id } " / > </ h : selectOneMenu > <h : commandButton action = " #{ bugMB . save } " value = " Save " / > </ h : panelGrid > </ h : form > < hr / > < h1 > Bug List </ h1 > <h : dataTable value = " #{ bugMB . bugs } " var = " bug " rendered = " #{ not empty bugMB . bugs } " border = " 1 " > <h : column > <f : facet name = " header " > Id </ f : facet > #{ bug . id } </ h : column > <h : column > <f : facet name = " header " > Project </ f : facet > #{ bug . project . name } </ h : column > <h : column > <f : facet name = " header " > Severity </ f : facet > #{ bug . severity } </ h : column > <h : column > <f : facet name = " header " > Description </ f : facet > #{ bug . description } </ h : column > <h : column > <f : facet name = " header " > Delete </ f : facet > <h : form > <h : commandLink action = " #{ bugMB . delete ( bug . id ) } " > delete </ h : commandLink > </ h : form > </ h : column > <h : column > <f : facet name = " header " > Edit </ f : facet > <h : form > <h : commandLink action = " #{ bugMB . prepareEdit ( bug . id ) } " > edit </ h : commandLink > </ h : form > </ h : column > </ h : dataTable > </ h : body > </ html >
Cdigo XHTML A.4: bugs.xhtml
P ROJETO
Crie uma tela para os erros internos e os erros de autorizao. Adicione um arquivo chamado error.xhtml na pasta WebContent do projeto bugWeb.
16
1 2 3 4 5 6 7 8
<! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Transitional // EN " " http :// www . w3 . org / TR / xhtml1 / DTD / xhtml1 - transitional . dtd " > < html xmlns = " http :// www . w3 . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . sun . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / core " >
www.facebook.com/k19treinamentos
181
P ROJETO
9 1 11 12 13 14 15 16 <h : head > < title > Error </ title > </ h : head > <h : body > < h3 > Internal Error or Client not authorized for this invocation . </ h3 > </ h : body > </ html >
Cdigo XHTML A.5: error.xhtml
182
Congure a pgina de erro no arquivo web.xml do projeto bugWeb. Adicione o seguinte trecho de cdigo nesse arquivo.
17
1 2 3 4
< error - page > < exception - type > java . lang . Exception </ exception - type > < location >/ error . xhtml </ location > </ error - page >
Cdigo XML A.5: web.xml
18
Teste a aplicao!!!
182
www.k19.com.br