You are on page 1of 192

TREINAMENTOS

Desenvolvimento Web Avançado com JSF2, EJB3.1 e CDI

Desenvolvimento Web Avançado com JSF2, EJB3.1 e CDI

15 de abril de 2013

Sumário Sobre a K19 Seguro Treinamento Termo de Uso Cursos 1 Enterprise JavaBeans 1.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 EJB Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 Exercícios de Fixação . . . . . . 2.7 Cliente Java Web Local - EJB 3.1 2.8 Exercícios de Fixação . . . . . . 2.9 Cliente Java SE Remoto . . . . . 2.10 Exercícios de Fixação . . . . . . 2.11 Ciclo de Vida . . . . . . . . . . . 2.12 Escalabilidade e Pool . . . . . . 2.13 Callbacks . . . . . . . . . . . . . 2.14 Exercícios de Fixação . . . . . . 2.15 Métodos Assíncronos . . . . . . 2.16 Exercícios de Fixação . . . . . . 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

2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3

. . . . . . . . . . 6 Transações 6. . . . . . . . . . . . . . . . . . . . . . . . .6 Concorrência . . . . . . . . . . . . . . . . .1 Data Sources . . . . . . . . . . . . . . . . . . . . . . . . .br . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Segurança 7. . . .4 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .xml . . . . . . . SFSB . . . .2 Exercícios de Fixação . . . .S UMÁRIO ii 3. . . . .3 External Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . . . .2 Transação Local ou Distribuída .2 3. . . . . . . .com. . . . . . . . 6. . . . . . . . . . . . . . . . . . Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . 8. . 8. . . . . . . . . . . . . . . . . . . . 5. . . . . . . . . . . . .7 Entity Managers . . . . . .EJB 3. . . . . .6 Exercícios de Fixação . . . . . . . 6. . . . . . . . . . . . . . . . . .5 Exercícios de Fixação . . . . . . . . . 7. . . . . . . . . . . 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Autenticação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5 Autorização . .4 Entity Beans . . . . . . . . . 5. . . Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . .EJB 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .BMT . 8. . Interceptadores 8. . . . .4 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 ACID . . .5 3. . . . . . . . . . 4. . . . . . . . . . . . . . 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7 4 Caracterizando os SFSBs SFSB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .2 Internal Interceptors . . . . . . . . . . . .4 Excluindo Interceptadores 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . .3 3.Aplicações EJB . . . . . . . . .8 Entity Manager Factories . . . . . . . . . . . . . .5 Invocation Context . . . . . . . . . . . . . . . . . . . . . . . . . .4 Container Managed Transactions . . . . . 6. . . . . 8 . . . . . . . . . . . . . Callbacks . . 4. . . . . . . . . . .k19. . . . . . . . . . . . . . . . . . . . . .5 Entity Classes e Mapeamento 5. . . . . .2 Implementação . . . . . . . . . . . . . . . . . . . . . 7 . . . . . . . . . . .5 Bean Managed Transactions . . . . . . .1 Interceptor Methods . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ciclo de Vida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 . 5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .0 . . .6 Exercícios de Fixação . . . . . .6 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7. . 6. . . . . . . . . . . . . . . . . . . . . . . .Aplicações Web 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .4 Ciclo de Vida . . . . . . .2 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .9 Exercícios de Fixação . 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4. .1 Caracterizando os Singleton Session Beans 4. . . . . .7 Exercícios de Fixação . . . . . . . . .3 persistence. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 JTA e JTS . 7.6 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5. . . . . . . . . . . . . . . . . . . . . ii www. . . . . . . . .1 Realms . . . . . . . . . . . . . . . . . . . . . . . . . . . .CMT 6. . Persistência 5. . . . . . . . . . . . . . . . 5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 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. . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . 169 www. . . . . . . . .4 beans. . . . . . . . . . . . 10. . . . . . . . . 10. . .1 Managed Beans . . . . . . . . . . . . . . .7 9 Ordem dos Interceptadores . . . . . . . . . . . . . . . . . . . .6 8. . . . 10. . . . . . . . . . . . A Projeto 169 A. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9. . . . . . . . . . . . . . . . . . .2 Producer Methods and Fields . . . . . . .3 EL Names . . . . . . . . . . . . . . . . . . .com/k19treinamentos iii . . . . . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . . . .7 Injection Points . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Contexts and Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Escopos e Contextos . . . . . . . . 9. . . . . . . . . . . . . . . . . . . . . 10. . . . . . . . . . . . . . . .xml . . . . . . . . . . . . 139 147 147 147 148 149 157 157 158 158 159 160 164 165 166 Scheduling 9. . . . . . . . . . . . . . . . . . . . . . . .2 Métodos de Timeout 9. . . .5 Exercícios de Fixação .8 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . . . . . .facebook. . . . .1 Exercícios de Fixação . . . 139 Exercícios de Fixação . . . . . . . .1 Timers . . . . . .iii S UMÁRIO 8. . . . . . . . . . . . . . . . . . . . . . . . .CDI 10. . . . .3 Timers Automáticos . . . . . . . . . . . . . . . . . . . . . . .4 Exercícios de Fixação . . . . . . . . . . . . . . . . . . . .

com.S UMÁRIO iv iv www.br .k19.

O principal objetivo da K19 é oferecer treinamentos de máxima qualidade e relacionados às principais tecnologias utilizadas pelas empresas.facebook. Através desses treinamentos.com/k19treinamentos 1 . Sua equipe é composta por profissionais formados em Ciência da Computação pela Universidade de São Paulo (USP) e que possuem vasta experiência em treinamento de profissionais para área de TI. www. oferece instalações físicas apropriadas para o ensino e seus instrutores estão sempre atualizados didática e tecnicamente. a K19 mantém as suas apostilas em constante renovação e melhoria. Visando a máxima qualidade.1 S UMÁRIO Sobre a K19 A K19 é uma empresa especializada na capacitação de desenvolvedores de software. seus alunos se tornam capacitados para atuar no mercado de trabalho.

O valor da franquia para utilizar o Seguro Treinamento é 10% do valor total do curso. Ao contratar um curso.k19.br . a K19 é a única que possui o Seguro Treinamento. 2 www.S UMÁRIO 2 Seguro Treinamento Na K19 o aluno faz o curso quantas vezes quiser! Comprometida com o aprendizado e com a satisfação dos seus alunos. o aluno poderá refazê-lo quantas vezes desejar mediante a disponibilidade de vagas e pagamento da franquia do Seguro Treinamento.com. As vagas não preenchidas até um dia antes do início de uma turma da K19 serão destinadas ao alunos que desejam utilizar o Seguro Treinamento.

www.com/k19treinamentos 3 . este material didático pode ser utilizado como material de apoio em cursos de ensino superior desde que a instituição correspondente seja reconhecida pelo MEC (Ministério da Educação) e que a K19 seja citada explicitamente como proprietária do material. A apostila pode ser utilizada livremente para estudo pessoal . O uso indevido está sujeito às medidas legais cabíveis.3 S UMÁRIO Termo de Uso Termo de Uso Todo o conteúdo desta apostila é propriedade da K19 Treinamentos. da K19 Treinamentos.facebook. por escrito. Além disso. É proibida qualquer utilização desse material que não se enquadre nas condições acima sem o prévio consentimento formal.

com. EJB3.Desenvolvimento Web com ASP. JMS e EJB K41 .SQL e Modelo Relacional K11 .Desenvolvimento Mobile com Android K51 .1 e CDI K23 .Desenvolvimento Web com Struts K31 .Lógica de Programação K02 .Integração de Sistemas com Webservices.NET MVC www.com.Orientação a Objetos em Java K12 .C# e Orientação a Objetos K32 .br .S UMÁRIO 4 TR S TO EN AM EIN TREINAMENTOS TR EIN AM EN TO S Conheça os nossos cursos K01.Desenvolvimento Web Avançado com JFS2. CSS e JavaScript K03 .Desenvolvimento Web com JSF2 e JPA2 K21 .k19.Design Patterns em Java K52 .Persistência com JPA2 e Hibernate K22 .br/cursos 4 www.k19.Desenvolvimento Web com HTML.

Remotabilidade: Aplicações EJB podem ser acessadas remotamente através de diversos protocolos de comunicação. Transações: A arquitetura EJB define um suporte sofisticado para utilização de transações.facebook. EJB Container Toda aplicação EJB é executada e gerenciada por um EJB Container. Gerenciamento de Objetos: Mecanismos de injeção de dependências e controle de ciclo de vida são oferecidos aos objetos de uma aplicação EJB. Os desenvolvedores das aplicações não precisam implementar a lógica de segurança pois ela faz parte da arquitetura EJB. Consequentemente. Ao utilizar essa arquitetura. Exercícios de Fixação www. Esse suporte é integrado com a Java Transaction API (JTA) e oferece inclusive a possibilidade de realizar transações distribuídas.CAPÍTULO E NTERPRISE J AVA B EANS 1 Introdução Muitos sistemas corporativos são desenvolvidos seguindo a arquitetura definida pelo padrão Enterprise JavaBeans (EJB). Podemos. facilmente integrar os recursos do JSF em uma aplicação EJB. O mecanismo de controle de ciclo de vida pode garantir a escalabilidade de uma aplicação. diversos recursos são disponibilizados a esses sistemas. Multithreading e Concorrência: A arquitetura EJB permite que as aplicações sejam acessados por múltiplos usuários simultaneamente de maneira controlada para evitar problemas de concorrência. Por exemplo. é possível desenvolver aplicações clientes de diversos tipos. Segurança: Suporte para realizar autenticação e autorização de forma transparente. Há diversas opções de EJB Container disponíveis. podemos utilizá-los para executar as nossas aplicações EJB.com/k19treinamentos 1 . por exemplo. aplicações EJB podem ser como Web Services. Integração: A arquitetura EJB é fortemente integrada com os componentes da plataforma Java EE. Portanto. Os servidores de aplicação Java EE como o Glassfish e o JBoss possuem um EJB Container. Persistência: Facilidades para utilizar os serviços dos provedores de persistência que seguem a especificação JPA.

zip da pasta K19-Arquivos para a sua Área de Trabalho e descompacte-o.E NTERPRISE J AVA B EANS 2 Copie o arquivo glassfish-VERSAO-with-hibernate.k19. 2 Importante Você também pode obter o arquivo jboss-as-VERSAO-Final. .br . No Eclipse.zip através do site da K19: www. 1 Importante Você também pode obter o arquivo glassfish-VERSAO-with-hibernate. . 3 Siga as imagens abaixo para configurar e testar o Glassfish.zip da pasta K19-Arquivos para a sua Área de Trabalho e descompacte-o.com.k19.com.k19.br/arquivos.zip através do site da K19: www.com.br/arquivos. 2 www. Copie o arquivo jboss-as-VERSAO-Final.

facebook.3 E NTERPRISE J AVA B EANS www.com/k19treinamentos 3 .

br .k19.E NTERPRISE J AVA B EANS 4 4 www.com.

facebook.5 E NTERPRISE J AVA B EANS www.com/k19treinamentos 5 .

E NTERPRISE J AVA B EANS 6 6 www.com.k19.br .

facebook.7 E NTERPRISE J AVA B EANS www.com/k19treinamentos 7 .

. 8 www.E NTERPRISE J AVA B EANS 4 8 Siga as imagens abaixo para configurar e testar o JBoss.k19.br . Pare o Glassfish antes de testar o JBoss No Eclipse. .com.

com/k19treinamentos 9 .9 E NTERPRISE J AVA B EANS www.facebook.

E NTERPRISE J AVA B EANS 10 10 www.br .k19.com.

com/k19treinamentos 11 .11 E NTERPRISE J AVA B EANS www.facebook.

br .E NTERPRISE J AVA B EANS 12 12 www.k19.com.

Vejamos alguns exemplos a seguir. Cada aplicação possui as suas próprias regras de negócio já que elas são consequência imediata do contexto da aplicação. Serviço de Câmbio Considere um sistema de conversão monetária. O EJB Container administra esses componentes oferecendo diversos recursos a eles. String moedaOrigem . 1 2 3 public String getDefinicao ( String palavra ) { // lógica do dicionario } www. as regras de negócio são implementadas em componentes específicos que são chamados de Session Beans. Esse sistema é capaz de converter valores monetários de uma moeda para outra. Caracterizando os SLSBs Stateless Session Bean é o primeiro tipo de Session Bean. entre outros. implementar essa regra de negócio através do método a seguir. Esses procedimentos são chamados de regras de negócio. 1 2 3 public double converte ( double valor . utilizaremos a sigla SLSB para fazer referência a esse tipo de componente. saques. Utilizando a arquitetura EJB.com/k19treinamentos 13 . Por exemplo. Dado uma palavra. converter 100 reais para o valor correspondente em dólar americano. Dicionário Considere a implementação de um dicionário digital de português. Em outras palavras. Por exemplo. Podemos criar um método para implementar essa regra de negócio. A característica fundamental dos SLSBs é que eles não armazenam estado conversacional. empréstimos. Muitas vezes. o dicionário digital deve devolver a definição dela. Poderíamos. o método converte() não precisa manter estado conversacional. cobranças. String moedaDestino ) { // lógica da conversão monetária } A execução do método converte() não depende das suas execuções anteriores. um sistema bancário possui processos específicos para realizar transferências.facebook.CAPÍTULO S TATELESS S ESSION B EANS 2 Session Beans Um sistema corporativo é composto por muitos processos ou tarefas. depósitos.

Dessa forma. Em outras palavras.EJB 3. Consulta de CEP Considere um sistema de consulta de CEP.java 14 www. double multiplica ( double a .b . double b ) . double b ) { return a * b . não é necessário manter estado conversacional. Uma possível interface para esse SLSB seria: 1 2 3 4 5 6 public interface Calculadora { double soma ( double a . String logradouro . 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 ) .4: Calculadora.S TATELESS S ESSION B EANS 14 As chamadas ao método getDefinicao() são totalmente independentes. } public double divide ( double a . suponha um SLSB que realiza operações matemáticas. Integer ← numero ) { // lógica da consulta do CEP } Como cada consulta de CEP independe das consultas anteriores. não é necessário manter dados entre uma consulta e outra. String cidade . } Código Java 2.br . SLSB . Ou seja. não é necessário manter estado conversacional. 1 2 3 public String consultaCEP ( String estado . Por exemplo. o segundo passo seria implementar as operações do SLSB através de uma classe. Depois da interface.k19.0 O primeiro passo para implementar um SLSB é definir os seus métodos de negócio através de uma interface. double b ) { return a + b . double subtrai ( double a .java Os métodos contidos na interface Calculadora são chamados de métodos de negócio. double divide ( double a . double b ) . } public double multiplica ( double a . double b ) .5: CalculadoraBean. } } Código Java 2. } public double subtrai ( double a . Esse sistema é capaz de informar o CEP de uma determinada localidade. não é necessário guardar informações referentes às chamadas anteriores. double b ) { return a / b .com. double b ) { return a . Podemos criar um método para implementar essa regra de negócio.

7: CalculadoraBean. apenas quem está dentro do servidor de aplicação no qual se encontra o SLSB pode acessá-lo.. não é mais necessário definir uma interface java nem utilizar a anotação @Local. 1 2 3 4 5 6 7 8 9 1 11 12 @Stateless public class CalculadoraBean { public double soma ( double a . Quando o acesso é local. double b ) { return a + b . o tipo seria SLSB. Essa definição é realizada através da anotação @Stateless. } Código Java 2.1 Observe que a classe CalculadoraBean implementa a interface Calculadora.java Por fim. 1 2 3 4 5 @Stateless @Remote ( Calculadora . O terceiro passo é especificar o tipo de Session Bean que queremos utilizar.java 1 2 3 4 5 @Stateless @Local ( Calculadora .. 1 2 3 4 @Stateless public class CalculadoraBean implements Calculadora { . } public double subtrai ( double a . SLSB . double b ) { www. class ) public class CalculadoraBean implements Calculadora { . A classe CalculadoraBean poderia implementar diversas interfaces..6: CalculadoraBean. No caso da calculadora. devemos informar as interfaces que definem os métodos de negócio do nosso SLSB. é necessário definir se o acesso do SLSB é local ou remoto.4. A definição do tipo de acesso pode ser realizada através das anotações: @Local e @Remote. SLSB . } Código Java 2.1 Na versão 3.com/k19treinamentos 15 .15 2. Então.1..EJB 3. } Código Java 2. class ) public class CalculadoraBean implements Calculadora { .b . bastaria criar uma classe java com a anotação @Stateless.8: CalculadoraBean. tanto quem está dentro quanto quem está fora do servidor de aplicação no qual se encontra o SLSB pode acessá-lo.EJB 3.. quando o acesso a um SLSB é local. Quando o acesso é remoto.facebook.. apenas os métodos das interfaces declaradas nessas anotações serão considerados métodos de negócio. Contudo. double b ) { return a .java Nas anotações @Local e @Remote. } public double multiplica ( double a .

o SLSB está pronto. O próximo passo é implementar a camada web.com. double b ) .EJB 3.java 16 Os métodos públicos dos objetos da classe CalculadoraBean serão considerados métodos de negócio.S TATELESS S ESSION B EANS 13 14 15 16 17 18 19 return a * b . class ) public class CalculadoraBean implements Calculadora { public double soma ( double a . 1 2 3 public interface Calculadora { double soma ( double a . Em particular. A seguir. Cliente Java Web Local . vamos implementar um sistema que realiza operações matemáticas básicas para exemplificar a utilização da arquitetura EJB em conjunto com as tecnologias Java para desenvolvimento de interfaces web. A interface Calculadora que define as operações do SLSB precisa estar no classpath da camada web diferentemente da classe CalculadoraBean que implementa as operações. além das regras de negócio. Nesse momento.9: CalculadoraBean.10: Calculadora. 16 www. double b ) { return a + b . essa interface é web. } } Código Java 2. na maioria dos casos. Suponha que todo o sistema (session beans e a camada web) esteja no mesmo servidor de aplicação.k19. devemos nos preocupar com a interface dos usuários. double b ) { return a / b .java Perceba que o acesso local foi definido para esse SLSB pois ele será acessado por uma camada web no mesmo servidor de aplicação. devemos implementar as operações do SLSB através de uma classe java com as anotações apropriadas.11: CalculadoraBean. } Código Java 2. Hoje em dia. Contudo. 1 2 3 4 5 6 7 @Stateless @Local ( Calculadora . } public double divide ( double a . A seguinte interface Java será utilizada para definir as operações de um SLSB.br . } } Código Java 2.0 Como vimos os session beans são utilizados para implementar as regras negócio das nossas aplicações. os stateless session beans são utilizados para implementar as regras de negócio que não necessitam manter estado conversacional.java Depois de definir a interface.

o SLSB em uma Servlet. Podemos injetar o SLSB em um managed bean também através da anotação @EJB. getParameter ( " a " ) ) . calculadora . println ( " Soma : " + resultado ) . siga exatamente as imagens abaixo. calculadora .java Exercícios de Fixação Crie um EJB project no eclipse. public void soma () { this . 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 . Depois. private double b . soma (a .java Agora. println ( " < html > < body > <p > " ) . 1 www. getParameter ( " b " ) ) . } // GETTERS AND SETTERS } Código Java 2. private double a . Podemos injetar.13: CalculadoraMB. double b = Double . SLSB .EJB 3. parseDouble ( request . } } Código Java 2.1 Suponha que a camada web da nossa aplicação utiliza apenas Servlets. getWriter () . suponha que a camada web utilize JSF. resultado = this . parseDouble ( request .17 2. PrintWriter out = response . Você pode digitar “CTRL+3” em seguida “new EJB project” e “ENTER”. protected void service ( HttpServletRequest req . private double resultado .facebook.12: SomaServlet. println ( " </p > </ body > </ html > " ) . b ) .com/k19treinamentos 17 . soma (a . double resultado = this . 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 .4. out . através da anotação @EJB. out . out . b ) . HttpServletResponse res ) { double a = Double .

k19.br .com.S TATELESS S ESSION B EANS 18 18 www.

SLSB . 2 www.4. calculadoraClient: As interfaces que definem as operações dos SLSB devem ser colocadas nesse projeto.1 OBS: Os seguintes três projetos serão criados: calculadora: As classes que implementam os SLSB devem ser colocadas nesse projeto. Depois.EJB 3. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”.com/k19treinamentos 19 . siga exatamente as imagens abaixo.19 2. calculadoraEAR: Esse projeto empacota todos os módulos da aplicação Java EE. Crie um Dynamic Web Project no eclipse para implementar a camada web.facebook.

br .S TATELESS S ESSION B EANS 20 20 www.k19.com.

4. Você pode selecionar o projeto calculadoraWeb e digitar “ALT+ENTER”. SLSB . 3 www. siga as imagens abaixo.21 2. Abra as propriedades do projeto calculadoraWeb. Depois.com/k19treinamentos 21 . Adicione o projeto calculadoraClient como dependência do projeto calculadoraWeb.1 OBS: O módulo web já está vinculado ao projeto calculadoraEAR.facebook.EJB 3.

k19.com.S TATELESS S ESSION B EANS 22 22 www.br .

java 5 No projeto calculadora.23 2. } } Código Java 2.k19. ejb .com/k19treinamentos 23 . SLSB .15: CalculadoraBean.com. double b ) { return a + b . @Stateless @Local ( Calculadora . crie uma interface java chamada Calculadora em um pacote chamado br. sessionbeans .EJB 3. crie uma classe java chamada CalculadoraBean em um pacote chamado br.1 No projeto calculadoraClient.facebook.14: Calculadora. public interface Calculadora { double soma ( double a . double b ) .com. class ) public class CalculadoraBean implements Calculadora { public double soma ( double a .k19. } Código Java 2.java www.4. k19 . import javax . sessionbeans .sessionbeans. ejb . 4 1 2 3 4 5 package br .sessionbeans. com . import javax . k19 . Local . com . 1 2 3 4 5 6 7 8 9 1 11 12 package br . Stateless .

org /1999/ xhtml " xmlns : h = " http :// java . Transitional // EN " " http :// www .xhtml 24 www. 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. b ) . w3 .com. ejb . soma (a .transitional .k19. Calculadora .managedbeans. k19 . b } " / > <h : commandButton action = " #{ calculadoraMB . private double a .16: CalculadoraMB. a } " / > <h : outputLabel value = " Valor B : " / > <h : inputText value = " #{ calculadoraMB . com .com. @ManagedBean public class CalculadoraMB { @EJB private Calculadora calculadora . resultado } " / > </ h : form > </ h : body > </ html > Código XHTML 2. import javax . crie uma classe java chamada CalculadoraMB em um pacote chamado br. public void soma () { this . soma } " value = " soma " / > <h : outputLabel value = " Resultado : " / > <h : outputText value = " #{ calculadoraMB .java 7 Crie uma simples tela na aplicação web para utilizar o managed bean. bean .xhtml na pasta WebContent do projeto calculadoraWeb com o seguinte conteúdo. resultado = this . import javax . com / jsf / html " > <h : head > < title > Calculadora . private double b . sun . private double resultado .br . import br . dtd " > < html xmlns = " http :// www . 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 .S TATELESS S ESSION B EANS 6 24 No projeto calculadoraWeb. faces . org / TR / xhtml1 / DTD / xhtml1 . k19 . sessionbeans . Adicione o arquivo soma. } // GETTERS AND SETTERS } Código Java 2. ManagedBean . calculadora . w3 .k19. EJB . com .1: soma.Soma </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Valor A : " / > <h : inputText value = " #{ calculadoraMB .

xhtml e teste o funcionamento da aplicação. as regras de empacotamento foram simplificadas. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”.2 da view Servers e escolha a opção “Add and Remove”.4. siga exatamente as imagens 11 www.25 8 2.1 Runtime Server está parado.1. Além disso. calculadoraClient. siga as imagens abaixo. Depois. Inicie o Glassfish 3.2.1. Para isso. Isso simplifica bastante o funcionamento das IDEs como o eclipse.1 Como dito anteriormente.com/k19treinamentos 25 .EJB 3. Exercícios de Fixação Para não confunfir. Depois. não é mais necessário definir uma interface Java nem utilizar a anotação @Local.1. Clique com o botão direito no Glassfish 3.2. quando o acesso a um SLSB é local. na versão 3. Cliente Java Web Local .1. 10 Crie um Dynamic Web Project no eclipse para implementar a camada web.facebook. calculadoraEAR e calculadoraWeb. Acesse a url http://localhost:8 8 /calculadoraWeb/soma. clique com o botão direito do mouse sobre esses projetos e selecione a opção “Close Project”. feche os projetos calculadora.1 Adicione o projeto calculadoraEAR no Glassfish 3. SLSB .EJB 3. Perceberemos essa diferença o exercício seguinte. Os Session Beans podem ser empacotados no módulo web. 9 Certifique-se que o JBoss 7.

k19.com.br .S TATELESS S ESSION B EANS 26 abaixo. 26 www.

facebook.4. SLSB .27 2.com/k19treinamentos 27 .EJB 3.1 www.

k19.br . sun . import javax . } } Código Java 2. ejb . 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 . @ManagedBean public class DadoMB { @EJB private LancadorDeDadoBean lancadorDeDadoBean .xhtml na pasta WebContent do projeto dadoWeb com o seguinte conteúdo. Transitional // EN " " http :// www . sessionbeans . com / jsf / html " > <h : head > 28 www. import br .18: DadoMB. util . adicione um pacote chamado br. import java . public int lanca () { return this . org /1999/ xhtml " xmlns : h = " http :// java . faces . resultado = resultado .com.java No projeto dadoWeb.com.k19. k19 . gerador . Stateless . LancadorDeDadoBean . bean . Adicione o arquivo dado. adicione um pacote chamado br. resultado = this . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 package br . sessionbeans . public void lancaDado () { this . nextInt (6) + 1. import javax . com .managedbeans acrescenta nele uma classe chamada DadoMB. ejb .17: LancadorDeDadoBean. @Stateless public class LancadorDeDadoBean { private Random gerador = new Random () . EJB .java Crie uma simples tela na aplicação web para utilizar o managed bean. dtd " > < html xmlns = " http :// www . private int resultado . lanca () . ManagedBean . k19 . Random . w3 .com.S TATELESS S ESSION B EANS 12 28 No projeto dadoWeb. } public int getResultado () { return resultado .k19. w3 . managedbeans . 14 1 2 3 4 5 6 7 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1.transitional . import javax . com .sessionbeans e acrescente nele uma classe chamada LancadorDeDadoBean. } } Código Java 2. org / TR / xhtml1 / DTD / xhtml1 . k19 . com . } public void setResultado ( int resultado ) { this . lancadorDeDadoBean .

1 <h : body > <h : form > <h : commandButton action = " #{ dadoMB . lancaDado } " value = " Lança o Dado " / > <h : outputLabel value = " Resultado : " / > <h : outputText value = " #{ dadoMB .1.29 8 9 1 11 12 13 14 15 16 17 18 19 < title > Lançador de dado </ title > </ h : head > 2.1. www. siga as imagens abaixo.2: dado.2 da view Servers e escolha a opção “Add and Remove”.4.EJB 3.2. resultado } " / > </ h : form > </ h : body > </ html > Código XHTML 2. SLSB .xhtml 15 Remova o projeto calculadoraEAR e adicione o projeto dadoWeb no Glassfish 3.facebook. Clique com o botão direito no Glassfish 3. Depois.com/k19treinamentos 29 .

Toda aplicação fora desse servidor de aplicação pode utilizar esse nome para obter a referência remota do SLSB. os SLSBs devem ser obtidos de outra maneira. podemos injetar um SLSB através da anotação @EJB no componente que necessita dos serviços implementados pelo SLSB. Dessa forma. Quando o acesso é local. 30 www. Agora. Consequentemente. A partir da versão 3.1. um SLSB pode ser acessado por aplicações Java SE.com. os nomes dos Session Beans não eram padronizados. Antes da versão 3.xhtml e teste o funcionamento da aplicação. O trecho de código Java para fazer uma consulta por um SLSB no JNDI teria o seguinte padrão.1. não temos o recurso de injeção de dependência.org/en/ jsr/detail?id=318.br . Inclusive. Uma aplicação Java remota deve acessar o serviço de nomes (JNDI) do servidor de aplicação no qual o SLSB que ela deseja utilizar está implantado. cada servidor de aplicação possuía uma regra diferente para nomear os Session Beans. Todo SLSB implantado em um servidor de aplicação recebe um “nome”. eles podem ser acessados remotamente.S TATELESS S ESSION B EANS 30 16 Certifique-se que o Glassfish 3. ou seja. Contudo. Acesse a url http://localhost:8 8 / dadoWeb/dado. Consulte a especificação para conhecer as regras de nomenclatura http://jcp.k19. podem ser acessados por aplicações fora do mesmo servidor de aplicação. Cliente Java SE Remoto Vimos os SLSBs sendo acessados localmente por aplicações web implantadas no mesmo servidor de aplicação. 1 InitialContext ic = new InitialContext () .1. os nomes foram padronizados e portanto são portáveis (iguais em todos os servidores de aplicação).2 está executando. quando o acesso é remoto.

Você pode digitar “CTRL+3” em seguida “new Java project” e “ENTER”. Random . nextInt (6) + 1.EJB 3.java Crie um Java project no eclipse. } Código Java 2. package br . @Stateless @Remote ( LancadorDeDado .1 StatelessSessionBean statelessSessionBean = ( StatelessSessionBean ) ic .20: LancadorDeDado. k19 . public int lanca () { return this .k19. Remote .31 2 3 2. com . util . public interface LancadorDeDado { int lanca () . import javax . a aplicação pode chamar as operações normalmente como se o Session Bean estivesse local. } } 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 Código Java 2.facebook. Contudo.21: LancadorDeDadoBean.com/k19treinamentos 31 . sessionbeans . siga exatamente as imagens abaixo. Stateless . 19 www. com .com.java 18 Altere a classe LancadorDeDadoBean do projeto dadoWeb. é importante ressaltar que as chamadas são remotas e portanto mais demoradas. SLSB . gerador . class ) public class LancadorDeDadoBean implements LancadorDeDado { private Random gerador = new Random () . import javax . import java . Uma vez com a referência do SLSB. sessionbeans . k19 .4.sessionbeans do projeto dadoWeb. ejb . lookup ( " java : global / aplicacaoWeb / StatelessSessionBean " ) . ejb . Depois. Exercícios de Fixação Adicione uma interface chamada LancadorDeDado no pacote br. 17 1 2 3 4 5 package br .

S TATELESS S ESSION B EANS 32 Adicione as bibliotecas do Glassfish 3. 20 32 www.k19.1.com. Você pode selecionar o projeto dadoJavaSE e digitar “ALT+ENTER”.br . Depois. Abra as propriedades do projeto dadoJavaSE.2 necessárias para a consulta ao serviço de nomes. siga as imagens abaixo.

Você pode selecionar o projeto dadoJavaSE e digitar “ALT+ENTER”.EJB 3.4. Abra as propriedades do projeto dadoJavaSE.com/k19treinamentos 33 .facebook. siga as imagens abaixo 21 www. SLSB .1 Adicione o projeto dadoWeb como dependência do projeto dadoJavaSE. Depois.33 2.

k19.S TATELESS S ESSION B EANS 34 34 www.br .com.

LancadorDeDado . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 package br . println ( lancadorDeDado . SLSB . System . PRONTO NÃO EXISTE -> PRONTO Antes de ser criada. Três aspectos fundamentais dos SLSBs nos ajudam a entender o ciclo de vida das instâncias.22: TesteDeAcesso. k19 . lookup ( " java : global / dadoWeb / LancadorDeDadoBean " ) . uma instância não pode atender chamadas dos clientes. Uma única instância de um SLSB pode atender chamadas de diversos clientes.com/k19treinamentos 35 . o EJB Container pode criar novas instâncias de um SLSB. Cada instância criada passa para o estado PRONTO. import javax . 3. De acordo com a quantidade de chamadas e critérios de cada servidor de aplicação. nesse estado.com.1 No projeto dadoJavaSE.testes acrescenta nele uma classe chamada TesteDeAcesso. out . public class TesteDeAcesso { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () . com . O EJB Container pode criar várias instâncias do mesmo SLSB para atender mais rapidamente as chamadas dos clientes. 1. import br .facebook. 1. sessionbeans . com . k19 . ela processa uma chamada de cada vez.k19. Devemos entender o ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB. naming . adicione um pacote chamado br. uma instância está apta a receber uma chamada. www. dizemos que uma instância de um SLSB se encontra no estado NÃO EXISTE. InitialContext . LancadorDeDado lancadorDeDado = ( LancadorDeDado ) ic . No estado PRONTO. Uma instância de um SLSB não atende duas chamadas ao mesmo tempo. testes .35 22 2.EJB 3. 2. } } Código Java 2. Obviamente. Estados O ciclo de vida das instâncias de um SLSB possui apenas dois estados.java Execute a classe TesteDeAcesso e confira o resultado no console Ciclo de Vida As instâncias dos SLSBs são administradas pelo EJB Container.4. NÃO EXISTE 2. lanca () ) . Em outras palavras.

Cada servidor de aplicação oferece configurações específicas para melhorar a eficiência no atendimento das chamadas.br .k19. O EJB Container administra as instâncias criadas através de um Pool. Enquanto.S TATELESS S ESSION B EANS 36 PRONTO -> PRONTO Quando uma chamada é realizada. o EJB Container cria novas instâncias e cada instância pode atender vários clientes. o Glassfish permite que uma quantidade máxima de instâncias de um determinado SLSB seja definida pela aplicação. PRONTO -> NÃO EXISTE Novamente. Por exemplo. Depois de finalizar o atendimento. o EJB Container seleciona uma instância entre as que estejam no estado PRONTO para realizar o atendimento. uma instância está atendendo uma chamada ela não pode atender outras chamadas. o EJB Container pode destruir instâncias que estejam no estado PRONTO. Escalabilidade e Pool As características dos SLSBs favorecem a escalabilidade da aplicação pois. de acordo com a demanda. a instância volta para o estado PRONTO podendo receber outra chamada. 36 www. Essas instâncias voltam para o estado NÃO EXISTE. de acordo com a quantidade de chamadas e critérios de cada servidor de aplicação.com.

Esse registro é realizado através da anotação @PreDestroy. Random .facebook. com . k19 . println ( " Mais uma calculadora será destruída . SLSB .java Exercícios de Fixação 23 Adicione métodos de callbacks na classe LancadorDeDadoBean do projeto dadoWeb.com/k19treinamentos 37 . " ) } // METODOS DE NEGOCIO } Código Java 2. " ) } // METODOS DE NEGOCIO } Código Java 2.EJB 3.24: CalculadoraBean. println ( " Mais uma calculadora criada . sessionbeans . @PreDestroy Também podemos registrar um método de instância no EJB Container para que ele o execute em cada instância imediatamente antes dela ser destruída. 1 2 3 4 5 6 7 8 9 1 @Stateless public class CalculadoraBean { @PostConstruct public void inicializando () { System . Esse registro é realizado através da anotação @PostConstruct. Por fim. out .23: CalculadoraBean.37 2. os métodos anotados com @PostConstruct são executados. Depois de chamar o construtor sem argumentos. out .. @PostConstruct Podemos registrar um método de instância no EJB Container para que ele o execute em cada instância logo após ela ser criada. o EJB Container injeta eventuais dependências na instância criada. 1 2 3 4 www. util .1 Callbacks Podemos associar lógicas específicas nas transições de estado no ciclo de vida dos SLSBs. package br .4. 1 2 3 4 5 6 7 8 9 1 @Stateless public class CalculadoraBean { @PreDestroy public void destruindo () { System .java O EJB Container utiliza o construtor sem argumentos para criar uma instância de um SLSB. import java ....

println ( " Total : " + + LancadorDeDadoBean .S TATELESS S ESSION B EANS 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 36 37 import import import import javax .testes do projeto dadoJavaSE para fazer consultas em paralelo ao SLSB que lança moedas. public class TesteCicloDeVidaSLSB { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () .k19. javax . for ( int i = . LancadorDeDado . System . lookup ( " java : global / dadoWeb / LancadorDeDadoBean " ) . Remote . ejb . out . InitialContext .java Adicione um teste no pacote br. } } @PreDestroy public void destruindo () { synchronized ( LancadorDeDadoBean .-. System . i ++) { final LancadorDeDado lancadorDeDado = ( LancadorDeDado ) ic . k19 . contador . class ) { LancadorDeDadoBean . out . import br . ejb . import javax . contador ++. Stateless . javax . } } public int lanca () { return this . 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 . k19 .com. nextInt (6) + 1.br .. System .. i ++) { System . contador ) .. out . thread . } } } 38 www. " ) . com . println ( lancadorDeDado . i < 1 . class ) public class LancadorDeDadoBean implements LancadorDeDado { private Random gerador = new Random () . } } Código Java 2. " ) . println ( " Criando um lançador de dados .25: LancadorDeDadoBean. annotation . @PostConstruct public void inicializando () { synchronized ( LancadorDeDadoBean . com . System .com.. PostConstruct . } } }) . Thread thread = new Thread ( new Runnable () { @Override public void run () { for ( int i = . sessionbeans . lanca () ) . println ( " Destruindo um lançador de dados . private static int contador . contador ) . naming . testes . PreDestroy . println ( " Total : " + + LancadorDeDadoBean . out . 38 @Stateless @Remote ( LancadorDeDado . annotation . out . gerador . start () . i < 1 .k19. class ) { LancadorDeDadoBean . javax .

2. Reinicie o Glassfish 3. execute a classe TesteCicloDeVidaSLSB observe o log do servidor para conferir as mensagens dos métodos de callback.1.4. SLSB .2 no endereço http://localhost:4848/.2. Acesse a interface de administração do Glassfish 3. Observe também que depois de 10 segundos de ociosidade as instâncias são destruídas.26: TesteCicloDeVidaSLSB. Chame o instrutor caso não consiga visualizar o log do glassfish. execute a classe TesteCicloDeVidaSLSB observe o log do servidor para conferir as mensagens dos métodos de callback.facebook. Depois.EJB 3. 26 Altere as configurações do pool de SLSB do Glassfish 3.com/k19treinamentos 39 . Observe que o servidor tentará manter no Pool de SLSB com apenas 5 instâncias do LancadorDeDadoBean. Faça as modificações indicadas na imagem abaixo. 27 Métodos Assíncronos www. Chame o instrutor caso não consiga visualizar o log do glassfish.java 25 Reinicie o Glassfish 3.1. Depois.2.1.39 2.1 Código Java 2.1.

} @Asynchronous public Future < String > metodoAssincrono2 () {..1 do EJB.br .} public Future < String > metodoAssincrono2 () {. metodoAssincrono1 () .Future. 1 2 3 4 5 6 7 8 @Stateless @Asynchronous public class MeuSessionBean { public Future < Integer > metodoAssincrono1 () {. Se essa anotação for aplicada na classe que define um session bean. // executa alguma coisa enquanto o session bean trabalha // verifica se a tarefa terminou if ( future . Geralmente.util..27: MeuSessionBean. metodoAssincrono1 () .. métodos assíncronos são utilizados para implementar tarefas demoradas.} } Código Java 2. get () .. // executa alguma coisa enquanto o session bean trabalha // verifica se a tarefa terminou if ( future .concurrent. 1 2 3 4 5 6 7 8 MeuSessionBean bean = .. Future < String > future = bean .28: MeuSessionBean.S TATELESS S ESSION B EANS 40 A partir da versão 3. basta utilizar a anotação @Asynchronous... Para definir um método assíncrono..k19..} public String metodoSincrono1 () {. 1 2 3 4 5 6 7 8 MeuSessionBean bean = . isDone () ) { String resultado = future ...java 1 2 3 4 5 6 7 8 9 1 11 12 13 @Stateless public class MeuSessionBean { @Asynchronous public Future < Integer > metodoAssincrono1 () {. } 40 www.. isDone () ) { } A interface Future também permite que o resultado seja recuperado através do método get(). todos os métodos de negócio desse session bean serão assíncronos.java Observe que o retorno dos métodos assíncronos utiliza a interface java.} public Integer metodoSincrono2 () {.} } Código Java 2. podemos aplicar essa anotação somentes nos métodos de negócio que devem ser assíncronos..com. Future < String > future = bean . Por outro lado... podemos definir métodos assíncronos nos session beans.. Essa interface permite verificar se a tarefa já foi concluída através do método isDone().

map . i ++) { int v = this . Integer > > calculaFrequencia () { Map < Integer .util. put (v .. try { Thread . util .41 2. map . Integer >() .HashMap • java. get ( v ) + 1) .Future 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 . Map .Map • java. } catch ( InterruptedException e ) { } System . map . com .util.. k19 .util.util.. SLSB ..java 30 Adicione uma classe chamada TesteAsynchronous no projeto dadoJavaSE. @Asynchronous public Future < Map < Integer . testes .concurrent. out .util.. Future < Map < Integer . ) . put (3 . ) . map .com/k19treinamentos 41 . } return new AsyncResult < Map < Integer . i < 5 .1 Exercícios de Fixação 28 Acrescente o método calculaFrequencia() na classe LancadorDeDadoBean do projeto dadoWeb. ) . Integer > >( map ) . sleep (1 ) .31: LancadorDeDadoBean..Map • java. nextInt (6) + 1. Código Java 2. Integer > map = new HashMap < Integer . gerador . ) .4. map . put (2 . put (5 . Integer > > calculaFrequencia () .facebook. put (6 . put (1 .. .. ) . import java . Código Java 2.EJB 3. ) . 1 2 3 www.Future 1 2 3 .java 29 Adicione o método calculaFrequencia() na interface LancadorDeDado do projeto dadoWeb. map . for ( int i = .32: LancadorDeDado.concurrent. Obs: Faça o importe dos seguintes itens: • java. Obs: Faça o importe dos seguintes itens: • java. map . package br . println ( i ) . map . } . put (4 .

java 42 31 Execute a classe TesteAsynchronous e verifique o console do cliente e do servidor.S TATELESS S ESSION B EANS 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 import java . println ( " \ n " + future . util . LancadorDeDado lancadorDeDado = ( LancadorDeDado ) ic . public class TesteAsynchronous { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () . sleep (1 ).k19. while (! future . } } Código Java 2. naming . isDone () ) { System . out .br . com . Future < Map < Integer . out . k19 . Integer > > future = lancadorDeDado . get () ) . Thread . import javax . sessionbeans . print ( " Aguardando " ) .33: TesteAsynchronous. import br . lookup ( " java : global / dadoWeb / LancadorDeDadoBean " ) . LancadorDeDado . InitialContext . System . out .com. Future . print ( " * " ) . calculaFrequencia () . 42 www. } System . concurrent .

A ideia fundamental por trás dos SFSBs é a necessidade de manter estado conversacional. } public void remove ( Produto produto ) { this . remove ( produto ) .com/k19treinamentos 43 . o estado do carrinho.facebook. uma instância da classe CarrinhoBean não deve atender vários clientes para não misturar produtos escolhidos por clientes diferentes. Primeiro. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 class CarrinhoBean { public void adiciona ( Produto produto ) { // lógica para adicionar produto } public void remove ( Produto produto ) { // lógica para remover produto } public void finalizaCompra () { // lógica para finalizar a compra } } Código Java 3. As regras de negócio do carrinho podem ser implementas através de alguns métodos. } www. os produtos adicionados devem ser mantidos entre as chamadas dos métodos da classe CarrinhoBean. Segundo. add ( produto ) . suponha o funcionamento de um carrinho de compras de uma loja virtual. 1 2 3 4 5 6 7 8 9 1 11 class CarrinhoBean { private Set < Produto > produtos = new HashSet < Produto >() . é necessário manter estado conversacional. produtos . ou seja. os produtos adicionados seria mantido em uma lista ou em um conjunto.java Há duas necessidades fundamentais no exemplo do carrinho de compras que devemos observar. Em outras palavras. public void adiciona ( Produto produto ) { this . produtos . Provavelmente.1: CarrinhoBean. Muitas vezes. Carrinho de Compras Para exemplificar. utilizaremos a sigla SFSB para fazer referência a esse tipo de componente.CAPÍTULO S TATEFUL S ESSION B EANS 3 Caracterizando os SFSBs Stateful Session Bean é o segundo tipo de Session Bean.

} public void finaliza () { // lógica para finalizar a prova } } Código Java 3. respostas . } } Código Java 3. Character resposta ) { this . } public void embaralha () { Collections .2: CarrinhoBean.k19. suponha o funcionamento de um sistema para aplicar provas que permita que os usuários respondam as questões em qualquer ordem ou modifiquem respostas já realizadas antes de finalizar a prova. Character > respostas = new HashMap < Integer . SFSB . as respostas já realizadas devem ser mantidas entre as chamadas.3: ProvaBean. 1 2 3 4 5 6 7 8 9 1 11 class ListaDeVideos { private List < Video > videos = new ArrayList < Video >() .S TATEFUL S ESSION B EANS 12 13 14 15 16 44 public void finalizaCompra () { // lógica para finalizar a compra } } Código Java 3. 1 2 3 4 5 6 7 8 9 1 11 class ProvaBean { private Map < Integer . resposta ) . TrackList Mais um exemplo. shuffle ( this . videos ) . public void adiciona ( Video video ) { this .0 44 www. public void responde ( Integer questao . put ( questao . Além disso.4: ListaDeVideos. suponha o funcionamento de um player de vídeo que permite que os usuários selecionem um conjunto de vídeos para assistir. cada instância da classe ListaDeVideos deve ser exclusiva de um cliente e os vídeos adicionados devem ser mantidos entre as chamadas dos métodos. Character >() .com. As resposta poderiam ser mantidas em um mapa.java Prova Digital Outro exemplo.br .EJB 3.java Novamente.java Uma instância da classe ProvaBean não pode atender dois clientes para não misturar as respostas de dois usuários diferentes. add ( video ) . videos .

} Código Java 3. } Código Java 3. ele pode ser acessado tanto por aplicações que estejam no mesmo servidor de aplicação quanto aplicações que não estejam..java O terceiro passo é especificar o tipo de session bean que queremos utilizar.. produtos . ele só pode ser acessado por aplicações que estejam no mesmo servidor de aplicação que ele. o tipo seria SFSB. Uma possível interface de utilização para esse session bean seria: 1 2 3 4 public interface Carrinho { void adiciona ( Produto produto ) . quando o acesso a um SLSB é remoto.. A definição do tipo de acesso é realizada através das anotações: @Local e @Remote. } } Código Java 3. Caso contrário. public void adiciona ( Produto produto ) { this .. } www.6: CarrinhoBean. No caso do carrinho.45 S TATEFUL S ESSION B EANS O primeiro passo para implementar um SFSB é definir a sua interface de utilização através de uma interface java.5: Carrinho. 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 remove ( Produto produto ) { this . Essa definição é realizada através da anotação @Stateful.com/k19treinamentos 45 .facebook. 1 2 3 4 5 @Stateful @Remote ( Carrinho . } Código Java 3. Por exemplo. 1 2 3 4 @Stateful public class CarrinhoBean implements Carrinho { . é necessário definir se o SFSB poderá ser acessado remotamente ou apenas localmente.8: CarrinhoBean.java Após definir a interface de utilização. Quando o acesso a um SLSB é local. o segundo passo seria implementar as operações do SFSB através de uma classe java. produtos .java 1 2 3 4 5 @Stateful @Local ( Carrinho ... class ) public class CarrinhoBean implements Carrinho { .java Por fim.7: CarrinhoBean. remove ( produto ) . class ) public class CarrinhoBean implements Carrinho { . add ( produto ) . considere um SFSB que implemente o funcionamento do carrinho de compras. void remove ( Produto produto ) .

produtos . public void adiciona ( Produto produto ) { this . não é mais necessário definir uma interface java nem utilizar a anotação @Local. remove ( produto ) . Para isso. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. Então. } public void remove ( Produto produto ) { this . produtos .1. bastaria implementar uma classe java com a anotação @Stateful.k19. Depois. 1 Crie um Dynamic Web Project no eclipse para implementar o funcionamento do carrinho de compras. 2 46 www. clique com o botão direito do mouse sobre esses projetos e selecione a opção “Close Project”.S TATEFUL S ESSION B EANS 46 Código Java 3. add ( produto ) .java SFSB .com.java Exercícios de Fixação Para não confunfir.10: CarrinhoBean. feche os projetos dadoWeb e dadoJavaSE.EJB 3. 1 2 3 4 5 6 7 8 9 1 11 12 13 @Stateful public class CarrinhoBean { private Set < Produto > produtos = new HashSet < Produto >() .1 Na versão 3. } } Código Java 3.br .9: CarrinhoBean. siga exatamente as imagens abaixo. quando o acesso a um SFSB é local.

com/k19treinamentos 47 .facebook.47 S TATEFUL S ESSION B EANS www.

S TATEFUL S ESSION B EANS

48

3

Crie um pacote chamado br.com.k19.sessionbeans e adicione a seguinte classe.
package br . com . k19 . sessionbeans ; import java . util . HashSet ; import java . util . Set ;

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

S TATEFUL S ESSION B EANS

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 ; } }
Código Java 3.11: CarrinhoBean.java

4

Crie um pacote chamado br.com.k19.managedbeans e adicione a seguinte classe.
package br . com . k19 . managedbeans ; import java . util . ArrayList ; import java . util . List ; import javax . ejb . EJB ; import javax . faces . bean . ManagedBean ; import javax . faces . bean . SessionScoped ; import br . com . k19 . sessionbeans . CarrinhoBean ; @ManagedBean @SessionScoped public class CarrinhoMB { @EJB private CarrinhoBean carrinhoBean ; private String produto ; public List < String > getProdutos () { return new ArrayList < String >( this . carrinhoBean . getProdutos () ) ; } public void adiciona () { this . carrinhoBean . adiciona ( this . produto ) ; } public void remove ( String produto ) { this . carrinhoBean . remove ( produto ) ; } public void setProduto ( String produto ) { this . produto = produto ; } public String getProduto () { return produto ; } }
Código Java 3.12: CarrinhoMB.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

S TATEFUL S ESSION B EANS
5

50

Adicione o arquivo produtos.xhtml na pasta WebContent do projeto carrinhoWeb com o seguinte conteúdo.
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 >
Código XHTML 3.1: produtos.xhtml

Remova o projeto dadoWeb do Glassfish 3.1.2. Adicione o projeto carrinhoWeb no JBoss 7.1 Runtime Server. Certifique-se que o Glassfish 3.1.2 esteja parado. Execute o JBoss 7.1 Runtime Server e teste a aplicação acessando a url http://localhost:8 8 /carrinhoWeb/produtos.xhtml.
6

Ciclo de Vida
As instâncias dos SFSBs são 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 instâncias dos SFSBs, devemos sempre ter em mente que cada instância atende apenas um cliente.

Estados
O ciclo de vida das instâncias de um SFSB possui três estados.

1. NÃO EXISTE 2. PRONTO 3. PASSIVADO
50
www.k19.com.br

a aplicação é responsável por determinar quando uma instância se torna inútil. Para não consumir a memória do computador. Após ser passivada. logo após ser criada. Por outro lado.51 S TATEFUL S ESSION B EANS NÃO EXISTE -> PRONTO Antes de ser criada. a instância ociosa se encontrará no estado PASSIVADO. No exemplo do carrinho de compras. O EJB Container é o responsável por destruir uma instância de um SFSB que não é mais útil. depois de um certo tempo de ociosidade. o EJB Container cria uma nova instância desse SFSB para atender exclusivamente esse cliente. Nesse instante. Adicionando um método de negócio anotado com @Remove a aplicação declara que após a execução desse método a instância não é mais necessária. poderíamos definir um método para implementar a lógica de finalizar compra e anotá-lo com @Remove. Após ser ativada. logo após a execução desse método a instância seria destruída pelo EJB Container. quando o cliente de um carrinho de compras finaliza a compra. Esse processo consiste na transferência do conteúdo da instância passivada para a memória principal novamente. Obviamente. } public void remove ( String produto ) { www. o EJB Container realizará automaticamente o processo de ativação. a instância se encontra no estado PRONTO e pode atender as chamadas do seu respectivo cliente.com/k19treinamentos 51 . Por exemplo. uma instância não pode atender as chamadas do seu cliente. o EJB Container pode transferir o conteúdo de uma instância ociosa para dispositivos secundários de armazenamento (hard disk). PRONTO -> NÃO EXISTE Em determinadas situações. Por exemplo. o cliente correspondente pode não precisar mais dela. Quando um cliente recebe por injeção ou recupera por lookup um SFSB. add ( produto ) . PASSIVADA -> PRONTO Se o cliente de uma instância passivada realizar uma chamada a ela. dizemos que uma instância de um SFSB se encontra no estado NÃO EXISTE. Outros fatores além da ociosidade podem levar o EJB Container decidir passivar instâncias dos SFSBs. uma instância de um SFSB pode não ser mais útil. PRONTO -> PASSIVADO Uma instância de um SFSB fica ociosa enquanto não estiver processando uma chamada do seu cliente. 1 2 3 4 5 6 7 8 9 1 @Stateful public class CarrinhoBean { private Set < String > produtos = new HashSet < String >() . Em outras palavras. quando um certo limite de instâncias no estado PRONTO (ocupando memória) for atingido. Esse processo de transferência é chamado de passivação.facebook. nesse estado. a instância que representa o carrinho pode ser destruída (não compensa reaproveitar o mesmo carrinho para outro cliente). Dessa forma. public void adiciona ( String produto ) { this . a instância se encontrará no estado PRONTO e apta a atender a chamada realizada. produtos .

br .13: CarrinhoBean. Nesses casos. Esse registro é realizado através da anotação @PostConstruct. remove ( produto ) . } public Set < String > getProdutos () { return produtos . 1 2 3 @Stateful public class CarrinhoBean { 52 www. o EJB Container ativa e depois a destrói. o respectivo cliente não realizou nenhuma chamada durante um “grande” período de tempo. } @Remove public void finalizaCompra () { // lógica para finalizar compra } } Código Java 3. produtos .k19. o EJB Container pode assumir que o cliente não chamará mais a instância passivada e portanto ela não é mais útil. quando passivada. uma instância pode não receber uma chamada do seu cliente durante um “grande” período de tempo.com.java 52 PASSIVADO -> PRONTO -> NÃO EXISTE Uma instância pode ser passivada porque ficou ociosa quando estava no estado PRONTO. Callbacks Podemos associar lógicas específicas nas transições de estado no ciclo de vida dos SFSBs. @PostConstruct Podemos registrar um método de instância no EJB Container para que ele o execute em cada instância logo após ela ser criada. Da mesma maneira.S TATEFUL S ESSION B EANS 11 12 13 14 15 16 17 18 19 2 21 22 this . Ou seja. Quando uma instância passivada não é mais útil.

println ( " Mais um carrinho será passivado .com/k19treinamentos 53 .java @PostActivate Também podemos registrar um método de instância no EJB Container para que ele o execute em cada instância imediatamente depois dela ser ativada.. " ) . Por fim. } // METODOS DE NEGOCIO } Código Java 3. 1 @Stateful www.15: CarrinhoBean. out .14: CarrinhoBean. Esse registro é realizado através da anotação @PostActivate. } // METODOS DE NEGOCIO } Código Java 3. 1 2 3 4 5 6 7 8 9 1 @Stateful public class CarrinhoBean { @PreDestroy public void destruindo () { System .. Esse registro é realizado através da anotação @PreDestroy.16: CarrinhoBean. o EJB Container injeta eventuais dependências na instância criada. Esse registro é realizado através da anotação @PrePassivate. } // METODOS DE NEGOCIO } Código Java 3. Depois de chamar o construtor sem argumentos. println ( " Mais um carrinho criado .. 1 2 3 4 5 6 7 8 9 1 @Stateful public class CarrinhoBean { @PrePassivate public void passivando () { System . " ) . println ( " Mais um carrinho será destruído . out . " ) .facebook... out .java S TATEFUL S ESSION B EANS O EJB Container utiliza o construtor sem argumentos para criar uma instância de um SLSB. os métodos anotados com @PostConstruct são executados. @PreDestroy Também podemos registrar um método de instância no EJB Container para que ele o execute em cada instância imediatamente antes dela ser destruída.53 4 5 6 7 8 9 1 @PostConstruct public void inicializando () { System .java @PrePassivate Também podemos registrar um método de instância no EJB Container para que ele o execute em cada instância imediatamente antes dela ser passivada..

produtos . add ( produto ) . javax .S TATEFUL S ESSION B EANS 2 3 4 5 6 7 8 9 1 public class CarrinhoBean { @PostActivate public void ativando () { System .java 54 Exercícios de Fixação Adicione uma interface chamada Carrinho no pacote br. 7 1 2 3 4 5 6 7 8 9 1 11 12 13 14 package br .java 8 Altere a classe CarrinhoBean do projeto carrinhoWeb.k19. void remove ( String produto ) . static int contadorTotal . javax . package br . ejb . util . int id . com .sessionbeans do projeto carrinhoWeb. Stateful . ejb . public interface Carrinho { void adiciona ( String produto ) . util . PrePassivate . Remote .17: CarrinhoBean.k19. javax . class ) public class CarrinhoBean implements Carrinho { private private private private Set < String > produtos = new HashSet < String >() . Set < String > getProdutos () . println ( " Mais um carrinho foi ativado . javax ... ejb . sessionbeans . import java . void finalizaCompra () . HashSet . util .com. out . javax . PreDestroy .18: Carrinho. Remove . } // METODOS DE NEGOCIO } Código Java 3. ejb . public void adiciona ( String produto ) { this . javax . com . import java . } Código Java 3. annotation . k19 . Set . ejb . import java . import import import import import import import javax . 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 .br . annotation . sessionbeans . static int contadorAtivos . Set . PostConstruct . k19 . PostActivate .com. " ) . 54 www.

-. out . contadorAtivos ) . println ( " ContatorTotal : " + CarrinhoBean . contadorAtivos ) . out . } public Set < String > getProdutos () { return produtos . System . out . class ) { CarrinhoBean . class ) { CarrinhoBean . class ) { CarrinhoBean . contadorTotal . } } @PostActivate public void postActivate () { synchronized ( CarrinhoBean . out . out . System . println ( " ContatorTotal : " + CarrinhoBean . contadorTotal ) . id ) . out . System . out . out . contadorAtivos ) . println ( " ContatorTotal : " + CarrinhoBean .-. System .facebook. id = CarrinhoBean . out . contadorTotal ) . System . System . out . out . System .com/k19treinamentos 55 . out . println ( " ID : " + this . out . println ( " PostConstruct " ) . println ( " ContatorTotal : " + CarrinhoBean . println ( " ID : " + this . contadorAtivos ++. println ( " Finalizando a compra " ) . } } } Código Java 3. contadorAtivos . out . System . contadorAtivos ) . contadorTotal ) . } } @PreDestroy public void preDestroy () { synchronized ( CarrinhoBean . class ) { CarrinhoBean . contadorAtivos . System . println ( " ID : " + this . id ) . } } @PrePassivate public void prePassivate () { synchronized ( CarrinhoBean . println ( " PreDestroy " ) . out . System . this . contadorTotal ++. remove ( produto ) . println ( " ID : " + this . S TATEFUL S ESSION B EANS System . println ( " ContatorAtivos : " + CarrinhoBean . println ( " PrePassivate " ) .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 . println ( " ContatorAtivos : " + CarrinhoBean . } @Remove public void finalizaCompra () { System . println ( " ContatorAtivos : " + CarrinhoBean .java www. System . contadorTotal ) . } @PostConstruct public void postContruct () { synchronized ( CarrinhoBean . produtos . id ) . println ( " PostActivate " ) . System . out . contadorAtivos ++.19: CarrinhoBean. id ) . CarrinhoBean . System . System . System . out . println ( " ContatorAtivos : " + CarrinhoBean .

1. managedbeans .1. com . Carrinho . Siga os passos abaixo. import java . cosen@k19 :~/ Desktop / jboss . ArrayList . import javax . properties ’ Added user ’k19 ’ to file ’/ home / cosen / Desktop / jboss . util . package br . properties ) b) Application User ( application .as -7..as -7. Final / domain / configuration / application . ejb . @ManagedBean @SessionScoped public class CarrinhoMB { @EJB private Carrinho carrinhoBean .users . import java .com. . util .user .1. ManagedBean . bean .1. sessionbeans . k19 . 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 . faces .users .users . Final / standalone / configuration / application . SessionScoped . Realm ( ApplicationRealm ) : Username : k19 Password : Re . bean . Modifique o arquivo JBOSS_HOME/standalone/configuration/standalone.20: CarrinhoMB.. k19 .java 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 10 Adicione um usuário no JBoss com as seguintes características: Tipo: Application User Username: k19 Password: 1234 Utilize o script add-user. Final / bin$ .1.br .users .sh para adicionar o usuário k19 no JBoss. properties ) (a ): b Enter the details of the new user to add . com . properties ’ Terminal 3.S TATEFUL S ESSION B EANS 9 56 Altere a classe CarrinhoMB do projeto carrinhoWeb. } Código Java 3. faces .enter Password : What roles do you want this user to belong to ? ( Please enter a comma separated list . import br . EJB .as -7.1: Criando um usuário no JBoss Configure o cache de SFSBs do JBoss.1. import javax .xml. sh What type of user do you wish to add ? a) Management User ( mgmt . 11 56 www.k19. List ./ add . private String produto . import javax .

< cache name = " passivating " passivation .. www.unit = " SECONDS " max .timeout . Você pode digitar “CTRL+3” em seguida “new Java project” e “ENTER”. < file ..xml 12 Crie um Java project no eclipse.size = " 5 " / > .com/k19treinamentos 57 ...store ..facebook.store name = " file " idle .timeout = " 1 " idle ..access ..ref = " file " aliases = " SimpleStatefulCache " / > .passivation . < stateful default .timeout = " 5 " cache . Depois.57 1 2 3 4 5 6 7 8 9 1 S TATEFUL S ESSION B EANS . siga exatamente as imagens abaixo.1: standalone.ref = " passivating " / > .. Código XML 3.

com.k19.br .S TATEFUL S ESSION B EANS 58 58 www.

59 S TATEFUL S ESSION B EANS www.com/k19treinamentos 59 .facebook.

create .br . public class TesteCicloDeVisaSFSB { public static void main ( String [] args ) throws Exception { Properties props = new Properties () . name = client .properties 1 2 3 4 5 6 Crie uma classe chamada TesteCicloDeVisaSFSB em um pacote chamado br. connection . INITIAL_CONTEXT_FACTORY .com. util . SSL_ENABLED = false remote . connectionprovider . import br . default .properties na pasta src do projeto carrinhoJavaSE. props . host = localhost remote . naming . default . 60 www.k19. org . connection . com . k19 . Context .testes no projeto carrinhoJavaSE. Options . connections = default remote .1: jboss-ejb-client. sessionbeans . import javax . Carrinho . import java . default . com . k19 . connect . xnio . options .com. testes .endpoint remote . 14 1 2 3 4 5 6 7 8 9 1 11 12 13 package br . org . connection . port =4447 remote . SASL_POLICY_NOANONYMOUS = ← false Arquivo de Propriedades 3. naming . options . xnio .k19. put ( Context . Options . Properties . endpoint . import javax .S TATEFUL S ESSION B EANS 60 13 Adicione o arquivo jboss-ejb-client. InitialContext .

SECURITY_PRINCIPAL . execute a classe TesteCicloDeVisaSFSB e observe o console do servidor. props .facebook. " remote ://127. com . props . put ( Context . sleep (1 ). carrinhos [ i ]. put ( Context . Carrinho " ) . } } Código Java 3. " k19 " ) . SECURITY_CREDENTIALS . InitialContext ic = new InitialContext ( props ) .K19 " ) . length . carrinhos [ ].java 15 Reinicie o JBoss 7. sleep (5 ). remote . www. InitialContextFactory " ) . carrinhos [ i ]. i ++) { carrinhos [ i ] = ( Carrinho ) ic . put ( Context . client . } carrinhos [ ].1 Runtime Server. S TATEFUL S ESSION B EANS for ( int i = . Carrinho [] carrinhos = new Carrinho [6]. k19 . adiciona ( " Borracha .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 . PROVIDER_URL . adiciona ( " Chaveiro . . adiciona ( " Caneta . . jboss .21: TesteCicloDeVisaSFSB. Thread .K19 " ) . Depois. Thread .K19 " ) . naming . props . i < carrinhos . finalizaCompra () .1:4447 " ) . " 1234 " ) . lookup ( " carrinhoWeb / CarrinhoBean ! br . sessionbeans .com/k19treinamentos 61 .

br .S TATEFUL S ESSION B EANS 62 62 www.com.k19.

com/k19treinamentos 63 . 1 2 3 4 5 6 7 8 9 1 11 12 class ContadorDeUsuariosBean { private int contador = public void adiciona () { this . contador ++. } } Código Java 4. } public List < String > listaSalas () { return new ArrayList < String >( this . A ideia fundamental dos Singleton Session Beans é a necessidade de compartilhar dados transientes entre todos os usuários de uma aplicação EJB. Podemos definir alguns métodos para implementar esse sistema. Uma única instância da classe ContadorDeUsuariosBean deve ser criada para contabilizar corretamente o número de usuários conectados. Sistema de chat Outro exemplo. Esse serviço pode ser implementado através da classe abaixo.java .1: ContadorDeUsuariosBean. contador . suponha o funcionamento de um sistema de chat no qual as salas são criadas dinamicamente pelos usuários durante a execução. public void criaSala ( String sala ) { this . Número de usuários conectados Para exemplificar. add ( sala ) . salas ) . suponha que seja necessário contabilizar a quantidade de usuários conectados à aplicação. Além disso. o contador de usuários conectados não precisa ser persistido entre duas execuções da aplicação. } } www. Este tipo de session bean surgiu na versão 3.1 da especificação Enterprise Java Beans.CAPÍTULO S INGLETON S ESSION B EANS 4 Caracterizando os Singleton Session Beans Singleton Session Bean é o terceiro tipo de session bean. } public int getContador () { return this .facebook. salas . 1 2 3 4 5 6 7 8 9 1 11 class ChatBean { private Set < String > salas = new HashSet < String >() .

1 2 3 4 5 6 7 8 9 1 11 12 13 class TransitoBean { private Map < String . o segundo passo seria implementar as operações do session bean através de uma classe java. } 64 www. salas . suponha que um Singleton Session Bean será utilizado para implementar um sistema de chat.2: ChatBean. List < Integer > > vias = new HashMap < String . 1 2 3 4 5 6 7 public class ChatBean implements Chat { private Set < String > salas = new HashSet < String >() . vias . Integer velocidade ) { if ( this .k19. get ( via ) . Por exemplo.java As salas são criadas dinamicamente e todos os usuários compartilham todas as salas. } } public List < Integer > getVelocidadesRegistradas ( String via ) { return this . add ( velocidade ) . get ( via ) . List < String > listaSalas () . A princípio. public void criaSala ( String sala ) { this . não é necessário manter esses dados persistidos.4: Chat.br .java Após definir a interface de utilização. vias . List < Integer > >() . Uma única instância da classe ChatBean deve ser criada já que as salas serão compartilhadas entre todos os usuários.java Os dados sobre o trânsito são fornecidos pelos usuários e todos podem consultar as mesmas informações. Trânsito Colaborativo Mais um exemplo. add ( sala ) .com. Implementação Para implementar um Singleton Session Bean podemos definir uma interface java com as assinaturas dos métodos de negócio. } } Código Java 4.S INGLETON S ESSION B EANS 64 Código Java 4. } Código Java 4. containsKey ( via ) ) { this . vias . suponha um sistema colaborativo para informar o grau de congestionamento nas vias de uma cidade.3: TransitoBean. As regras desse sistema poderiam ser implementadas através de alguns métodos. Se o sistema “cair” por qualquer que seja o motivo não é necessário guardar as salas pois na próxima execução novas salas serão criadas pelos usuários. 1 2 3 4 public interface Chat { void criaSala ( String sala ) . public void registra ( String via .

. } } Código Java 4. } Código Java 4. Quando o acesso a um session bean é local. public void criaSala ( String sala ) { this . Essa definição é realizada através da anotação @Singleton.. quando o acesso a um session bean é remoto. } Código Java 4. salas ) . class ) public class ChatBean implements Chat { . salas . No caso do chat. é necessário definir se o session bean poderá ser acessado remotamente ou apenas localmente. 1 2 3 4 @Singleton public class ChatBean implements Chat { . não é necessário definir uma interface java nem utilizar a anotação @Local..6: ChatBean.com/k19treinamentos 65 .java Singleton Session Beans Locais Quando o acesso a um Singleton Session Bean é local.java Por fim.java O terceiro passo é especificar o tipo de session bean que queremos utilizar.. Então.java 1 2 3 4 5 @Singleton @Local ( Chat . ele pode ser acessado tanto por aplicações que estejam no mesmo servidor de aplicação quanto aplicações que não estejam.5: ChatBean. class ) public class ChatBean implements Chat { . A definição do tipo de acesso é realizada através das anotações: @Local e @Remote. Caso contrário. 1 2 3 4 5 @Singleton @Remote ( Chat . } www.65 8 9 1 11 12 S INGLETON S ESSION B EANS public List < String > listaSalas () { return new ArrayList < String >( this .7: ChatBean. } public List < String > listaSalas () { return new ArrayList < String >( this . 1 2 3 4 5 6 7 8 9 1 11 12 @Singleton public class ChatBean { private Set < String > salas = new HashSet < String >() . ele só pode ser acessado por aplicações que estejam no mesmo servidor de aplicação que ele. } Código Java 4. o tipo seria Singleton.facebook. bastaria implementar uma classe java com a anotação @Singleton. add ( sala ) ..8: ChatBean. salas ) ..

Para isso.br . clique com o botão direito do mouse sobre esses projetos e selecione a opção “Close Project”. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. siga exatamente as imagens abaixo.com.S INGLETON S ESSION B EANS 13 } 66 Código Java 4.k19. feche os projetos carrinhoWeb e carrinhoJavaSE.java Exercícios de Fixação Para não confunfir.9: ChatBean. 2 66 www. 1 Crie um Dynamic Web Project no eclipse para implementar o funcionamento de um sistema de chat. Depois.

67 S INGLETON S ESSION B EANS www.com/k19treinamentos 67 .facebook.

com .10: ChatBean. util . util . java . k19 .k19.S INGLETON S ESSION B EANS 68 3 Crie um pacote chamado br. salas . import import import import java .k19. util . } public List < String > listaSalas () { return new ArrayList < String >( this . ejb . sessionbeans .java 68 www.com. HashSet . @Singleton public class ChatBean { private Set < String > salas = new HashSet < String >() . } } Código Java 4. Singleton .com. java . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 package br . ArrayList . import javax . java .sessionbeans no projeto chatWeb e adicione a seguinte classe nesse pacote.br . Set . List . util . salas ) . public void criaSala ( String sala ) { this . add ( sala ) .

@ManagedBean public class ChatMB { @EJB private ChatBean chatBean . import javax . ejb . k19 . ChatBean . com . private String sala . util . sala ) . Transitional // EN " " http :// www . faces . chatBean . sessionbeans . com / jsf / html " xmlns : f = " http :// java . } public String getSala () { return sala . 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. sala } " / > <h : commandButton value = " Criar " action = " #{ chatMB . managedbeans . listaSalas () .k19. salas } " var = " sala " > <h : column > <h : outputText value = " #{ sala } " / > </ h : column > www. w3 . adicionaSala } " / > < hr / > <h : dataTable value = " #{ chatMB . dtd " > < html xmlns = " http :// www . k19 . org / TR / xhtml1 / DTD / xhtml1 . com / jsf / facelets " xmlns : h = " http :// java . chatBean . bean . import java .com. com . } public void setSala ( String sala ) { this . } } Código Java 4. sun . org /1999/ xhtml " xmlns : ui = " http :// java . List . sun .11: ChatMB.xhtml na pasta WebContent do projeto chatWeb com o seguinte conteúdo. 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 . EJB .transitional .com/k19treinamentos 69 . com / jsf / core " > <h : head > < title > Chat </ title > </ h : head > <h : body > <h : form > <h : outputLabel value = " Nova Sala : " / > <h : inputText value = " #{ chatMB .69 4 S INGLETON S ESSION B EANS Crie um pacote chamado br. sala = sala . criaSala ( this . w3 . } public List < String > getSalas () { return this . ManagedBean . import br .managedbeans no projeto chatWeb e adicione a seguinte classe. import javax . sun .facebook.java Adicione o arquivo chat. public void adicionaSala () { this .

S INGLETON S ESSION B EANS 25 26 27 28 </ h : dataTable > </ h : form > </ h : body > </ html > Código XHTML 4. 70 www. é possível determinar que essa criação seja realizada na inicialização da aplicação através da anotação @Startup. Adicione o projeto chatWeb no Glassfish 3.1 Runtime Server esteja parado. o EJB Container é quem decide quando a criação da instância de um Singleton Session Bean deve ser realizada. dizemos que uma instância de um Singleton Session Bean se encontra no estado NÃO EXISTE. Por padrão. Estados O ciclo de vida das instâncias dos Singleton Session Beans possui dois estados. NÃO EXISTE 2. uma instância não pode atender as chamadas dos clientes da aplicação. PRONTO NÃO EXISTE -> PRONTO Antes de ser criada.1.2 e teste a aplicação acessando a url http://localhost:8 8 /chatWeb/chat. Utilize pelo menos dois navegadores diferentes para acessar a aplicação e observe que as mesmas salas são apresentadas nesses navegadores.2.1 Runtime Server.1. Obviamente.com. contador . contador ++.br . } } .xhtml. O EJB Container cria apenas uma instância para cada Singleton Session Bean. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 @Singleton @Startup class ContadorDeUsuariosBean { private int contador = public void adiciona () { this . Inicie o Glassfish 3. nesse estado. 1. 6 Ciclo de Vida As instâncias dos Singleton Session Beans são administradas pelo EJB Container. Para entender mais facilmente o ciclo de vida das instâncias dos Singleton Session Beans.1: chat. Contudo. Certifique-se que o JBoss 7. Devemos entender o de ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB.k19.xhtml 70 Remova o projeto carrinhoWeb do JBoss 7. } public int getContador () { return this . devemos sempre ter em mente que o EJB Container cria apenas uma instância de cada session bean desse tipo.

println ( " Contador de usuários criado .. elas passam do estado PRONTO para o NÃO EXISTE. Esse registro é realizado através da anotação @PostConstruct. www. Callbacks Podemos associar lógicas específicas nas transições de estado no ciclo de vida dos Singleton Session Beans.java Quando a instância de um Singleton Session Bean é criada.71 S INGLETON S ESSION B EANS Código Java 4. " ) . 1 2 3 4 5 6 @Singleton class ContadorDeUsuariosBean { @PostConstruct public void inicializando () { System . Dessa forma.com/k19treinamentos 71 . ela passa para do estado NÃO EXISTE para o estado PRONTO e pode atender as chamadas dos clientes da aplicação. @PostConstruct Podemos registrar um método de instância no EJB Container para que ele o execute em cada instância logo após ela ser criada. out .. o EJB Container destrói as instâncias dos Singleton Session Beans. PRONTO -> NÃO EXISTE Quando a aplicação é finalizada.12: ContadorDeUsuariosBean.facebook.

List . public void criaSala ( String sala ) { this . @PreDestroy Também podemos registrar um método de instância no EJB Container para que ele o execute em cada instância imediatamente antes dela ser destruída.com. PreDestroy . java . Por fim. util . os métodos anotados com @PostConstruct são executados. Set . @Singleton public class ChatBean { private Set < String > salas = new HashSet < String >() . package br . k19 .k19. } public List < String > listaSalas () { return new ArrayList < String >( this . annotation . Esse registro é realizado através da anotação @PreDestroy. ArrayList . salas ) . ejb . 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 . Singleton . } // METODOS DE NEGOCIO } Código Java 4. salas . Depois de chamar o construtor sem argumentos. annotation .java Exercícios de Fixação 7 Altere a classe ChatBean do projeto chatWeb.14: ContadorDeUsuariosBean. util .. HashSet . util . " ) .. util .13: ContadorDeUsuariosBean. com . import javax . } @PostConstruct 72 www. sessionbeans . PostConstruct . out .br . import javax . println ( " Contador de usuários será destruído . add ( sala ) . o EJB Container injeta eventuais dependências na instância criada. 1 2 3 4 5 6 7 8 9 1 @Singleton class ContadorDeUsuariosBean { @PreDestroy public void destruindo () { System .S INGLETON S ESSION B EANS 7 8 9 1 } // METODOS DE NEGOCIO } Código Java 4. java . import import import import java . java .java 72 O EJB Container utiliza o construtor sem argumentos para criar a instância de um Singleton Session Bean.

• Pare o Glassfish 3. • Reinicie o Glassfish 3. a instância de um Singleton Session Bean pode processar diversas chamadas a métodos de negócio simultaneamente.1. • Acesse o endereço http://localhost:8 8 /chatWeb/chat.. println ( " Criando o ChatBean .java 1 2 3 4 5 6 10 Inicie o Glassfish 3.xhtml e observe que agora a mensagem aparece no console. lembre-se que não é necessarário pois esse é o modo padrão. Em outras palavras.15: ChatBean.com/k19treinamentos 73 ... } @PreDestroy public void preDestroy () { System . out . println ( " Destruindo o ChatBean . podemos declarar o modo CMC através da anotação @ConcurrencyManagement. } Código Java 4.2 e observe que a mensagem de criação não aparece no console.1.73 26 27 28 29 3 31 32 33 34 public void postConstruct () { System . • Tente acessar o mesmo endereço através de outros navegadores e repare que a mensagem de criação não aparece novamente no console. 1 2 @Singleton @ConcurrencyManagement ( ConcurrencyManagementType . } } Código Java 4.java S INGLETON S ESSION B EANS 8 Teste os métodos de callback seguindo os passos abaixo.2 e observe no console a mensagem de destruição.1. Opcionalmente. " ) . . out .facebook. CONTAINER ) www.16: ChatBean. Concorrência Um Singleton Session Bean suporta acesso concorrente..2 e observe que a mensagem de criação já aparece no console.... Mas. Há dois modos de gerenciamento de acesso à instância de um Singleton Session Bean: • Container Managed Concurrency (CMC) • Bean Managed Concurrency (BMC) O modo padrão de gerenciamento é o CMC. @Singleton @Startup public class ChatBean { . " ) .. 9 Altere novamente a classe ChatBean.

no CMC.S INGLETON S ESSION B EANS 3 4 5 public class ContadorDeUsuariosBean { . Chamadas a métodos associados ao Read Lock podem ser executadas simultaneamente. os métodos são associados ao Write Lock. chamadas a métodos associados ao Write Lock são executadas uma de cada vez.20: ContadorDeUsuariosBean.com.k19. } Código Java 4. Opcionalmente.java 1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton public class ContadorDeUsuariosBean { private int contador = . } public int getContador () { return this . Por outro lado.java A anotação @Lock pode ser aplicada na classe do session bean ou diretamente nos métodos de negócio. lembre-se que não é necessário pois o Write Lock é associado aos métodos de negócio por padrão. 1 2 3 4 5 @Singleton @ConcurrencyManagement ( ConcurrencyManagementType .. 1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton @Lock ( LockType . Por padrão. public void adiciona () { this .java 74 Para selecionar o modo BMC. contador ++... WRITE ) public class ContadorDeUsuariosBean { private int contador = . Mas.. todo método de negócio é associado ao Read Lock ou ao Write Lock. } Código Java 4. } } Código Java 4.18: ContadorDeUsuariosBean. podemos declarar o tipo de Lock através da anotação @Lock. WRITE ) public void adiciona () { this . @Lock ( LockType . BEAN ) public class ContadorDeUsuariosBean { . } } Código Java 4. } public int getContador () { return this .java CMC No modo CMC. devemos utilizar a anotação @ConcurrencyManagement. contador . 74 www. contador ++.19: ContadorDeUsuariosBean. contador .17: ContadorDeUsuariosBean.br .

devemos utilizar a anotação @Lock na classe do session bean ou nos métodos de negócio. k19 . Para isso. } } Código Java 4. você precisa ter bons conhecimento de programação concorrente. public void adiciona () { this . com . int getValor () . www.com/k19treinamentos 75 . Exercícios de Fixação 11 Crie uma inteface chamada Contador no pacote br.sessionbeans do projeto chatWeb.facebook.java BMC No modo BMC.21: ContadorDeUsuariosBean.com. contador ++.sessionbeans do projeto chatWeb.23: Contador. 1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton @Lock ( LockType .k19.75 S INGLETON S ESSION B EANS Para associar o Read Lock aos métodos de negócio. } public int getContador () { return this . package br . sessionbeans . } Código Java 4. o controle de concorrência deve ser implementado dentro dos métodos de negócio. READ ) public class ContadorDeUsuariosBean { private int contador = .concurrent. READ ) public int getContador () { return this .java 1 2 3 4 5 6 7 8 12 Crie uma classe chamada ContadorBean no pacote br.java 1 2 3 4 5 6 7 8 9 1 11 12 13 @Singleton public class ContadorDeUsuariosBean { private int contador = . } @Lock ( LockType .22: ContadorDeUsuariosBean. contador . } } Código Java 4.com. contador . public interface Contador { void incrementa () .k19. contador ++. Você pode utilizar a instrução synchronized ou os recursos do pacote java.util. public void adiciona () { this .

valor . public void incrementa () { this .br . LockType . Você pode digitar “CTRL+3” em seguida “new Java project” e “ENTER”. } } Código Java 4.com. class ) public class ContadorBean implements Contador { private int valor . import import import import javax .java Crie um Java project no eclipse. com . javax . ejb . ejb . 13 76 www. siga exatamente as imagens abaixo. } public int getValor () { return this . sessionbeans . Depois. Lock . Singleton . javax . ejb . 76 @Singleton @Lock ( LockType . k19 .S INGLETON S ESSION B EANS 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 package br . valor ++. ejb .24: ContadorBean. javax .k19. Remote . READ ) @Remote ( Contador .

77 S INGLETON S ESSION B EANS www.com/k19treinamentos 77 .facebook.

br .S INGLETON S ESSION B EANS 78 78 www.com.k19.

println ( " Contador = " + contador . import br . System . sessionbeans . length . out . incrementa () . import javax . threads [ i ]. System . length + " vezes " ) . i < threads . com . public class TesteDeAcessoConcorrente { public static void main ( String [] args ) throws Exception { InitialContext ic = new InitialContext () . } } }) . final Thread [] threads = new Thread [2 ]. length * threads . start () . Contador .com.79 S INGLETON S ESSION B EANS 14 Crie uma classe chamada TesteDeAcessoConcorrente em um pacote chamado br. final Contador contador = ( Contador ) ic . testes . getValor () ) .com/k19treinamentos 79 . naming . InitialContext . i < threads . println ( " Incrementando " + threads . k19 . lookup ( " java : global / chatWeb / ContadorBean " ) . for ( int i = . k19 .k19. length . www.testes no projeto contadorJavaSE.facebook. i ++) { threads [ i ] = new Thread ( new Runnable () { @Override public void run () { for ( int i = . 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 . i ++) { contador . out . com .

17 80 www. } } Código Java 4. javax . Remote .26: ContadorBean.k19. getValor () ) . javax . LockType . valor .com. } @Lock ( LockType . ejb . 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 .java 80 Execute alguns vezes a classe TesteDeAcessoConcorrente e observe que o valor do contador não estará correto. class ) public class ContadorBean implements Contador { private int valor . sessionbeans . import import import import javax .S INGLETON S ESSION B EANS 29 3 31 32 33 34 35 36 37 } for ( Thread thread : threads ) { thread . println ( " Contador = " + contador . Singleton . join () .2. Execute alguns vezes a classe TesteDeAcessoConcorrente e observe que o valor do contador estará correto. com .br . ejb . package br . Lock . } System .25: TesteDeAcessoConcorrente. READ ) public int getValor () { return this . ejb . valor ++. } } Código Java 4. ejb .1. 15 16 Modifique a classe ContadorBean do projeto chatWeb. javax . out . public void incrementa () { this .java Reinicie o Glassfish 3. k19 .

Por exemplo. 2 www. Quando definidas em uma aplicação serão utilizadas somente por essa aplicação. as configurações JDBC são definidas em componentes chamados Data Sources. A criação de Data Sources depende do servidor de aplicação utilizado. Acesse o MySQL Server através do MySQL Workbench ou através do cliente de linha de comando. a configuração de um Connection Pool.com/k19treinamentos 81 .jar que se encontra na pasta K19-Arquivos/MySQL-Connector-JDBC da Área de Trabalho para a pasta glassfishv3/glassfish/lib. Exercícios de Fixação 1 Vamos configurar um Data Source no Glassfish.br/arquivos. Quando definidas em um servidor de aplicação podem ser utilizadas em diversas aplicações. As configurações relativas às conexões JDBC podem ser definidas nas aplicações ou nos servidores de aplicação. com. Importante Você também pode obter o driver JDBC do MySQL através do site da K19: www. Os Data Sources permitem que uma única configuração JDBC seja utilizada por diversas aplicações. Além disso. no Glassfish. Em particular. os Data Sources podem ser criados através da interface de administração. Copie o arquivo mysql-connector-java-VERSAObin.facebook. Eles também permitem que outros tipos de configurações sejam compartilhadas. algumas informações como usuário. senha e base de dados são necessárias. apague a base de dados k22_glassfish caso ela exista. Esse serviço é definido pela especificação Java Transaction API (JTA).k19.CAPÍTULO P ERSISTÊNCIA 5 Data Sources Aplicações Java se comunicam com banco de dados através de conexões JDBC. crie uma base de dados chamada k22_glassfish. Em um servidor de aplicação. através de Data Sources podemos utilizar facilmente o serviço de transações dos servidores de aplicação. Para estabelecer uma conexão JDBC.

com. Siga os passos abaixo: 82 www.br .k19.P ERSISTÊNCIA 3 82 Reinicie o Glassfish 3.2. abra a interface de administração acessando a url localhost:4848.1.

siga os passos abaixo: www. Para testar o Connection Pool K19.83 P ERSISTÊNCIA Defina os seguintes valores para as seguintes propriedades: DatabaseName: k22_glassfish Password: root ServerName: localhost URL: jdbc:mysql://localhost:3306/k22_glassfish url: jdbc:mysql://localhost:3306/k22_glassfish User: root Depois.facebook. clique em finish.com/k19treinamentos 83 .

br .k19.com.P ERSISTÊNCIA 84 OBS: A mensagem “Ping Succeeded” deve aparecer. 84 www.

85 P ERSISTÊNCIA Agora vamos criar o Data Source. Siga os passos abaixo: www.facebook.com/k19treinamentos 85 .

bin .1. com. Acesse o MySQL Server através do MySQL Workbench ou através do cliente de linha de comando. 5 Na pasta modules/com/mysql/main do JBoss. vamos configurar um Data Source no JBoss. 6 7 Altere o arquivo de configuração do JBoss (standalone/configuration/standalone. apague a base de dados k22_jboss caso ela exista.br/arquivos.java -5.1: module. Copie o arquivo mysql-connector-java-VERSAO-bin.P ERSISTÊNCIA 4 86 Agora. " name = " com . mysql " > < resources > < resource .jar que se encontra na pasta K19-Arquivos/MySQLConnector-JDBC da Área de Trabalho para a pasta main. " encoding = " UTF -8 " ? > < module xmlns = " urn:jboss:module:1 .k19.. Adicione dentro da tag <datadources> a configuração de um novo Data Source.k19. 1 .xml 1 2 3 4 5 6 7 8 9 Na linha 4.13 . jar " / > </ resources > < dependencies > < module name = " javax . crie um arquivo chamado module. indique corretamente o nome correspondente ao arquivo do driver que você está utilizando.br . Crie uma pasta chamada mysql dentro da pasta modules/com do JBoss. Dentro da pasta mysql crie uma pasta chamada main.xml.root path = " mysql . 86 www.xml). Importante Você também pode obter o driver JDBC do MySQL através do site da K19: www..connector . crie uma base de dados chamada k22_jboss. api " / > </ dependencies > </ module > Código XML 5. <? xml version = " 1.com.

Bound data source [java:/jdbc/K19] persistence. Código XML 5. ← MySQL5InnoDBDialect " / > </ properties > </ persistence .class > </ driver > . w3 . Inicie o JBoss 7.2. jdbc2 .com/k19treinamentos 87 . 1 2 3 4 5 6 7 . auto " value = " update " / > < property name = " hibernate . mysql </ driver > < security > < user . sun .ccm = " true " > < connection .xml 8 Pare o Glassfish 3. format_sql " value = " true " / > < property name = " hibernate . < driver name = " com . MysqlXADataSource </ xa .xml P ERSISTÊNCIA Depois.url > < driver > com . algumas configurações ainda devem ser realizadas pelas aplicações. show_sql " value = " true " / > < property name = " hibernate . sun .2: standalone.url > jdbc:mysql: // localhost:33 6 / k22_jboss </ connection ..source > < properties > < property name = " hibernate . No console.1 Runtime Server e observe se o Data Source foi criado corretamente. ejb .datasource . optional . mysql " module = " com . hibernate . " encoding = " UTF -8 " ? > < persistence version = " 2.data .facebook. HibernatePersistence </ provider > <jta . deve aparecer uma mensagem semelhante a que é apresentada abaixo.3: standalone.class > com . com / xml / ns / persistence http: // java .name = " java: / jdbc / K19 " pool . com / xml / ns / persistence " xmlns:xsi = " http: // www .instance " xsi:schemaLocation = " http: // java .java .. No arquivo persistece. org /2 1/ XMLSchema ..xml dentro de uma pasta chamada META-INF no classpath da aplicação. adicione dentro da tag <drivers> a seguinte configuração..xml Em um ambiente Java EE. jdbc .. mysql " > <xa . Contudo. xsd " > < persistence .source > jdbc / K19 </ jta .data . dialect .datasource . Código XML 5. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 <? xml version = " 1. com / xml / ← ns / persistence / persistence_2_ .xml podemos definir qual Data Source será utilizado pela aplicação. hibernate . dialect " value = " org .unit name = " K19 " transaction . hbm2ddl .name > < password > root </ password > </ security > </ datasource > .87 2 3 4 5 6 7 8 9 1 11 < datasource jndi .type = " JTA " > < provider > org .name > root </ user . A especificação JPA determina que cada aplicação contenha um arquivo de configurações chamado persistence..unit > </ persistence > www.context = " true " use . " xmlns = " http: // java .name = " K19 " jta = " true " enabled = " true " use .1. diversas configurações relativas à persistência são realizadas nos Data Sources. mysql . sun .

Outra vez. Mas. Por convenção. podemos alterar esse comportamento utilizando a anotação @Table. As Entity Classes devem ser mapeadas para tabelas no banco de dados através de anotações ou XML. Os atributos declarados em uma classe anotada com @Entity são mapeados para colunas na tabela correspondente à classe. As principais anotações de mapeamento são: @Entity É a principal anotação do JPA. E novamente.P ERSISTÊNCIA 88 Código XML 5. Serve para indicar que o valor de um atributo que compõe uma chave primária deve ser gerado pelo banco no momento em que um novo registro é inserido. @GeneratedValue Geralmente vem acompanhado da anotação @Id. podemos alterar esse padrão utilizando para isso a anotação @Column.4: persisntece. Por outro lado.k19. São exemplos de entity beans que poderiam formar uma aplicação: • clientes • produtos • pedidos • funcionários • fornecedores Entity Classes e Mapeamento Os Entity Beans são definidos por classes java (Entity Classes).br . Supondo uma aplicação que administra livros e autores. @Id Utilizada para indicar qual atributo de uma classe anotada com @Entity será mapeado para a chave primária da tabela correspondente à classe.xml Entity Beans As regras de negócio de uma aplicação EJB são implementadas nos session beans. As seguintes classes são exemplos de Entity Classes mapeadas com anotações que poderiam ser utilizadas no contexto dessa aplicação: 1 2 @Entity public class Livro { 88 www.com. as tabelas possuem os mesmos nomes das classes. As classes anotadas com @Entity são mapeadas para tabelas. E deve ser definida em todas as classes que terão objetos persistidos no banco de dados. as colunas possuem os mesmos nomes dos atributos. por convenção. Ela que deve aparecer antes do nome de uma classe. os dados da aplicação que devem ser persistidos são armazenados em objetos chamados Entity Beans. Geralmente o atributo anotado com @Id é do tipo Long.

java 1 2 3 4 5 6 7 8 9 1 11 12 13 @Entity public class Autor { @Id @GeneratedValue ( strategy = GenerationType .br/downloads/apostilas-java.2: Autor. Depois.k19.1: Livro. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. feche os projetos chatWeb e contadorJavaSE. private String nome . @ManyToMany private List < Livro > livros .java Consulte a apostila do curso “K21 . private String nome .com/k19treinamentos 89 . IDENTITY ) private Long id . // GETTERS AND SETTERS } Código Java 5. Para isso. private Double preco .facebook.com.Persistência com JPA 2 e Hibernate” para obter detalhes sobre o mapeamento das Entity Classes http://www. clique com o botão direito do mouse sobre esses projetos e selecione a opção “Close Project”.89 3 4 5 6 7 8 9 1 11 12 P ERSISTÊNCIA @Id @GeneratedValue ( strategy = GenerationType . // GETTERS AND SETTERS } Código Java 5. siga exatamente as imagens abaixo. IDENTITY ) private Long id . 10 www. Exercícios de Fixação Para não confunfir. 9 Crie um Dynamic Web Project no eclipse chamado persistenciaWeb.

br .P ERSISTÊNCIA 90 90 www.k19.com.

facebook.com/k19treinamentos 91 .91 P ERSISTÊNCIA www.

P ERSISTÊNCIA

92

92

www.k19.com.br

93

P ERSISTÊNCIA

11

Adicione uma pasta chamada META-INF na pasta src do projeto persistenciaWeb.

12

Faça as configurações de persistência adicionando o arquivo persistence.xml na pasta META-

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 ERSISTÊNCIA
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 >
Código 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 definir 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 }
Código Java 5.3: Livro.java

Adicione no pacote br.com.k19.entidades uma Entity Class para definir 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

xml. createEntityManager () . o controle da criação e do fechamento dos Entity Managers é responsabilidade das aplicações. • Sincronizar o conteúdo dos Entity Beans com os registros das tabelas do banco de dados. 1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceContext private EntityManager manager . nos Data Sources e através das anotações de mapeamento nas Entity Classes.7: CalculadoraBean.4: Autor. em um ambiente Java EE. Consulte a apostila do curso “Persistência com JPA 2” para obter detalhes sobre o funcionamento dos Entity Managers http://www. www. dentro de um Session Bean. Uma aplicação Java SE deve chamar.com/k19treinamentos 95 . o gerenciamento dos Entity Managers pode ser atribuído ao servidor de aplicação. explicitamente. podemos pedir a injeção de um Entity Manager através da anotação @PersistenceContext. Nesse caso. close () . 1 manager . • Montar Entity Beans com os dados obtidos do banco de dados através de consultas. Por outro lado.95 P ERSISTÊNCIA Código Java 5. // Resto do código } Código Java 5. As principais responsabilidade dos Entity Managers são: • Recuperar as informações armazenadas no banco de dados.java Entity Managers Os Entity Managers são objetos que administram os Entity Beans. Obtendo Entity Managers Em um ambiente Java SE.java Entity Manager Factories As Entity Managers Factories são objetos responsáveis pela criação de Entity Managers de acordo com as configurações definidas no arquivo persistence. ela pode utilizar o recurso de Injeção de Dependência oferecido pelo servidor de aplicação.facebook. Por exemplo.br/downloads/apostilas-java. o método createEntityManager() em uma Entity Manager Factory para obter um novo Entity Manager ou o método close() em um Entity Manager para fechá-lo.com.k19. para uma aplicação Java EE obter um Entity Manager. 1 EntityManager manager = factory .

sessionbeans .com. 96 www. EntityManager . 1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceUnit private EntityManagerFactory factory . o comum é utilizar diretamente os Entity Managers que são obtidos com a anotação @PersisteceContext. Stateless . uma Entity Manager Factory é obtida através do método estático createEntityManagerFactory() da classe Persistence. com . o controle sobre a criação das Entity Manager Factories é responsabilidade do servidor de aplicação. import java . Na verdade.java Exercícios de Fixação Crie um pacote chamado br.P ERSISTÊNCIA 96 Obtendo Entity Manager Factories Em um ambiente Java SE. as aplicações Java EE não necessitam interagir diretamente com as Entity Manager Factories. 1 EntityManagerFactory factory = Persistence .9: CalculadoraBean. ejb . o servidor de aplicação evita a criação de fábricas desnecessárias. persistence . O método createEntityManagerFactory() deve ser chamado apenas uma vez a cada execução da aplicação. 1 2 3 4 5 6 7 8 @Stateless public class CalculadoraBean { @PersisteceContext private EntityManager manager .10: CalculadoraBean. import javax . ela deve utilizar a anotação @PersistenceUnit para pedir a injeção desse objeto. Se uma aplicação Java EE deseja obter a Entity Manager Factory criada pelo servidor de aplicação.java Em geral. Por outro lado.br . import javax .k19. k19 .com. util .k19. Inclusive. Não é necessário chamá-lo mais do que uma vez porque a aplicação não necessita de mais do que uma Entity Manager Factory e o custo de criação desse objeto é alto.sessionbeans no projeto persistenciaWeb e adicione nesse pacote um SLSB para funcionar como repositório de livros. // Resto do código } Código Java 5. List . createEntityManagerFactory ( " unidade " ) . 15 1 2 3 4 5 6 package br . em um ambiente Java EE. // Resto do código } Código Java 5.

manager . EJB . import br . return query . com . public void adiciona ( Livro livro ) { this .k19. persistence . Livro . livrosCache = this . createQuery ( " select x from Livro x " . getResultList () . Livro .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 . import javax . persist ( livro ) . ManagedBean . } return this . livro = new Livro () . entidades . Livro . k19 . LivroRepositorio . 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 . private Livro livro = new Livro () . import javax . managedbeans . repositorio . livrosCache = null . bean . k19 . class ) . getLivros () . livro = livro . livrosCache .11: LivroRepositorio. com . k19 . faces .facebook. k19 . PersistenceContext . repositorio .managedbeans no projeto persistenciaWeb e adicione nesse pacote um Managed Bean para oferecer algumas ações para as telas. import br . @Stateless public class LivroRepositorio { @PersistenceContext private EntityManager manager . entidades . persistence .java P ERSISTÊNCIA 16 Crie um pacote chamado br. livrosCache == null ) { this .com/k19treinamentos 97 . util . adiciona ( this . ejb . this . com .com. } public Livro getLivro () { return livro . import javax . } public List < Livro > getLivros () { TypedQuery < Livro > query = this . this . manager . } } Código Java 5. List . import br . } public void setLivro ( Livro livro ) { this . TypedQuery . } public List < Livro > getLivros () { if ( this . sessionbeans . import java . public void adiciona () { this . www. private List < Livro > livrosCache . livro ) . @ManagedBean public class LivroMB { @EJB private LivroRepositorio repositorio .

1. 19 20 Remova o projeto persistenciaWeb do Glassfish 3. 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. nome } " / > </ h : column > <h : column > <h : outputText value = " #{ livro .transitional . preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 5.xhtml Remova o projeto chatWeb do Glassfish 3.xhtml.P ERSISTÊNCIA 4 41 } } Código Java 5. livro . 18 Acesse o MySQL Server através do MySQL Workbench ou através do cliente de linha de comando. Inicie o Glassfish 3. Adicione o projeto persistenciaWeb no JBoss 7. org / TR / xhtml1 / DTD / xhtml1 . livro . Transitional // EN " " http :// www . livros } " var = " livro " > <h : column > <h : outputText value = " #{ livro .k19. org /1999/ xhtml " xmlns : ui = " http :// java .1 Runtime Server e teste a aplicação acessando a url http://localhost:8 8 /persistenciaWeb/ livros.xhtml.xhtml com o seguinte conteúdo.br . preco } " / > <h : commandButton action = " #{ livroMB . w3 .1. com / jsf / facelets " xmlns : h = " http :// java .2 esteja parado.2 e teste a aplicação acessando a url http://localhost:8 8 /persistenciaWeb/livros.12: LivroMB. Inicie o JBoss 7.1 Runtime Server. 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 .com.2. 98 www.1: livros.1. com / jsf / html " xmlns : f = " http :// java . sun . sun . Certifique-se que o JBoss 7. sun .1. Certifique-se que o Glassfish 3.2. nome } " / > <h : outputLabel value = " Preço : " / > <h : inputText value = " #{ livroMB .1.1 Runtime Server esteja parado.2.java 98 Crie uma tela para cadastrar livros. Adicione o projeto persistenciaWeb no Glassfish 3. adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Livros </ h1 > <h : dataTable value = " #{ livroMB . Adicione na pasta WebContent um arquivo chamado livros. w3 . Verifique as tabelas geradas na base de dados k22_glassfish e seus respectivos dados. dtd " > < html xmlns = " http :// www .

com/k19treinamentos 99 . www.99 21 P ERSISTÊNCIA Acesse o MySQL Server através do MySQL Workbench ou através do cliente de linha de comando. Verifique as tabelas geradas na base de dados k22_jboss e seus respectivos dados.facebook.

k19.com.P ERSISTÊNCIA 100 100 www.br .

CAPÍTULO

T RANSAÇÕES

6

Geralmente, uma aplicação realiza diversas tarefas diferentes. Também é comum e muitas vezes necessário dividir as tarefa em pequenos passos. Daí surge o conceito de transação. Uma transação é um conjunto de passos que devem ser executados em uma ordem específica para que uma determinada tarefa seja realizada. Tipicamente, as transações modificam informações armazenadas em resources (bases de dados, filas de mensagens, sistemas corporativos de informação - EIS, entre outros).

ACID
Além da restrição natural de ordem, as transações possuem outras quatro propriedades fundamentais: Atomicidade, Consistência, Isolamento e Durabilidade. A sigla ACID é utilizada para indicar a existência dessas propriedades.

Atomicidade: Todos os passos de uma transação devem ser executados com sucesso para que a própria transação seja executada com sucesso. Se algum passo falhar a transação falhará e todos os passos realizados até o momento da falha serão desfeitos. Consistência: Não pode existir inconsistência nos dados da aplicação nem antes nem depois da execução de uma transação. Ou seja, uma transação leva a aplicação de um estado consistente para outro estado consistente. Isolamento: Alterações realizadas por uma transação não finalizada não podem afetar operações que não fazem parte da transação. Durabilidade: Após a confirmação de uma transação, as modificações realizadas por ela devem ser refletidas nos resources mesmo que aconteça uma falha de hardware.

Transação Local ou Distribuída
Quando as alterações realizadas por uma transação afetam apenas um resource (bases de dados, filas de mensagens, sistemas corporativos de informação - EIS, entre outros), dizemos que a transação é local. Caso contrário, se dois ou mais resources são modificados por uma única transação ela é dita distribuída.

JTA e JTS
www.facebook.com/k19treinamentos

101

T RANSAÇÕES

102

Todo servidor de aplicação Java EE deve oferecer suporte para as aplicações utilizarem transações. As especificações relacionadas a esse tópico são: Java Transaction API - JTA e Java Transaction Service - JTS. Os documentos dessas especificações podem ser obtidos através do site: www.jcp.org. A especificação Enterprise Java Beans (EJB) é fortemente integrada com as especificações JTA e JTS, simplificando bastante o trabalho dos desenvolvedores de aplicação EJB que não precisam em momento nenhum lidar diretamente com JTS e muito pouco com JTA. Na arquitetura EJB, as aplicações podem gerenciar as transações de dois modos:

• Container Managed Transactions - CMT

• Bean Managed Transactions - BMT

Container Managed Transactions - CMT
Quando optamos pelo gerenciamento CMT, a responsabilidade de abrir, confirmar ou abortar transações é atribuída ao EJB Container. Contudo, a aplicação deve indicar ao EJB Container através de configurações quando ele deve abrir, confirmar ou abortar transações. Podemos definir o modo CMT individualmente para cada Session Bean da nossa aplicação através da anotação @TransactionManagement.
1 2 3 4 5 @Stateful @TransactionManagement ( TransactionManagementType . CONTAINER ) public class CarrinhoBean { ... }

O modo CMT é padrão. Dessa forma, tecnicamente, não é necessário acrescentar a anotação

@TransactionManagement. Mas, podemos adicioná-la com o intuito de explicitar a opção de gerenciamento transacional.

Atributo Transacional
O EJB Container abre, confirma, aborta ou suspende transações de acordo com o atributo transacional de cada método dos Session Beans em modo CMT. O atributo transacional de um método pode ser definido 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 RANSAÇÕES

Atributo Transacional REQUIRED REQUIRED REQUIRES_NEW REQUIRES_NEW SUPPORTS SUPPORTS MANDATORY MANDATORY NOT_SUPPORTED NOT_SUPPORTED NEVER NEVER

Já existia uma transação aberta? NÃO SIM NÃO SIM NÃO SIM NÃO SIM NÃO SIM NÃO SIM

O que o EJB Container faz? Abre uma nova transação Usa a transação que já estava aberta Abre uma nova transação Abre uma transação e Suspende a que estava aberta Não faz nada Usa a transação que já estava aberta Lança EJBTransactionRequiredException Usa a transação que já estava aberta Não faz nada Suspende a que estava aberta Não faz nada Lança EJBException

O atributo transacional de um método pode ser definido pela anotação @TransactionAttribute.
1 2 3 4 @TransactionAttribute ( TransactionAttributeType . REQUIRED ) public void adiciona ( String produto ) { ... }

Quando queremos que todos os métodos 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 definido explicitamente, o EJB Container utilizará por padrão o REQUIRED.

Rollback com SessionContext
Quando algum erro é identificado pela aplicação, ela pode marcar a transação corrente para rollback através do setRollbackOnly() do Session Context que pode ser obtido através de injeção com a anotação @Resource.
1 2 3 4 5 6 7 8 @Stateful public class CarrinhoBean { @Resource private SessionContext context ; public void adiciona ( String produto ) { if ( produto == null ) {

www.facebook.com/k19treinamentos

103

} .4: CarrinhoBean.br .. quando uma Application Exception é lançada.java Bean Managed Transactions .BMT Quando optamos pelo gerenciamento BMT. transações podem ser abortadas pelo EJB Container.. Application Exceptions: Todas Checked Exceptions exceto as java. são consideradas System Exceptions. quando um método de um Session Bean lança uma System Exception. o EJB Container não aborta a transação corrente. Devemos entender a classificação das exceptions para saber quando as transações serão abortadas. Na arquitetura EJB. confirmar ou abortar transações é atribuída a aplicação.rmi. são consideradas Application Exceptions.k19. Por outro lado. por padrão. a responsabilidade de abrir.com.RemoteException. Podemos utilizar a anotação @ApplicationException para alterar a classificação de uma System Exception.java 104 Rollback com Exceptions Quando exceptions ocorrem. setRollbackOnly () . BEAN ) 104 www.rmi. o EJB Container aborta a transação corrente.6: ValorNegativoException. por padrão. 1 2 3 4 @ApplicationException ( rollback = true ) public class ValorNegativoException extends RuntimeException { } Código Java 6. Podemos definir o modo BMT individualmente para cada Session Bean da nossa aplicação através da anotação @TransactionManagement. Por padrão.5: ValorNegativoException.RemoteException. } } Código Java 6. as exceptions são classificadas em dois grupos: System Exceptions: Todas Unchecked Exceptions e as java. 1 2 @Stateful @TransactionManagement ( TransactionManagementType .T RANSAÇÕES 9 1 11 12 13 context . 1 2 3 4 @ApplicationException public class ValorNegativoException extends RuntimeException { } Código Java 6.java A mesma anotação pode alterar o comportamento padrão para rollback das Application Exceptions.

java O modo BMT permite um controle maior sobre as transações. 2 www.com/k19treinamentos 105 . devemos injetar um UserTransaction através da anotação @Resource.java No modo BMT. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 @Stateful @TransactionManagement ( TransactionManagementType . siga exatamente as imagens abaixo. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. } catch ( ProdutoInvalidoException e ) { ut .8: CarrinhoBean.facebook. o modo CMT é mais simples de utilizar e mais fácil de manter.105 3 4 5 public class CarrinhoBean { . // IMPLEMENTACAO ut . Para isso. public void adiciona ( Produto p ) { try { ut . begin () . clique com o botão direito do mouse sobre esse projeto e selecione a opção “Close Project”. Exercícios de Fixação Para não confunfir. feche os projetos persistenciaWeb. Depois. printStackTrace () . commit () . } } } Código Java 6. Contudo. rollback () . Esse objeto permite que a aplicação abra.7: CarrinhoBean. confirme ou aborte transações. BEAN ) public class CarrinhoBean { @Resource private UserTransaction ut . } T RANSAÇÕES Código Java 6. 1 Crie um Dynamic Web Project no eclipse chamado transacoesWeb. } catch ( Exception e ) { e ...

k19.com.br .T RANSAÇÕES 106 106 www.

com/k19treinamentos 107 .facebook.107 T RANSAÇÕES www.

data . k19 . Resource .br . 4 Faça as configurações de persistência adicionando o arquivo persistence. import javax . // GETTERS AND SETTERS } Código Java 6. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. import javax . GeneratedValue .k19. annotation .T RANSAÇÕES 3 108 Adicione uma pasta chamada META-INF na pasta src do projeto transacoesWeb. entidades . 6 1 2 3 4 5 6 package br . import javax . xsd " > < persistence . hibernate . Entity . import javax . sessionbeans .com. com / xml / ns / persistence http: // java .type = " JTA " > < provider > org .xml Crie um pacote chamado br.source > < properties > < property name = " hibernate .com. ejb . com . persistence . show_sql " value = " true " / > < property name = " hibernate .xml na pasta META- INF.java Crie um pacote chamado br. format_sql " value = " true " / > < property name = " hibernate .1: persistence. org /2 1/ XMLSchema . persistence . " encoding = " UTF -8 " ? > < persistence version = " 2. List .unit name = " K19 " transaction . com / xml / ns / persistence " xmlns:xsi = " http: // www . MySQL5InnoDBDialect " / > </ properties > </ persistence . hibernate . import java .data . import javax . ejb . sun . hbm2ddl . Id .sessionbeans no projeto transacoesWeb e adicione nesse pacote um SLSB para funcionar como repositório de produtos. HibernatePersistence </ provider > <jta . " xmlns = " http: // java .k19. com .unit > </ persistence > Código XML 6. dialect " value = " org . sun .9: Produto. auto " value = " update " / > < property name = " hibernate . persistence . private String nome . private double preco .entidades no projeto transacoesWeb e adicione nesse pacote uma Entity Class para definir 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 . dialect . @Entity public class Produto { @Id @GeneratedValue private Long id . 108 www.instance " xsi:schemaLocation = " http: // java . SessionContext .source > jdbc / K19 </ jta . k19 . sun . w3 . com / xml / ns / persistence / persistence_2_ .k19.com. util .

javax . Stateless . context . bean . produtosCache = null . repositorio . EntityManager . getResultList () .facebook. ejb . entidades . persistence . createQuery ( " select x from Produto x " . www.managedbeans no projeto transacoesWeb e adicione nesse pacote um Managed Bean para oferecer algumas ações para as telas. TypedQuery . util . produtosCache = this . @Resource private SessionContext context . com . import br . k19 . produtosCache . 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 . import javax .k19. javax . this . manager . ProdutoRepositorio . entidades . k19 . adiciona ( this . com . public void adiciona ( Produto produto ) { this . sessionbeans . produtosCache == null ) { this . class ) .com/k19treinamentos 109 .java 7 Crie um pacote chamado br.10: ProdutoRepositorio. @Stateless public class ProdutoRepositorio { @PersistenceContext private EntityManager manager . Produto . manager . faces . com . persistence . k19 . javax . this . } return this . List . } } Código Java 6. @ManagedBean public class ProdutoMB { @EJB private ProdutoRepositorio repositorio . PersistenceContext . import br . getProdutos () .com. ManagedBean . EJB . } } public List < Produto > getProdutos () { TypedQuery < Produto > query = this . private Produto produto = new Produto () . return query . private List < Produto > produtosCache . import javax . } public List < Produto > getProdutos () { if ( this . k19 . produto = new Produto () . getPreco () < ) { this . com . Produto . ejb . managedbeans . if ( produto . public void adiciona () { this . setRollbackOnly () . T RANSAÇÕES import br . import java . Produto .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 . persistence . repositorio . produto ) . persist ( produto ) .

1 Runtime Server. produto = produto . 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 . xhtml.11: ProdutoMB. 10 110 www.k19.java 110 Adicione um arquivo chamado produtos. preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 6.xhtml 9 Remova o projeto persistenciaWeb do JBoss 7. nome } " / > <h : outputLabel value = " Preço : " / > <h : inputText value = " #{ produtoMB .transitional . produtos } " var = " produto " > <h : column > <h : outputText value = " #{ produto . nome } " / > </ h : column > <h : column > <h : outputText value = " #{ produto . } public Produto getProduto () { return produto . Certifique-se que o JBoss 7.xhtml na pasta WebContent do projeto transacoesWeb. preco } " / > <h : commandButton action = " #{ produtoMB . produto .1: produtos.T RANSAÇÕES 32 33 34 35 36 37 38 39 4 41 } public void setProduto ( Produto produto ) { this . Transitional // EN " " http :// www . sun .1 Runtime Server esteja parado. Adicione o projeto transacoesWeb no glassfish. produto . Adicione o projeto transacoesWeb no Glassfish 3. w3 . dtd " > < html xmlns = " http :// www .2 e teste a aplicação acessando a url http://localhost:8 8 /transacoesWeb/produtos. Clique com o botão direito no glassfish da view Servers e escolha a opção “Add and Remove”.1. org / TR / xhtml1 / DTD / xhtml1 . com / jsf / facelets " xmlns : h = " http :// java . w3 . } } Código Java 6. com / jsf / html " xmlns : f = " http :// java . sun . org /1999/ xhtml " xmlns : ui = " http :// java . Inicie o Glassfish 3. adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Produtos </ h1 > <h : dataTable value = " #{ produtoMB .1. sun .2.com.br . 8 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 34 35 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1.

111 T RANSAÇÕES Adicione alguns produtos e observe que produtos com preço negativo não são persistidos devido ao rollback.com/k19treinamentos 111 . www.facebook.

k19.com.T RANSAÇÕES 112 112 www.br .

Na plataforma Java.facebook. a segurança é um aspecto obrigatório. para realizar o processo de autenticação. O processo de autenticação consiste na identificação dos usuários através de algum tipo de certificado (usuário e senha). Infelizmente. as configurações necessárias para criar um Realm não são padronizadas. Um Realm é uma base de dados na qual os usuários de uma ou mais aplicações estão cadastrados. Da segurança podemos extrair dois processos fundamentais: Autenticação e Autorização.1. Já o processo de autorização determina o que cada usuário autenticado pode acessar dentro da aplicação. esses dois processos são padronizados pela especificação JAAS (Java Authentication and Authorization Service). ou seja. abra a interface de administração acessando a url localhost: 4848.CAPÍTULO S EGURANÇA 7 Para muitas aplicações. Realms Em um ambiente Java EE. Veremos no exercício como criar um Realm no Glassfish.com/k19treinamentos 113 .2 executando. cada servidor de aplicação as realiza da sua própria maneira. Siga os passos abaixo: www. devemos criar um ou mais Realms. Exercícios de Fixação 1 Com o Glassfish 3.

com.k19.br .S EGURANÇA 114 114 www.

115
2

S EGURANÇA

Adicione um usuário chamado K19 dentro de um grupo chamado admin com a senha K19. Siga os passos abaixo:

www.facebook.com/k19treinamentos

115

S EGURANÇA

116

116

www.k19.com.br

117
3

S EGURANÇA

Repita o processo do exercício anterior e cadastre os seguintes usuários: Usuário keizo afk Grupo admin users Senha keizo afk

Acesse o MySQL Server através do MySQL Workbench ou através do cliente de linha de comando; crie tabelas chamadas Usuario, Grupo e Usuario_Grupo na base de dados k22_glassfish.
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

5

Adicione registros nas tabelas com o código a seguir.
INSERT INTO Usuario ( nome , senha ) VALUES ( ’ K19 ’ , md5 ( ’ K19 ’) ) ; INSERT INTO Usuario ( nome , senha ) VALUES ( ’ keizo ’ , md5 ( ’ keizo ’) ) ; INSERT INTO Usuario ( nome , senha ) VALUES ( ’ afk ’ , md5 ( ’ afk ’) ) ; INSERT INTO Grupo ( nome ) VALUES ( ’ admin ’) ; INSERT INTO Grupo ( nome ) VALUES ( ’ users ’) ; INSERT INTO Usuario_Grupo ( Usuario_nome , grupos_nome ) VALUES ( ’ K19 ’ , ’ admin ’) ; INSERT INTO Usuario_Grupo ( Usuario_nome , grupos_nome ) VALUES ( ’ keizo ’ , ’ admin ’) ; INSERT INTO Usuario_Grupo ( Usuario_nome , grupos_nome ) VALUES ( ’ afk ’ , ’ users ’) ;

1 2 3 4 5 6 7 8 9 1

Com o Glassfish 3.1.2 executando, abra a interface de administração acessando a url localhost: 4848. Siga os passos abaixo:
6

www.facebook.com/k19treinamentos

117

• Name: K19-Realm-JDBC • Class Name: com.realm.com.auth.jdbc.enterprise.S EGURANÇA 118 Importante: Na próxima tela preencha as seguintes propriedades.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.sun.br .security.

Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. clique com o botão direito do mouse sobre esse projeto e selecione a opção “Close Project”. 8 www. Veremos no exercício como configurar uma aplicação web no Glassfish para realizar o processo de autenticação. Portanto. Contudo. o processo de autenticação é realizado na camada web. 7 Crie um Dynamic Web Project no eclipse chamado segurancaWeb. siga exatamente as imagens abaixo.facebook. feche os projetos transacoesWeb. Exercícios de Fixação Para não confunfir.com/k19treinamentos 119 . Para isso. A maior parte das configurações referentes ao processo de autenticação que as aplicações web devem realizar são definidas no arquivo web.xml.119 S EGURANÇA Autenticação . vamos restringir a nossa discussão a esse tipo de aplicação.Aplicações Web Geralmente. alguns servidores de aplicação exigem configurações extras. Depois.

com.br .S EGURANÇA 120 120 www.k19.

121 S EGURANÇA www.com/k19treinamentos 121 .facebook.

1: sun-web.list > < login ... < welcome .resource .name >K19 .name > < group . xhtml </ form . Transitional // EN " " http :// www ...file .k19.collection > < auth .mapping > < security .name > < role . Acrescente no arquivo WebContent/WEB-INF/web.mapping > < role .file .login .xml Essa configuração é específica do Glassfish.name > users </ group . xhtml </ welcome .method > </ web .method > FORM </ auth .xml Adicione um arquivo chamado login.config > < security .method > < realm .name > </ security .role .name > < form .config > < form .method > POST </ http .login .xml do projeto segurancaWeb o seguinte trecho de código dentro do elemento web-app.config > < auth .xhtml na pasta WebContent do projeto segurancaWeb com seguinte conteúdo.page >/ acesso .2: web. w3 .role .S EGURANÇA 9 122 Acrescente no arquivo WebContent/WEB-INF/sun-web. org /1999/ xhtml " xmlns : ui = " http :// java .constraint > < role .role .transitional . org / TR / xhtml1 / DTD / xhtml1 .name > admin </ group . 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 .role .name > USERS </ role .Realm </ realm .method > GET </ http . 1 2 3 4 5 6 7 8 9 1 11 . dtd " > < html xmlns = " http :// www .. Código XML 7.file > </ welcome .name > </ security . < security .page > < form .name > </ auth .page > </ form ...constraint > <web .method > < http . xhtml </ form .file >/ index .pattern > /* </ url . w3 . com / jsf / facelets " 122 www.page >/ login .br .resource .mapping > < role .xml do projeto segurancaWeb o seguinte trecho de código logo após o elemento context-root.name > ADMIN </ role .name > < group .collection > <web . Código XML 7.mapping > ..resource .list > < welcome .constraint > .com.name > USERS </ role .error .login .config > </ login .name > ADMIN </ role .name > <url .error . Os grupos são utilizados pelo Glassfish e os roles pela aplicação.login . sun .constraint > </ security .negado .resource . 11 1 2 3 4 5 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1.name > resources </ web .pattern > < http .

facebook. sun . w3 . sun . sun . com / jsf / html " xmlns : f = " http :// java . org /1999/ xhtml " xmlns : ui = " http :// java . com / jsf / core " > <h : head > < title > Segurança </ title > </ h : head > <h : body > < form method = " post " action = " j_security_check " > Usuário : < input type = " text " name = " j_username " / > Senha : < input type = " password " name = " j_password " / > < input type = " submit " value = " Login " / > </ form > </ h : body > </ html > Código XHTML 7.2: acesso-negado. sun .com/k19treinamentos 123 . w3 . sun .transitional . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. com / jsf / core " > <h : head > < title > Segurança </ title > </ h : head > <h : body > < h1 > Acesso Negado </ h1 > <h : link outcome = " / login " value = " Tentar novamente " / > </ h : body > </ html > Código XHTML 7.xhtml Adicione um arquivo chamado menu.123 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 xmlns : h = " http :// java . sun . sun . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ autenticadorMB . dtd " > < html xmlns = " http :// www .xhtml S EGURANÇA 12 Adicione um arquivo chamado acesso-negado.xhtml na pasta WebContent do projeto segurancaWeb www. 13 1 2 3 4 5 6 7 8 9 1 11 12 < ui : composition xmlns = " http :// www . org /1999/ xhtml " xmlns : ui = " http :// java . com / jsf / facelets " xmlns : h = " http :// java . w3 . org / TR / xhtml1 / DTD / xhtml1 .xhtml 14 Adicione um arquivo chamado index. com / jsf / html " xmlns : f = " http :// java .xhtml na pasta WebContent do projeto segurancaWeb com seguinte conteúdo.xhtml em uma pasta chamada includes dentro de WebContent/WEB-INF no projeto segurancaWeb com seguinte conteúdo. sair } " value = " Sair " / > </ h : panelGrid > </ h : form > </ ui : composition > Código XHTML 7.3: menu. com / jsf / facelets " xmlns : h = " http :// java . com / jsf / html " xmlns : f = " http :// java . sun .1: login. Transitional // EN " " http :// www .

w3 . dtd " > < html xmlns = " http :// www .k19.com. import import import import javax . xhtml " / > </ h : body > </ html > Código XHTML 7. ExternalContext ec = fc .2. com / jsf / facelets " xmlns : h = " http :// java . session . javax .1.1 Runtime Server esteja parado.4: index. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. faces . 15 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 package br .1: AutenticadorMB. sun . bean .k19. com / jsf / html " xmlns : f = " http :// java .xhtml Crie um pacote chamado br. @ManagedBean public class AutenticadorMB { public String sair () { FacesContext fc = FacesContext . context .transitional . javax .java Remova o projeto transacoesWeb do Glassfish 3. } } Código Java 7. http . HttpSession session = ( HttpSession ) ec . com / jsf / core " > <h : head > < title > Segurança </ title > </ h : head > <h : body > < h1 > Autenticado </ h1 > < ui : include src = " / WEB . Inicie o Glassfish 3. 16 Obs: Os usuários cadastrados no K19-Realm são: Usuário K19 keizo afk 124 Grupo admin admin users Senha K19 keizo afk www. Transitional // EN " " http :// www . return " / login " . com . invalidate () .1.com. getExternalContext () . getSession ( false ) .managedbeans no projeto segurancaWeb e adicione nesse pacote um Managed Bean. HttpSession . context .INF / includes / menu . ManagedBean . ExternalContext . Adicione o projeto segurancaWeb no Glassfish 3. FacesContext . javax .S EGURANÇA 124 com seguinte conteúdo. w3 . sun . faces . servlet . Certifique-se que o JBoss 7.2. k19 .br .1. org / TR / xhtml1 / DTD / xhtml1 . faces . sun .2 e teste a aplicação acessando a url http://localhost:8 8 /segurancaWeb. managedbeans . getCurrentInstance () . org /1999/ xhtml " xmlns : ui = " http :// java .

Na pasta META-INF.config > < auth . entidades .data . com / xml / ns / persistence http: // java . com .page > < form .2 e teste a aplicação acessando a url http://localhost:8 8 /segurancaWeb. MySQL5InnoDBDialect " / > </ properties > </ persistence .k19. com / xml / ns / persistence / persistence_2_ . com / xml / ns / persistence " xmlns:xsi = " http: // www . import javax . dialect " value = " org .error . < login .. hibernate . xhtml </ form . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1.name > < form .1.negado .xml. persistence .name >K19 . show_sql " value = " true " / > < property name = " hibernate . " encoding = " UTF -8 " ? > < persistence version = " 2. persistence .xml para utilizar o JDBC Realm.. HibernatePersistence </ provider > <jta .source > < properties > < property name = " hibernate . sun . ejb . dialect .page >/ login .login .method > < realm .login . w3 . Código XML 7. auto " value = " update " / > < property name = " hibernate . xhtml </ form .. public String getNome () { www.config > < form .3: web.data .. org /2 1/ XMLSchema .com.Realm . 1 2 3 4 5 6 7 8 9 1 11 12 package br . 19 Adicione uma pasta chamada META-INF na pasta src do projeto segurancaWeb.config > </ login .unit > </ persistence > Código XML 7. sun .xml 1 2 3 4 5 6 7 8 9 1 11 12 18 Reinicie o Glassfish 3. @Entity public class Grupo { @Id private String nome .unit name = " K19 " transaction .JDBC </ realm .facebook. sun .page >/ acesso . k19 .type = " JTA " > < provider > org .com/k19treinamentos 125 .login . " xmlns = " http: // java . hbm2ddl . import javax .4: persistence.config > . xsd " > < persistence . hibernate .125 17 S EGURANÇA Altere o arquivo WebContent/WEB-INF/web.error .instance " xsi:schemaLocation = " http: // java . .source > jdbc / K19 </ jta . Id .method > FORM </ auth .login . crie o arquivo persistence.xml 20 Crie uma classe chamada Grupo em um pacote chamado br.entidades no projeto segurancaWeb.page > </ form . format_sql " value = " true " / > < property name = " hibernate . Entity .

@Stateless public class GrupoRepositorio { @PersistenceContext private EntityManager manager .com. util . @ManyToMany ( fetch = FetchType .S EGURANÇA 13 14 15 16 17 18 19 2 21 22 23 24 return nome . import br . com . import java . 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 . k19 . nome .br . entidades . util .java 126 21 Crie uma classe chamada Usuario no pacote br. List . persistence . TypedQuery .k19. ArrayList .com. import java .3: Usuario. EntityManager .java Crie uma classe chamada GrupoRepositorio em um pacote chamado br. javax .2: Grupo. javax . } } Código Java 7. entidades . persistence . Grupo . k19 . } public void setNome ( String nome ) { this . import import import import javax . EAGER ) private List < Grupo > grupos = new ArrayList < Grupo >() . sessionbeans . persistence . Id . nome = nome . util . javax . k19 . persistence . javax . javax .entidades no projeto segurancaWeb. persistence .k19. ejb . package br . persistence .com.sessionbeans no projeto segurancaWeb. Entity . FetchType . PersistenceContext .k19. List . javax . ManyToMany . com . private String senha . import java . persistence . // GETTERS AND SETTERS } Código Java 7. com . import import import import javax . } @Override public String toString () { return this . Stateless . 22 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 package br . 126 www.

com . TypedQuery . com . GrupoRepositorio . java .k19. ejb . } } Código Java 7. import import import import java . EJB . 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. import import import import javax . PersistenceContext . manager .sessionbeans no projeto segurancaWeb. java . Grupo . import br . List . java . Grupo . @Stateless public class UsuarioRepositorio { @PersistenceContext private EntityManager manager . faces . import br . BigInteger . security . persistence . Usuario . class ) . javax . persistence . bean . www. Usuario . math . com . javax . persist ( g ) . persist ( u ) . manager . entidades .facebook. NoSuchAlgorithmException .5: UsuarioRepositorio. return query . sessionbeans .k19. createQuery ( " select x from Grupo x " . ManagedBean . managedbeans . javax . createQuery ( " select x from Usuario x " . 24 1 2 3 4 5 6 7 8 9 1 11 12 13 package br .java Crie uma classe chamada UsuarioMB em um pacote chamado br. } public List < Usuario > buscaTodos () { TypedQuery < Usuario > query = this . manager . com . MessageDigest . manager . k19 . ejb . import javax .com. entidades . import java . import javax . Usuario . EntityManager . import br .4: GrupoRepositorio. getResultList () . entidades . util .java 23 Crie uma classe chamada UsuarioRepositorio no pacote br.127 19 2 21 22 23 24 25 26 27 public void adiciona ( Grupo g ) { this . k19 . sessionbeans . public void adiciona ( Usuario u ) { this . List . } S EGURANÇA public List < Grupo > buscaTodos () { TypedQuery < Grupo > query = this . util . com . security . k19 . return query . k19 . k19 .com/k19treinamentos 127 . getResultList () . com . } } Código Java 7. persistence . Stateless . k19 . ← class ) .managedbeans no projeto segurancaWeb. import br .

usuarioRepositorio . add ( g ) . grupos = this .com. String senhaCriptografada = hash . // or " SHA -1" md . getBytes () ) . } return this . nomesDosGrupos ) { Grupo g = new Grupo () . } return this . g .k19. } public List < String > getNomesDosGrupos () { return nomesDosGrupos .S EGURANÇA 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 . @ManagedBean public class UsuarioMB { @EJB private UsuarioRepositorio usuarioRepositorio . while ( senhaCriptografada . } 128 128 www. usuario = usuario . usuario . this . } public List < Grupo > getGrupos () { if ( this . usuario . update ( this . } public void setUsuario ( Usuario usuario ) { this . grupoRepositorio . public void adiciona () throws NoSuchAlgorithmException { // Associando os Grupos ao novo Usuário for ( String nomeDoGrupo : this . setSenha ( senhaCriptografada ) . getInstance ( " MD5 " ) . this . grupos . usuarios = this . private List < String > nomesDosGrupos . UsuarioRepositorio . } this . usuario ) . buscaTodos () . private List < Grupo > grupos .br . // Salvando o usuário this . usuarios . com . getSenha () . digest () ) . usuario . } // Criptografando a senha do novo Usuário MessageDigest md = MessageDigest . length () < 32) { // 4 for SHA -1 senhaCriptografada = " " + senhaCriptografada . @EJB private GrupoRepositorio grupoRepositorio . BigInteger hash = new BigInteger (1 . usuario = new Usuario () . private List < Usuario > usuarios . md . } public List < Usuario > getUsuarios () { if ( this . this . usuarios = null . } public Usuario getUsuario () { return usuario . setNome ( nomeDoGrupo ) . getGrupos () . usuarioRepositorio . sessionbeans . buscaTodos () . grupos == null ) { this . toString (16) . usuarios == null ) { this . adiciona ( this . k19 . private Usuario usuario = new Usuario () .

} } Código Java 7. com / jsf / core " > <h : head > < title > Segurança </ title > </ h : head > <h : body > < ui : include src = " / WEB . nomesDosGrupos = nomesDosGrupos .facebook. Transitional // EN " " http :// www . grupos } " var = " g " itemLabel = " #{ g . sun . adiciona } " / > </ h : form > < hr / > <h : dataTable value = " #{ usuarioMB .5: index. sun . nome } " required = " true " / > <h : outputLabel value = " Senha " / > <h : inputSecret value = " #{ usuarioMB . grupos } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 7. xhtml " / > < h1 > Novo Usuario </ h1 > <h : messages / > <h : form > <h : panelGrid columns = " 2 " > <h : outputLabel value = " Nome " / > <h : inputText value = " #{ usuarioMB . usuario . senha } " required = " true " / > <h : selectManyCheckbox value = " #{ usuarioMB . w3 . nome } " / > </ h : selectManyCheckbox > </ h : panelGrid > <h : commandButton value = " Salvar " action = " #{ usuarioMB . org / TR / xhtml1 / DTD / xhtml1 .INF / includes / menu .xhtml na pasta WebContent do projeto segurancaWeb com seguinte conteúdo.com/k19treinamentos 129 . nomesDosGrupos } " required = " true " > <f : selectItems value = " #{ usuarioMB . nome } " / > </ h : column > <h : column > <f : facet name = " header " > Grupos </ f : facet > <h : outputText value = " #{ u . usuarios } " var = " u " border = " 1 " > <h : column > <f : facet name = " header " > Nome do Usuário </ f : facet > <h : outputText value = " #{ u . 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.6: UsuarioMB.129 84 85 86 87 88 S EGURANÇA public void setNomesDosGrupos ( List < String > nomesDosGrupos ) { this . com / jsf / html " xmlns : f = " http :// java .java Adicione um arquivo chamado usuarios. usuario .transitional .xhtml www. nome } " itemValue = " #{ g . org /1999/ xhtml " xmlns : ui = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java . w3 . dtd " > < html xmlns = " http :// www .

k19. manager .S EGURANÇA 26 130 Modifique o arquivo WebContent/WEB-INF/includes/menu. } 130 www. Obs: Os usuários cadastrados no K19-Realm-JDBC são: Usuário K19 keizo afk Grupo admin admin users Senha K19 keizo afk 28 Adicione e teste novos usuários através do endereço http://localhost:8 8 /segurancaWeb/ usuarios. com / jsf / html " xmlns : f = " http :// java .6: menu.xhtml do projeto segurancaWeb. é possível declarar que um determinado método de um Session Bean só pode ser chamado por usuários administradores ou moderadores. com / jsf / facelets " xmlns : h = " http :// java . w3 . } 1 2 3 4 5 @RolesAllowed ({ " administrador " . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ autenticadorMB .xhtml 1 2 3 4 5 6 7 8 9 1 11 12 27 Reinicie o Glassfish 3. sun . sun . persist ( produto ) . < ui : composition xmlns = " http :// www . valerá as restrições definidas no método.. Por exemplo.com.br . Se aplicada ao mesmo tempo na classe e em algum método. sair } " value = " Sair " / > <h : commandLink action = " / usuarios " value = " Usuários " / > </ h : panelGrid > </ h : form > </ ui : composition > Código XHTML 7. sun . " moderador " }) public void adiciona ( Produto produto ) { this . Se aplicada na classe valerá para todos os métodos. org /1999/ xhtml " xmlns : ui = " http :// java . @RolesAllowed Restrições de acesso podem ser definidas pela anotação @RolesAllowed que pode ser aplicada na classe ou nos métodos de um Session Bean..2 e teste a aplicação acessando a url http://localhost:8 8 /segurancaWeb. 1 2 3 4 @RolesAllowed ({ " administrador " .Aplicações EJB Podemos limitar o acesso dos usuários aos métodos de um Session Bean.1.xhtml Autorização . " moderador " }) @Stateful class CarrinhoBean { .

class ...java @DenyAll O funcionamento da anotação @DenyAll é exatamente o oposto da @PermitAll. www. Podemos utilizar a anotação @DenyAll em aplicações que são implantadas em ambientes diferentes. manager . Para conseguir o mesmo efeito com a anotação @RolesAllowed. temos que definir o papel de administrador para o primeiro Session Bean através da anotação @RunAs. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 @Stateless @RunAs ( " administrador " ) class MensagemRepositorio { @PersistenceContext private EntityManager manager . que os métodos do primeiro possam ser executados por usuários moderadores e os métodos do segundo por administradores. manager . find ( Mensagem . Para que o primeiro Session Bean possa chamar o Segundo. id ) .12: CarrinhoBean.131 S EGURANÇA @PermitAll Podemos utilizar a anotação @PermitAll para permitir que qualquer tipo de usuário tenha acesso. } 1 2 3 4 5 @DenyAll @Stateful class CarrinhoBean { .java @RunAs Eventualmente. alterações seriam necessárias. Suponha. 1 2 3 4 @PermitAll public void adiciona ( Produto produto ) { this . } 1 2 3 4 5 @PermitAll @Stateful class CarrinhoBean { . teríamos que listar todos os Roles. Sendo que em determinados ambientes certas funcionalidades devem ser desabilitadas. manager ..facebook. @EJB private TopicoRepositorio topicoRepositorio . um Session Bean chama outro Session Bean. } Código Java 7. remove ( m ) . caso um Role fosse criado ou destruído. persist ( produto ) . @RolesAllowed ({ " moderador " }) public void remove ( Long id ) { Mensagem m = this .com/k19treinamentos 131 . manager .. Além disso. 1 2 3 4 @DenyAll public void adiciona ( Produto produto ) { this . this .10: CarrinhoBean. } Código Java 7. persist ( produto ) .

security . RolesAllowed . faces . import java . " USERS " }) public List < String > listaTarefas () { return this . sessionbeans . util . bean . ArrayList . getTopico () .13: MensagemRepositorio.br . tarefas .S EGURANÇA 15 16 17 18 19 2 21 22 132 Topico t = m . List . tarefas . remove ( tarefa ) .com. sessionbeans . } } Código Java 7. import java . @ManagedBean 132 www.managedbeans do projeto segurancaWeb. adicione uma classe chamada TarefasMB. } @RolesAllowed ({ " ADMIN " . tarefas .com. 30 1 2 3 4 5 6 7 8 9 1 package br . @Singleton public class TarefasBean { private List < String > tarefas = new ArrayList < String >() . import javax . import java . if ( t .com.14: TarefaBean. adicione uma classe chamada TarefasBean.k19. util . 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 . Singleton . TarefasBean .java Exercícios de Fixação 29 No pacote br. } @RolesAllowed ({ " ADMIN " }) public void remove ( String tarefa ) { this . import br . remove ( t ) . import javax . com . @RolesAllowed ({ " ADMIN " . import javax . com . managedbeans .k19. k19 . annotation . size () == 1) { this . import javax . k19 . List . com . ejb . add ( tarefa ) . topicoRepositorio . } } } Código Java 7.java No pacote br. ManagedBean .sessionbeans do projeto segurancaWeb. util . ejb . getMensagens () .k19. k19 . " USERS " }) public void adiciona ( String tarefa ) { this . EJB .

transitional .INF / includes / menu . org /1999/ xhtml " xmlns : ui = " http :// java . remove ( tarefa ) } " > remove </ h : commandLink > </ h : column > </ h : dataTable > </ h : form > </ h : body > </ html > Código XHTML 7. www.7: tarefas. org / TR / xhtml1 / DTD / xhtml1 . adiciona } " value = " Salvar " / > < h1 > Lista de Tarefas </ h1 > <h : dataTable value = " #{ tarefasMB . tarefasBean . tarefas } " var = " tarefa " > <h : column > <h : outputText value = " #{ tarefa } " / > </ h : column > <h : column > <h : commandLink action = " #{ tarefasMB . tarefasBean . } public void remove ( String tarefa ) { this . tarefa ) . listaTarefas () .com/k19treinamentos 133 . w3 .facebook. adiciona ( this . Transitional // EN " " http :// www . com / jsf / facelets " xmlns : h = " http :// java . sun . xhtml " / > < h1 > Nova Tarefa </ h1 > <h : form > <h : outputLabel value = " Tarefa : " / > <h : inputText value = " #{ tarefasMB . tarefasBean . w3 .xhtml na pasta WebContent do projeto segurancaWeb. } public List < String > getTarefas () { return this . sun .xhtml do projeto segurancaWeb.15: TarefaMB.java S EGURANÇA 31 Crie um arquivo chamado tarefas.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 . com / jsf / html " xmlns : f = " http :// java .xhtml 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 28 29 3 31 32 33 32 Modifique o arquivo WebContent/WEB-INF/includes/menu. } // GETTERS AND SETTERS } Código Java 7. remove ( tarefa ) . private String tarefa . com / jsf / core " > <h : head > < title > Segurança </ title > </ h : head > <h : body > < ui : include src = " / WEB . tarefa } " / > <h : commandButton action = " #{ tarefasMB . sun . <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. dtd " > < html xmlns = " http :// www . public void adiciona () { this .

S EGURANÇA 1 2 3 4 5 6 7 8 9 1 11 12 13 < ui : composition xmlns = " http :// www .xhtml 134 33 Observe que usuários com role USERS não conseguem remover tarefas.8: menu. org /1999/ xhtml " xmlns : ui = " http :// java . sun .br . w3 .com. sun . sair } " value = " Sair " / > <h : commandLink action = " / usuarios " value = " Usuários " / > <h : commandLink action = " / tarefas " value = " Tarefas " / > </ h : panelGrid > </ h : form > </ ui : composition > Código XHTML 7. 134 www. com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ autenticadorMB . com / jsf / html " xmlns : f = " http :// java . sun . com / jsf / facelets " xmlns : h = " http :// java .k19.

Por exemplo. na arquitetura EJB.facebook. podemos utilizar a ideia de interceptadores para conseguir executar lógicas antes ou depois da execução de um método de negócio. • O método de callback “PostActivate” é executado quando uma instância de um Stateful Session Bean muda do estado PASSIVADO para o PRONTO. podemos implementar logging ou controle de acesso com interceptadores.com/k19treinamentos 135 . www. Há um método de callback para cada uma das seguintes transições: NÃO EXISTE->PRONTO. Além dessas transições. // CHAMANDO O MÉTODO DE NEGÓCIO E PEGANDO O SEU RETORNO Object retornoDoMetodoDeNegocio = ic . ele pode ser público. • O método de callback “PreDestroy” é executado quando uma instância de um Session Bean muda do estado PRONTO para o NÃO EXISTE. Contudo. PRONTO->PASSIVADO. É comum utilizar interceptadores para tarefas que não estão diretamente relacionadas às regras de negócio implementadas nos Session Beans. podemos considerar que toda vez que um método de negócio é chamado ocorre a transição PRONTO>PRONTO. proceed () . Não há restrições em relação a visibilidade desse método. Contudo. Interceptor Methods A lógica de um interceptador é definida dentro de um método anotado com @AroundInvoke ou registrado através de XML. PASSIVADO->PRONTO e PRONTO->NÃO EXISTE. • O método de callback “PrePassivate” é executado quando uma instância de um Stateful Session Bean muda do estado PRONTO para o PASSIVADO. ou seja. Não há método de callback para essa transição especial. ele deve possuir uma assinatura compatível com o seguinte formato: 1 Object < METODO >( InvocationContext ) throws Exception Veja um exemplo concreto de método interceptador: 1 2 3 4 5 6 7 8 @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { // IDA System . • O método de callback “PostConstruct” é executado quando uma instância de um Session Bean de qualquer tipo muda do estado NÃO EXISTE para o PRONTO. padrão ou privado. protegido. lógicas a serem executadas pelo EJB Container quando uma instância de um Session Bean muda de estado. println ( " ANTES DO MÉTODO DE NEGÓCIO " ) . através de métodos de callback. out .CAPÍTULO I NTERCEPTADORES 8 Uma aplicação EJB pode definir.

Um interceptador interno atua em todos os métodos de negócio do seu respectivo Session Bean. não mais do que um método interceptador pode ser definido em uma mesma classe. // CHAMANDO O MÉTODO DE NEGÓCIO E PEGANDO O SEU RETORNO Object retornoDoMetodoDeNegocio = ic . proceed () . Cada Session Bean pode ter no máximo um interceptador interno.br . return retornoDoMetodoDeNegocio . println ( " DEPOIS DO MÉTODO DE NEGÓCIO " ) . 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 .4: LoggingInterceptor. // VOLTA System .java 136 www. return retornoDoMetodoDeNegocio .java External Interceptors Os interceptadores externos são criados quando um método interceptador é definido fora de um Session Bean em uma classe comum. return retornoDoMetodoDeNegocio . // VOLTA System . } } Código Java 8. out . println ( " ANTES DO MÉTODO DE NEGÓCIO " ) . } } Código Java 8.k19. println ( " DEPOIS DO MÉTODO DE NEGÓCIO " ) .I NTERCEPTADORES 9 1 11 12 // VOLTA System . out . proceed () . println ( " ANTES DO MÉTODO DE NEGÓCIO " ) . } 136 Internal Interceptors Um interceptador interno é criado quando um método interceptador é definido dentro de um Session Bean. println ( " DEPOIS DO MÉTODO DE NEGÓCIO " ) .com. out . // CHAMANDO O MÉTODO DE NEGÓCIO E PEGANDO O SEU RETORNO Object retornoDoMetodoDeNegocio = ic . out .3: CalculadoraBean. out . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 @Stateless class CalculadoraBean { // MÉTODOS DE NEGÓCIO // MÉTODOS DE CALLBACK // MÉTODO INTERCEPTADOR @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { // IDA System . Novamente.

SegurancaInterceptor . double b ) { return a + b .java Class-Level Interceptors Interceptadores externos também podem ser associados a Session Beans através da anotação @Interceptors.7: CalculadoraBean.5: CalculadoraBean. SegurancaInterceptor . um interceptador externo será aplicado a todos os métodos de negócio desse Session Bean.java Vários interceptadores externos podem ser associados a um método de negócio através da anotação @Interceptors. Quando associado a um Session Bean.137 I NTERCEPTADORES Method-Level Interceptors Interceptadores externos podem ser associados a métodos de negócio através da anotação @Interceptors. class }) class CalculadoraBean { public double soma ( double a . double b ) { return a + b . double b ) { return a + b .8: CalculadoraBean. 1 2 3 4 5 6 7 8 @Stateless class CalculadoraBean { @Interceptors ({ LoggingInterceptor . } } Código Java 8. class }) public double soma ( double a . } } Código Java 8. 1 2 3 4 5 6 7 8 @Stateless class CalculadoraBean { @Interceptors ({ LoggingInterceptor . double b ) { return a + b .facebook.6: CalculadoraBean.com/k19treinamentos 137 . } } Código Java 8. class . } } Código Java 8. class }) public double soma ( double a . 1 2 3 4 5 6 7 8 @Stateless @Interceptors ({ LoggingInterceptor .java www. 1 2 3 4 5 6 7 8 @Stateless @Interceptors ({ LoggingInterceptor . class }) class CalculadoraBean { public double soma ( double a .java Vários interceptadores externos podem ser associados a um Session Bean através da anotação @Interceptors. class .

SegurancaInterceptor . Por exemplo.class > </ interceptor . class . } } Código Java 8.xml.com.class > INTERCEPTOR </ interceptor .10: CalculadoraBean. 1 2 3 4 < interceptor .I NTERCEPTADORES 138 Default Interceptors Interceptadores externos também podem ser associados a métodos de negócio através de configurações adicionadas no arquivo de configuração do EJB.class > interceptadores .9: CalculadoraBean.class > </ interceptor . double b ) { return a + b .binding Excluindo Interceptadores Podemos excluir os Default Interceptors e os Class-Level Interceptors através das anotações @ExcludeDefaultInterceptors e @ExcludeClassInterceptors respectivamente.binding > Ou podemos aplicar a apenas um Session Bean. class }) class CalculadoraBean { @ExcludeClassInterceptors public double soma ( double a . } } Código Java 8. A anotação @ExcludeDefaultInterceptors pode ser aplicada em um método de negócio ou no Session Bean.name > sessionbeans .name > < interceptor .binding > <ejb . 1 2 3 4 < interceptor .name >* </ ejb .binding > <ejb . double b ) { return a + b . Esse arquivo deve ser colocado em uma pasta chamada META-INF dentro do módulo EJB da aplicação. 1 2 3 4 5 6 7 8 @Stateless @ExcludeDefaultInterceptors class CalculadoraBean { public double soma ( double a . 1 2 3 4 5 6 7 8 9 @Stateless @Interceptors ({ LoggingInterceptor . suponha que o interceptador externo definido pela classe LoggingInterceptor tenha que ser aplicado em todos os métodos de negócio de todos os Session Beans.java Invocation Context 138 www.name > < interceptor .k19.br . LoggingInterceptor </ interceptor . o ejb-jar. CalculadoraBean </ ejb .java A anotação @ExcludeClassInterceptors pode ser aplicada em um método de negócio.

Map < String . 2 www. Exercícios de Fixação Para não confunfir.xml. 1 2 3 4 5 6 7 8 public interface InvocationContext { public Object getTarget () . eles serão executados na ordem em que foram declarados na anotação @Interceptors.java Ordem dos Interceptadores A ordem na qual os interceptadores são executados pode afetar o funcionamento da aplicação. public Method getMethod () .11: InvocationContext. clique com o botão direito do mouse sobre esse projeto e selecione a opção “Close Project”. Depois.com/k19treinamentos 139 . Quando dois ou mais Method-Level Interceptors estão associados a um método de negócio. Internal Interceptors Quando dois ou mais Default Interceptors estão associados a um método de negócio. Para isso. public Object [] getParameters () .139 I NTERCEPTADORES Um método interceptador recebe um Invocation Context como parâmetro. Default Interceptors 2. feche os projetos segurancaWeb. Object > getContextData () . Quando dois ou mais Class-Level Interceptors estão associados a um método de negócio. quais parâmetros foram passados e até mesmo trocar os parâmetros antes de chegar no método de negócio. A especificação dos interceptadores define a seguinte ordem: 1. public Object proceed () throws Exception . } Código Java 8. public void setParameters ( Object []) . eles serão executados na ordem em que foram declarados na anotação @Interceptors. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. eles serão executados na ordem em que foram definidos no ejb-jar. util . Veja os métodos disponíveis nessa interface. os métodos interceptadores podem acessar a instância do Session Bean que será utilizada para atender a chamada. siga exatamente as imagens abaixo.facebook. descobrir qual método de negócio será executado. 1 Crie um Dynamic Web Project no eclipse chamado interceptadoresWeb. public java . Através dos Invocation Context. Class-Level Interceptors 3. Method-Level Interceptors 4.

I NTERCEPTADORES 140 140 www.k19.br .com.

141 I NTERCEPTADORES www.facebook.com/k19treinamentos 141 .

show_sql " value = " true " / > < property name = " hibernate . dialect " value = " org . ejb . import javax . Entity . " encoding = " UTF -8 " ? > < persistence version = " 2. HibernatePersistence </ provider > <jta . MySQL5InnoDBDialect " / > </ properties > </ persistence . persistence . com . import java .entidades no projeto interceptadoresWeb e adicione nesse pacote um Entity Bean para modelar mensagens. Id .3: persistence.sessionbeans no projeto interceptadoresWeb e adicione nesse pacote um SLSB para funcionar como repositório de mensagens 5 1 2 3 4 5 6 7 8 9 1 package br . hbm2ddl .type = " JTA " > < provider > org . javax . javax .com. EntityManager .xml na pasta META-INF dentro do src do projeto interceptadoresWeb. import import import import javax . sun .unit > </ persistence > Código XHTML 8. k19 .instance " xsi : schemaLocation = " http :// java .data . sun . entidades . GeneratedValue . k19 . w3 . com . persistence . " xmlns = " http :// java .source > jdbc / K19 </ jta . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 package br . adicionando o arquivo persistence. sun . hibernate . xsd " > < persistence .com.data . auto " value = " update " / > < property name = " hibernate . persistence . com . import javax . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1.k19. format_sql " value = " true " / > < property name = " hibernate . k19 .I NTERCEPTADORES 3 142 Configure a aplicação interceptadoresWeb para utilizar o data source jdbc/K19 criado no capítulo 5. 142 www. List . persistence .com. @Entity public class Mensagem { @Id @GeneratedValue private Long id . Stateless . util . hibernate .unit name = " K19 " transaction .source > < properties > < property name = " hibernate . com / xml / ns / persistence http :// java . PersistenceContext .12: Mensagem. Mensagem . private String texto . dialect . com / xml / ns / persistence " xmlns : xsi = " http :// www . persistence . sessionbeans .java Crie um pacote chamado br. com / xml / ns / persistence / persistence_2_ .k19. ejb . javax . // GETTERS AND SETTERS } Código Java 8.xml 4 Crie um pacote chamado br. org /2 1/ XMLSchema . entidades . persistence . import javax .k19. TypedQuery . import br .br .

public void adiciona ( Mensagem mensagem ) { this . com . repositorio . k19 . this . getResultList () . } } Código Java 8. Mensagem . import javax . sessionbeans . import java . Mensagem . import br .managedbeans no projeto interceptadoresWeb e adicione nesse pacote um Managed Bean para oferecer algumas ações para as telas. return query . this . k19 . private List < Mensagem > mensagensCache .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 . } } Código Java 8.13: MensagemRepositorio. import br . mensagensCache = this . import javax . managedbeans . private Mensagem mensagem = new Mensagem () . } public void setMensagem ( Mensagem mensagem ) { this . repositorio . manager . MensagemRepositorio .java Crie um pacote chamado br. com . public void adiciona () { this .com. ejb . 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 . } public Mensagem getMensagem () { return mensagem . faces . mensagem = new Mensagem () . com . } public List < Mensagem > getMensagens () { TypedQuery < Mensagem > query = this . mensagensCache = null . List . mensagensCache .java www. getMensagens () . util . } public List < Mensagem > getMensagens () { if ( this . mensagem ) .facebook. adiciona ( this . persist ( mensagem ) . k19 . manager .com/k19treinamentos 143 . ManagedBean . mensagem = mensagem .14: MensagemMB. createQuery ( " select x from Mensagem x " . class ) . EJB . entidades .k19. bean . mensagensCache == null ) { this . } return this . @ManagedBean public class MensagemMB { @EJB private MensagemRepositorio repositorio .

sun . sun .xhtml com o seguinte conteúdo. com . w3 . dtd " > < html xmlns = " http :// www . interceptadores .java 9 Adicione na pasta WEB-INF do projeto interceptadoresWeb o arquivo ejb-jar. w3 . getMethod () + " FINALIZADO " ) . texto } " / > <h : commandButton action = " #{ mensagemMB . System .br 144 .xhtml Implemente um interceptador externo para realizar o logging da aplicação. id } " / > </ h : column > <h : column > <h : outputText value = " #{ mensagem . Object retornoDoMetodoDeNegocio = ic . Crie um pacote chamado br. return retornoDoMetodoDeNegocio . Transitional // EN " " http :// www . texto } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 8. adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Mensagens </ h1 > <h : dataTable value = " #{ mensagemMB . public class LoggingInterceptor { @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { System . println ( " CHAMANDO O MÉTODO : " + ic . k19 .interceptadores no projeto interceptadoresWeb e adicione nesse pacote a seguinte classe.15: LoggingInterceptor. sun .I NTERCEPTADORES 7 144 Crie uma tela para cadastrar mensagens. mensagens } " var = " mensagem " > <h : column > <h : outputText value = " #{ mensagem .xml com o sewww. proceed () . interceptor . } } Código Java 8. import javax .4: mensagens. getMethod () ) . out . interceptor . com / jsf / html " xmlns : f = " http :// java . println ( " MÉTODO " + ic .com. 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 . InvocationContext .com. out . 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. org / TR / xhtml1 / DTD / xhtml1 .k19.k19. Adicione na pasta WebContent do projeto interceptadoresWeb um arquivo chamado mensagens. org /1999/ xhtml " xmlns : ui = " http :// java . 8 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 package br . mensagem . AroundInvoke . com / jsf / facelets " xmlns : h = " http :// java . import javax .transitional .

class > </ interceptor . replaceAll ( palavraProibida . this . sun .name >* </ ejb . this .k19. Adicione no pacote br. interceptadores . } @AroundInvoke public Object interceptador ( InvocationContext ic ) throws Exception { Object [] parameters = ic .name > < interceptor . } return ic . palavrasProibidas ) { String textoOriginal = mensagem . " ! CENSURADO ! " ) ← . org /2 1/ XMLSchema .1. mensagem . k19 . com .xml 10 Remova o projeto segurancaWeb do Glassfish 3. interceptadores .5: ejb-jar.1 Runtime Server esteja parado.1.1. w3 . 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 .descriptor > < interceptor .2. k19 .facebook.jar_3_1 . xsd " > < interceptors > < interceptor > < interceptor .jar > Código XHTML 8. Mensagem mensagem = ( Mensagem ) parameters [ ]. Implemente um interceptador externo para eliminar palavras proibidas das mensagens adicionas o logging da aplicação. Certifique-se que o JBoss 7. String textoCensurado = textoOriginal .com.145 I NTERCEPTADORES guinte conteúdo. add ( " coca . com . palavrasProibidas .2. interceptadores .class > br .2 e teste a aplicação acessando a url http://localhost:8 8 /interceptadoresWeb/mensagens.interceptadores do projeto interceptadoresWeb a seguinte classe.binding > </ assembly . com . getParameters () .1 " xmlns = " http :// java . k19 .com/k19treinamentos 145 . palavrasProibidas . } } www. public class CensuraInterceptor { private List < String > palavrasProibidas = new ArrayList < String >() . getTexto () . com / xml / ns / javaee http :// java . 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. add ( " fiat " ) .binding > <ejb .class > br .class > </ interceptor > </ interceptors > < assembly .cola " ) . sun .1. Verifique o log do Glassfish 3. palavrasProibidas .instance " xsi : schemaLocation = " http :// java . Inicie o Glassfish 3. com / xml / ns / ← javaee / ejb . " encoding = " UTF -8 " ? > <ejb . sun .descriptor > </ ejb . add ( " sony " ) .2 para observar as mensagens do interceptador. for ( String palavraProibida : this . com / xml / ns / javaee " xmlns : xsi = " http :// www . proceed () . public CensuraInterceptor () { this . setTexto ( textoCensurado ) . LoggingInterceptor </ interceptor .jar version = " 3. Adicione o projeto interceptadoresWeb no Glassfish 3. LoggingInterceptor </ interceptor .xhtml.

@Interceptors ({ CensuraInterceptor . } .17: CensuraInterceptor.java Associe o interceptador de censura ao método de adicionar mensagens do session bean MensagemRepositorio. 12 1 2 3 4 5 6 . Não esqueça de adicionar o importe da anotação import javax.xhtml.br .com. class }) public void adiciona ( Mensagem mensagem ) { this ..java 13 Adicione mensagens com palavras proibidas através da url http://localhost:8 8 /interceptadoresWeb/ mensagens. 146 www.k19.. Código Java 8.interceptor. persist ( mensagem ) .16: CensuraInterceptor.Interceptors...I NTERCEPTADORES 146 Código Java 8. manager .

3 * 6 * 1 .java S CHEDULING 9 Algumas aplicações possuem a necessidade de agendar tarefas para serem executadas periodicamente ou uma única vez após um determinado tempo.com/k19treinamentos 147 . * 6 * 1 . esse cálculo deve ser realizado uma vez por mês. Também. . Essa funcionalidade deve ser adicionada em versões futuras da especificação Enterprise Java Beans. createTimer (3 Podemos obter o TimerService por injeção através da anotação @Resource. Por exemplo. As entregas só são realizadas após a confirmação dos pagamentos. 1 timerService .CAPÍTULO * 6 * 1 . Código Java 9. " info " ) . podemos criar um alarme periódico que “dispara” a cada 30 minutos através do TimerService utilizando a sobrecarga do método createTimer(). suponha que seja necessário executar uma tarefa uma única vez depois de 30 minutos. Quando um cliente realiza um pedido. suponha uma aplicação que calcula o salário dos funcionários de uma empresa de acordo com as horas registradas. Métodos de Timeout www. Outro exemplo.. Possivelmente. o sistema da empresa deve esperar alguns dias para verificar se o pagamento correspondente foi realizado para que a entrega possa ser liberada. Timers Para agendar tarefas.. " info " ) . suponha que uma empresa vende seus produtos através da internet.3: FolhaDePagamentoBean. createTimer (3 O primeiro parâmentro do método createTimer() é quantidade de tempo que ele deve esperar para “disparar” e o segundo é uma informação que podemos associar ao timer. Por exemplo. 1 2 3 4 5 6 7 8 @Stateless class FolhaDePagamentoBean { @Resource private TimerService timerService .facebook. } Os alarmes não podem ser criados para Stateful Session Beans. 1 timerService . podemos criar alarmes (timers) através do TimerService.

-1] quantidade de dias para o término do mês. . Nov.com. . timerService . .java * 6 * 1 . . . . getInfo () . 2nd. Aug. Tue. 59] [0 . Last ] [Sun. Sep. . public void registraPedido ( Pedido pedido ) { this . Para definir um método de timeout devemos utilizar a anotação @Timeout. . Timers Automáticos Na versão 3. [1st. Thu. Oct. createTimer (5 * 24 * 6 } @Timeout public void verificaPagamento ( Timer timer ) { Pedido pedido = ( Pedido ) timer . 59] [0 . . Fri. // verifica o pagamento do pedido } } Código Java 9. Fri. May. Jun. 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 @Stateless class PedidoBean { @Resource private TimerService timerService . Mon. 5th. Mon. . Sat] [1 . Thu. . 1 2 3 4 5 6 7 8 @Stateless class FolhaDePagamentoBean { @Schedule ( dayOfMonth = " 1 " ) public void calculaSalarios () { // implementacao } } Código Java 9. 148 www. Sat] ano com 4 dígitos month dayOfWeek year Podemos utilizar lista de valores nos atributo da anotação @Schedule. 3rd.S CHEDULING 148 Quando um alarme (timer) “dispara”.4: PedidoBean. pedido ) . Mar. Feb. os alarmes podem ser criados e automaticamente associados a métodos de timeout através da anotação @Schedule. 31] [-7 . . Dec ] [0 . Tue. . . Jul.java Os atributos da anotação @Schedule são: Atributo second minute hour dayOfMonth Valores [0 . o EJB Container executa um método de timeout no Bean que criou o alarme. 7] [Sun. 12] [Jan. 4th.br .5: FolhaDePagamentoBean. 23] [1 .1 da especificação Enterprise Java Beans.k19. Wed. Apr. Wed.

Para isso. 3 . minute = " * " .149 1 @Schedule ( minute = " . 45") @Schedule ( second = " */15 " ) 1 2 // equivale a @Schedule ( second ="3 . 5 . 45 " ) S CHEDULING Também podemos utilizar intervalos de valores. 15 . 55") @Schedule ( second = " 3 /5 " ) Exercícios de Fixação Para não confunfir. 4 . 35 . Depois. todos os valores possíveis são associados a um atributo da anotação @Schedule. minute e hour. feche os projetos interceptadoresWeb. 2 www. 45 . 3 . 1 Crie um Dynamic Web Project no eclipse chamado schedulingWeb. 1 2 // equivale a @Schedule ( second =" . 1 @Schedule ( minute = " -1 " ) Utilizando o wildcard *.facebook. hour = " * " ) Podemos aplicar expressões aos atributos second. siga exatamente as imagens abaixo. clique com o botão direito do mouse sobre esse projeto e selecione a opção “Close Project”.com/k19treinamentos 149 . 15 . Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”. 1 @Schedule ( second = " * " .

com.S CHEDULING 150 150 www.br .k19.

com/k19treinamentos 151 .151 S CHEDULING www.facebook.

k19 . com / xml / ns / persistence http: // java .data . Stateless . javax . List .k19. adicionando o arquivo persistence. import javax . dialect " value = " org . javax . com . TypedQuery .unit > </ persistence > Código XML 9. sessionbeans . k19 . util . " encoding = " UTF -8 " ? > < persistence version = " 2.type = " JTA " > < provider > org .com.instance " xsi:schemaLocation = " http: // java . entidades .unit name = " K19 " transaction . hbm2ddl .S CHEDULING 3 152 Configure a aplicação schedulingWeb para utilizar o data source jdbc/K19 criado no capítulo 5.sessionbeans no projeto schedulingWeb e adicione nesse pacote um SLSB para funcionar como repositório de produtos. // GETTERS AND SETTERS } Código Java 9.com.source > jdbc / K19 </ jta . private double preco . 5 1 2 3 4 5 6 7 8 package br . Id . EntityManager . sun .k19.1: persistence.xml na pasta META-INF dentro do src do projeto schedulingWeb. ejb . import java .k19. com / xml / ns / persistence " xmlns:xsi = " http: // www . persistence . MySQL5InnoDBDialect " / > </ properties > </ persistence . HibernatePersistence </ provider > <jta . show_sql " value = " true " / > < property name = " hibernate .source > < properties > < property name = " hibernate .data . sun . persistence . 152 www. PersistenceContext .xml 4 Crie um pacote chamado br. " xmlns = " http: // java . @Entity public class Produto { @Id @GeneratedValue private Long id . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 package br . private String nome . org /2 1/ XMLSchema . com / xml / ns / persistence / persistence_2_ .com. hibernate . 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. dialect . Entity .br . w3 . GeneratedValue . persistence .entidades no projeto schedulingWeb e adicione nesse pacote um Entity Bean para modelar produtos. persistence . persistence . import javax . hibernate . ejb . persistence .java Crie um pacote chamado br. format_sql " value = " true " / > < property name = " hibernate . auto " value = " update " / > < property name = " hibernate . import javax . javax . com . import import import import javax . sun .11: Produto. xsd " > < persistence .

faces . persist ( produto ) . k19 . import javax . } public List < Produto > getProdutos () { if ( this . getResultList () . return query . entidades . List . produto = produto . manager . k19 . import javax . ManagedBean . produtosCache . repositorio . this . com . @Stateless public class ProdutoRepositorio { @PersistenceContext private EntityManager manager . produto = new Produto () . class ) . ProdutoRepositorio . @ManagedBean public class ProdutoMB { @EJB private ProdutoRepositorio repositorio . entidades . EJB . repositorio . } public void setProduto ( Produto produto ) { this .com. import br . produtosCache = this . produto ) . ejb . com . import br . produtosCache == null ) { this . k19 . com . produtosCache = null . Produto . private Produto produto = new Produto () . } public List < Produto > getProdutos () { TypedQuery < Produto > query = this . Produto . public void adiciona () { this . } } www.k19. private List < Produto > produtosCache .12: ProdutoRepositorio.java Crie um pacote chamado br. } } Código Java 9.managedbeans no projeto schedulingWeb e adicione nesse pacote um Managed Bean para oferecer algumas ações para as telas. com . this . public void adiciona ( Produto produto ) { this . managedbeans . } public Produto getProduto () { return produto . adiciona ( this . k19 . createQuery ( " select x from Produto x " . import java . manager . getProdutos () . bean .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/k19treinamentos 153 . 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 . util .facebook. } return this . Produto . sessionbeans .

org / TR / xhtml1 / DTD / xhtml1 . List .com. Implemente essa lógica através dos recursos de scheduling. import javax . Adicione o projeto schedulingWeb no Glassfish 3. produto .xhtml. Certifique-se que o JBoss 7.xhtml Remova o projeto interceptadoresWeb do Glassfish 3.2 e teste a aplicação acessando a url http://localhost:8 8 /schedulingWeb/produtos.1.xhtml com o seguinte conteúdo. ejb . produto .1. k19 . Adicione na pasta WebContent do projeto schedulingWeb um arquivo chamado produtos. org /1999/ xhtml " xmlns : ui = " http :// java .k19.com.13: ProdutoMB. Transitional // EN " " http :// www .k19. import java .2. com / jsf / facelets " xmlns : h = " http :// java . adiciona } " value = " Salvar " / > </ h : form > < h1 > Lista de Produtos </ h1 > <h : dataTable value = " #{ produtoMB . preco } " / > <h : commandButton action = " #{ produtoMB .transitional . Adicione a seguinte classe no pacote br. com / jsf / html " xmlns : f = " http :// java . EJB . produtos } " var = " produto " > <h : column > <h : outputText value = " #{ produto .S CHEDULING 154 Código Java 9.1: produtos. sun . 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. preco } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 9. w3 . com . ejb . 9 1 2 3 4 5 6 7 package br .br . import javax . w3 . import java . util .java Crie uma tela para cadastrar produtos. sun . 8 A cada minuto um produto cadastrado deve ser escolhido e colocado em destaque. util . 154 www. nome } " / > <h : outputLabel value = " Preço : " / > <h : inputText value = " #{ produtoMB . sun . Random . sessionbeans . 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 . Schedule . dtd " > < html xmlns = " http :// www .2.1.1 Runtime Server esteja parado.sessionbeans do projeto schedulingWeb. nome } " / > </ h : column > <h : column > <h : outputText value = " #{ produto . Inicie o Glassfish 3.

.. @Schedule ( second = " */5 " .java 1 2 3 4 11 Adicione na classe ProdutoMB do projeto schedulingWeb o seguinte método.. List < Produto > produtos = this . minute = " * " . produtoDestaque . 1 2 3 4 5 6 7 8 www.. . produtoDestaque = produtoDestaque . @EJB private ProdutoDestaqueBean produtoDestaqueBean . produtoDestaque ... hour = " * " ) public void trocaProdutoDestaque () { Random gerador = new Random () . this . size () ) . produtoDestaque = produtos .. Singleton . getProdutos () . @Singleton public class ProdutoDestaqueBean { @EJB private ProdutoRepositorio repositorio .. Código Java 9. public Produto getProdutoDestaque () { return this .. repositorio . import br . ejb . } public void setProdutoDestaque ( Produto produtoDestaque ) { this . get ( i ) . } .15: ProdutoMB. < h1 > Produto Destaque </ h1 > <h : outputLabel value = " Nome : " / > <h : outputText value = " #{ produtoMB .java S CHEDULING 10 Adicione na classe ProdutoMB do projeto schedulingWeb o seguinte atributo..com/k19treinamentos 155 .xhtml do projeto schedulingWeb o produto em destaque.facebook. Código Java 9. . Produto .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 . getProdutoDestaque () .16: ProdutoMB. preco } " / > . private Produto produtoDestaque ... k19 . produtoDestaqueBean . } public Produto getProdutoDestaque () { return produtoDestaque .14: ProdutoDestaqueBean. } } Código Java 9.. nextInt ( produtos . int i = gerador . entidades . . nome } " / > <h : outputLabel value = " Preço : " / > <h : outputText value = " #{ produtoMB . com .java 1 2 3 4 5 12 Acrescente na tela produtos.

xhtml Acesse periodicamente a url http://localhost:8 8 /schedulingWeb/produtos.k19.S CHEDULING 156 Código XHTML 9.com. 13 156 www.xhtml para verificar que o produto em destaque muda de tempos em tempos.br .2: produtos.

Na verdade. Persistence Units. Contudo essa especificação permite que outras especificações estendam a idéia original de Managed Beans. podemos destacar o mecanismo de Injeção de Dependência e o gerenciamento do ciclo de vida dos objetos através de contextos. os Managed Beans são objetos gerenciados pelo container Java EE.1 da especificação CDI são definidas essas restrições. Na seção 3.CDI 10 Aplicações corporativas costumam utilizar tanto o container WEB para a camada de apresentação quanto o container EJB para a camada de negócio.CAPÍTULO C ONTEXTS AND D EPENDENCY I NJECTION . os Managed Beans são definidos por classes que devem respeitar certas restrições. um Managed Bean do JSF é um caso particular de um Managed Bean do Java EE.1. Remote EJBs e Web Services) Managed Beans Na arquitetura Java EE. 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. Não devemos confundir o conceito de Managed Beans do Java EE com o conceito de Managed Bean do JSF. Dos recursos existentes na arquitetura CDI. De acordo com a especificação CDI.facebook. Persistence Contexts. A definição básica do conceito de Managed Beans está documentada na especificação Java EE 6 Managed Beans. A integração entre o container WEB e o container EJB pode ser mais facilmente realizada através dos recursos definidos pela especificação Contexts and Dependency Injection .com/k19treinamentos 157 .CDI. O container deve oferecer um pequeno conjunto de serviços fundamentais aos Managed Beans. A especificação CDI estende a definição de Managed Beans Na arquitetura CDI. www.

Producer Methods and Fields Os Producer Methods são apenas métodos que produzem objetos que serão administrados pelo container CDI e injetados em outros objetos. Somente objetos com um EL Name podem ser acessados por páginas JSP ou JSF. Os Producer Fields devem ser anotados com @Produces. os seguintes tipos de objetos podem possuir um EL Name: • Managed Beans 158 www. páginas JSP ou JSF podem acessar objetos através de EL. 1 2 @Produces public List < Produto > produtos . Os Producer Methods devem ser anotados com @Produces. EL Names Na arquitetura CDI.k19.CDI 158 As classes que se encaixam nessas restrições atuam como fonte de objetos que serão administrados pelo container CDI e poderão ser injetados em outros objetos. A princípio. 1 2 3 4 @Produces public List < Produto > listaProdutos () { // implementacao } Atributos também podem ser utilizados como fonte de objetos para o container Java EE.C ONTEXTS AND D EPENDENCY I NJECTION .com.br .

java 1 2 3 4 5 @Named @Stateless // Session Bean .EL Name : produtos public List < Produto > getProdutos () { // implementacao } 1 2 3 @Named @Produces // Producer Field . Utilizando essa anotação. 1 <? xml version = " 1.EL Name : produtos public List < Produto > produtos .java beans.xml Para habilitar os recursos do CDI para os objetos de uma aplicação.3: GeradorDeApostas. É possível alterar o padrão definindo EL Names diretamente na anotação @Named.com/k19treinamentos 159 . automaticamente.facebook. é necessário adicionar um arquivo chamado beans.java 1 2 3 4 5 6 7 8 9 1 11 @Named @Produces // Producer Method .CDI • Session Beans • Objetos criados por Producer Methods • Objetos disponibilizados por Producer Fields Devemos aplicar a anotação @Named aos objetos que devem possuir um EL Name.xml na pasta META-INF no classpath.EL Name : listaProdutos public List < Produto > listaProdutos () { // implementacao } @Named @Produces // Producer Method .EL Name : geradorDeApostas public class GeradorDeApostas { // implementacao } Código Java 10.4: GeradorDeApostas.7: GeradorDeApostas.159 C ONTEXTS AND D EPENDENCY I NJECTION . 1 2 3 4 @Named ( " gerador " ) public class GeradorDeApostas { // implementacao } Código Java 10. os objetos receberão um EL Name que é determinado de acordo com o tipo de objeto.EL Name : geradorDeApostas public class GeradorDeApostas { // implementacao } Código Java 10. " encoding = " UTF -8 " ? > www. 1 2 3 4 @Named // Managed Bean .

org /2 1/ XMLSchema .k19. com / xml / ns / javaee http: // java . feche os projetos schedulingWeb. Depois. sun . 2 160 www.br .instance " xsi:schemaLocation = " http: // java . sun .xml Exercícios de Fixação Para não confunfir.C ONTEXTS AND D EPENDENCY I NJECTION . Para isso. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”.com. com / xml / ns / javaee / beans_1_ . com / xml / ns / javaee " xmlns:xsi = " http: // www .CDI 2 3 4 5 6 7 < beans xmlns = " http: // java . xsd " > </ beans > 160 Código XML 10. sun . w3 .1: beans. clique com o botão direito do mouse sobre esse projeto e selecione a opção “Close Project”. 1 Crie um Dynamic Web Project no eclipse chamado cdiWeb. siga exatamente as imagens abaixo.

CDI www.161 C ONTEXTS AND D EPENDENCY I NJECTION .facebook.com/k19treinamentos 161 .

com / xml / ns / javaee " xmlns : xsi = " http :// www .k19. w3 . sessionbeans . sun . Named . import javax . sun . import javax . com .instance " xsi : schemaLocation = " http :// java .xml 4 Crie um pacote chamado br. com / xml / ns / javaee http :// java . ejb .com. " encoding = " UTF -8 " ? > < beans xmlns = " http :// java .sessionbeans no projeto cdiWeb e adicione nesse pacote um SLSB para funcionar como lançador de moeda. k19 . inject . public void lanca () { 162 www.1: beans. Stateless .com.C ONTEXTS AND D EPENDENCY I NJECTION .k19.xml na pasta WebContent/WEBINF do projeto cdiWeb 1 2 3 4 5 6 7 <? xml version = " 1. @Named @Stateless public class LancadorDeMoedaBean { private String resultado . org /2 1/ XMLSchema .CDI 162 3 Habilite os recursos do CDI adicionando um arquivo chamado beans. xsd " > </ beans > Código XHTML 10. 1 2 3 4 5 6 7 8 9 1 11 12 package br . sun . com / xml / ns / javaee / beans_1_ .br .

1. ArrayList . lanca } " value = " Jogar " / > </ h : form > < h2 > Resultado : <h : outputText value = " #{ lancadorDeMoedaBean .managedbeans no projeto cdiWeb e adicione nesse pacote uma classe para gerar números aleatórios.2: moeda.1. } else { this . util .xhtml.163 13 14 15 16 17 18 19 2 21 22 23 24 25 26 27 if ( Math .transitional . org / TR / xhtml1 / DTD / xhtml1 . managedbeans .xhtml Remova o projeto schedulingWeb do Glassfish 3. util . sun . Inicie o Glassfish 3. com .2 e teste a aplicação acessando a url http://localhost:8 8 /cdiWeb/moeda. Certifique-se que o JBoss 7. 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. k19 . enterprise .k19. sun .1. Produces . resultado = resultado . random () < . import javax . import java . dtd " > < html xmlns = " http :// www . } } public void setResultado ( String resultado ) { this .com.java 5 Crie uma tela para utilizar o lançador de moedas. com / jsf / html " xmlns : f = " http :// java .com/k19treinamentos 163 . inject . Transitional // EN " " http :// www . 6 Crie um pacote chamado br.facebook. public class GeradorDeNumeros { www. Named . resultado = " COROA " .2. import javax . inject . sun .5) { this . com / jsf / core " > <h : head > < title > Moeda </ title > </ h : head > <h : body > < h1 > Moeda </ h1 > <h : form > <h : commandButton action = " #{ lancadorDeMoedaBean . com / jsf / facelets " xmlns : h = " http :// java . w3 .CDI Código Java 10. resultado } " / > </ h2 > </ h : body > </ html > Código XHTML 10.2. } } C ONTEXTS AND D EPENDENCY I NJECTION . } public String getResultado () { return resultado . import java . w3 .8: LancadorDeMoedaBean. Adicione na pasta WebContent do projeto cdiWeb um arquivo chamado moeda.1 Runtime Server esteja parado. resultado = " CARA " . List . org /1999/ xhtml " xmlns : ui = " http :// java . Adicione o projeto cdiWeb no Glassfish 3. 7 1 2 3 4 5 6 7 8 9 1 package br .xhtml com o seguinte conteúdo.

com / jsf / core " > <h : head > < title > Números </ title > </ h : head > <h : body > < h1 > Números </ h1 > <h : dataTable value = " #{ numeros } " var = " numero " > <h : column > <h : outputText value = " #{ numero } " / > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML 10. w3 . para cada requisição HTTP um novo Request Context é criado pelo container CDI e destruído no final do processamento da mesma requisição. um contexto é uma coleção de objetos relacionados logicamente que devem existir durante um período de tempo específico. Transitional // EN " " http :// www . org / TR / xhtml1 / DTD / xhtml1 . random () ) . w3 . A especificação CDI define quatro contextos padrões. dtd " > < html xmlns = " http :// www . Request Context: Quando se trata de aplicações Java WEB.9: GeradorDeNumeros.java 164 Crie uma tela para utilizar o gerador de números.xhtml. Conceitualmente. sun . com / jsf / html " xmlns : f = " http :// java . } } Código Java 10. sun . com / jsf / facelets " xmlns : h = " http :// java .k19. 164 www. i < 5.xhtml 9 Acesse a url http://localhost:8 8 /cdiWeb/numeros.br . sun .transitional . add ( Math .3: numeros.xhtml com o seguinte conteúdo. Adicione na pasta WebContent do projeto cdiWeb um arquivo chamado numeros.CDI 11 12 13 14 15 16 17 18 19 2 @Named @Produces public List < Double > getNumeros () { List < Double > numeros = new ArrayList < Double >() . Escopos e Contextos Os objetos administrados pelo container CDI são armazenados em contextos. i ++) { numeros . org /1999/ xhtml " xmlns : ui = " http :// java . for ( int i = . } return numeros .C ONTEXTS AND D EPENDENCY I NJECTION . Múltiplos Request Contexts podem existir simultaneamente.com. 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.

O escopo de um objeto define em qual contexto ele será armazenado quando criado pelo container CDI.java 1 2 3 4 5 @Produces @SessionScoped public List < Produto > listaProdutos () { // implementacao } Injection Points Quando um objeto é criado pelo container CDI. Session. www. Application e Conversation são armazenados no Request Context.facebook. Por padrão. o container CDI também destrói o Session Context correspondente.165 C ONTEXTS AND D EPENDENCY I NJECTION .10: GeradorDeApostas. Conversation Context: Há dois tipos de Coversation Context: transient e long-running. Múltiplos Application Contexts não podem existir simultaneamente. todas as dependências são injetados pelo container nesse objeto. o container CDI cria um Session Context associado a essa HTTP Session. Se alguma dependência não estiver criada o container se encarrega de criá-la antes. A especificação CDI define cinco escopos padrões: Request. O objeto dependente é armazenado indiretamente em algum contexto de acordo com o escopo do objeto a qual ele pertence. Múltiplos Session Contexts podem existir simultaneamente. Conversation e Dependent. @ApplicationScoped. As anotações: @RequestScoped. Um objeto com escopo Dependent pertence a outro objeto.com/k19treinamentos 165 .begin() e destruído quando o método Conversation. Application Context e Conversation Context respectivamente. 1 2 3 4 @RequestScoped public class GeradorDeApostas { // implementacao } Código Java 10. Basicamente. @ConversationScoped e @Dependent são utilizadas para definir o escopo dos objetos. Application. Objetos com escopo Request. Application Context: O container CDI cria um Application Context quando a aplicação é inicializada e o destrói quando a aplicação é finalizada.CDI Session Context: Um Session Context está sempre associado a uma HTTP Session. Session. um Conversartion do tipo long-running é criado na chamada do método Conversation. @SessionScoped. Múltiplos Conversation Contexts podem existir simultaneamente. se nenhuma anotação for definida o escopo dos objetos é o Dependent. Quando uma HTTP Session é criada pelo container WEB. Quando uma HTTP Session é destruída pelo container WEB. Session Context. Um Conversation Context do tipo transient se comporta de maneira muito parecida com o Request Context. Todo objeto administrado pelo container CDI possui um escopo.end() é executado. As dependências são outros objetos pertencentes ao mesmo contexto do objeto que está sendo criado.

@Inject public void setUsuario ( Usuario usuario ) { this .14: CarrinhoDeCompras.12: CarrinhoDeCompras. List < Double > numeros = new ArrayList < Double >() . Há três tipos de Injection Points: Bean Constructors As dependências de um objeto podem ser definidas através de construtores com a anotação @Inject.k19. usuario = usuario .. i < 5.]@Named@Producespublic List<Double> getNumeros()[* System . println ( " GERANDO NÚMEROS " ) .. 10 1 2 3 . i ++) { 166 www.C ONTEXTS AND D EPENDENCY I NJECTION .13: CarrinhoDeCompras. out .java Field As dependências de um objeto podem ser definidas através de atributos com a anotação @Inject. } Código Java 10.com. for ( int i = .java Initializer methods As dependências de um objeto podem ser definidas através de métodos inicializadores com a anotação @Inject. } } Código Java 10.java Exercícios de Fixação Altere o método getNumeros() da classe GeradorDeNumeros do projeto cdiWeb para que ele adicione uma mensagem no console toda vez que for chamado. 1 2 3 4 5 6 7 8 9 public class CarrinhoDeCompras { private Usuario usuario .br .CDI 166 As dependências de um objeto são definidas através de Injection Points. 1 2 3 4 5 public class CarrinhoDeCompras { @Inject private Usuario usuario . 1 2 3 4 5 6 7 public class CarrinhoDeCompras { @Inject public CarrinhoDeCompras ( Usuario usuario ) { } } Código Java 10.

CDI Código Java 10. random () ) .xhtml e depois observe as mensagens impressas no log do Glassfish 3. utilize o Resquet Scope. Não esqueça de importar a anotação import javax..RequestScoped... random () ) . } return numeros . add ( Math . List < Double > numeros = new ArrayList < Double >() . } .16: GeradorDeNumeros. i < 5.1...facebook..2.xhtml e depois observe as mensagens impressas no console do eclipse. for ( int i = .java Acesse novamente a url http://localhost:8 8 /cdiWeb/numeros.com/k19treinamentos 167 .context. out .] Código Java 10. i ++) { numeros .java Acesse a url http://localhost:8 8 /cdiWeb/numeros.] C ONTEXTS AND D EPENDENCY I NJECTION . 11 Para evitar que o método getNumeros seja chamado mais do que uma vez por requisição HTTP . println ( " GERANDO NÚMEROS " ) . 13 www. } . 12 1 2 3 4 5 6 7 8 9 1 ..15: GeradorDeNumeros. add ( Math .167 4 5 6 7 8 numeros .enterprise.]@Named@Produces[*@RequestScoped public List < Double > getNumeros () { System . } return numeros .

com.CDI 168 168 www.C ONTEXTS AND D EPENDENCY I NJECTION .k19.br .

Exercícios de Fixação Crie um Dynamic Web Project no eclipse chamado bugWeb. implementaremos um pequeno projeto para praticar os conceitos discutidos nos capítulos anteriores. siga exatamente as imagens abaixo.APÊNDICE P ROJETO A Neste capítulo. Criaremos um sistema simples de cadastro de bugs. Você pode digitar “CTRL+3” em seguida “new Dynamic Web Project” e “ENTER”.com/k19treinamentos 169 . 1 www. Depois.facebook.

P ROJETO 170 170 www.br .com.k19.

com / xml / ns / persistence / persistence_2_ .171 P ROJETO Configure a aplicação bugWeb para utilizar o data source jdbc/K19 criado no capítulo 5.xml Habilite os recursos do CDI adicionando o arquivo beans. org /2 1/ XMLSchema .instance " xsi:schemaLocation = " http: // java . MySQL5InnoDBDialect " / > </ properties > </ persistence . w3 . " encoding = " UTF -8 " ? > < persistence version = " 2.xml na pasta WEB-INF do projeto bugWeb. format_sql " value = " true " / > < property name = " hibernate .source > < properties > < property name = " hibernate .xml na pasta META-INF dentro do src do projeto bugWeb. hbm2ddl .facebook. 2 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 <? xml version = " 1. xsd " > < persistence . com / xml / ns / persistence http: // java . auto " value = " update " / > < property name = " hibernate . hibernate . com / xml / ns / persistence " xmlns:xsi = " http: // www . show_sql " value = " true " / > < property name = " hibernate .unit name = " K19 " transaction . adicionando o arquivo persistence.data . dialect . sun . " xmlns = " http: // java . dialect " value = " org .data . hibernate . sun .source > jdbc / K19 </ jta . ejb .unit > </ persistence > Código XML A. HibernatePersistence </ provider > <jta .type = " JTA " > < provider > org . sun .com/k19treinamentos 171 . 3 www.1: persistence.

.mapping > < role . com . k19 . entities .name > </ security . " encoding = " UTF -8 " ? > < beans xmlns = " http: // java .name > users </ group .3: web..config > < realm . com / xml / ns / javaee " xmlns:xsi = " http: // www .4: sun-web. Adicione nesse pacote um Entity Bean para modelar projetos e outro para modelar bugs.name > USERS </ role .k19.role . adicionando no arquivo web.role .name > </ security .xml 5 Faça o mapeamento dos Groups do K19-Realm para os Roles da aplicação bugWeb.name > </ login . Código XML A. import javax . .name >K19 . w3 . < security .role .Realm </ realm .mapping > < role . sun ..config > .xml 172 Configure a aplicação bugWeb para que ele utilize o Realm K19-Realm criado no capítulo 7.entities no projeto bugWeb.2: beans. Entity . com / xml / ns / javaee http: // java . persistence . persistence . sun . GeneratedValue . org /2 1/ XMLSchema ..name > < group .xml do projeto bugWeb as configurações necessárias..mapping > < security .br . Código XML A.instance " xsi:schemaLocation = " http: // java .com. public Long getId () { return id . 4 1 2 3 4 5 .xml 1 2 3 4 5 6 7 8 9 1 11 Crie um pacote chamado br.P ROJETO 1 2 3 4 5 6 7 <? xml version = " 1. sun .k19. com / xml / ns / javaee / beans_1_ .. xsd " > </ beans > Código XML A. Id . persistence .name > ADMIN </ role . private String description .name > admin </ group . } 172 www.. 6 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 package br . @Entity public class Project { @Id @GeneratedValue private Long id .com..name > < group . import javax .role . private String name .mapping > . import javax . < login .

com . List . import java . RolesAllowed . PersistenceContext . entities .sessionbeans no projeto bugWeb.com/k19treinamentos 173 . TransactionAttribute . util . import br . EntityManager . javax . manager . com . Entity .1: Project. import import import import javax . javax .173 2 21 22 P ROJETO // GETTERS AND SETTERS } Código Java A. merge ( project ) . Adicione nesse pacote um SLSB para funcionar como repositório de projetos e outro para funcionar como repositório de bugs. @Entity public class Bug { @Id @GeneratedValue private Long id . Stateless . javax .java 7 Crie um pacote chamado br.facebook. public void add ( Project project ) { this . persist ( project ) .java 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 16 17 18 19 2 21 22 package br . Id . k19 . persistence . TransactionAttributeType . ManyToOne . TypedQuery . security . com . manager . javax . persistence . javax .com. persistence . annotation . persistence . k19 . Bug . entities . javax . private String description . javax .2: Bug. } public void edit ( Project project ) { this . 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 . persistence .k19. ejb . Project . import import import import import import import javax . k19 . GeneratedValue . // GETTERS AND SETTERS } Código Java A. private String severity . persistence . javax . entities . sessionbeans . @Stateless @RolesAllowed ({ " ADMIN " . ejb . javax . persistence . @ManyToOne private Project project . ejb . k19 . com . " USERS " }) public class ProjectRepository { @PersistenceContext private EntityManager manager . import br . } www.

persistence . } this . } @RolesAllowed ({ " ADMIN " }) public void removeById ( Long id ) { Bug bug = this . find ( Project . } @TransactionAttribute ( TransactionAttributeType . javax . EntityManager . class ) . NOT_SUPPORTED ) public Project findById ( Long id ) { return this . TransactionAttribute . public void add ( Bug bug ) { this . class ) . com . } @TransactionAttribute ( TransactionAttributeType . javax . getResultList () . manager . persistence . javax . import import import import import import import javax . import br . createQuery ( " select x from Bug x where x . manager . id ) . manager . Bug . " USERS " }) public class BugRepository { @PersistenceContext private EntityManager manager . persist ( bug ) . manager . security . createQuery ( " select x from Project x " . class ) . import java . javax . PersistenceContext .com. for ( Bug bug : bugs ) { this . remove ( bug ) .3: ProjectRepository. class . id ) . ejb . getResultList () . manager . ejb . NOT_SUPPORTED ) public List < Bug > findAll () { TypedQuery < Bug > query = this . manager . this . k19 . manager . k19 . List . getResultList () . } } Código Java A. javax . NOT_SUPPORTED ) public List < Project > findAll () { TypedQuery < Project > query = this . } @TransactionAttribute ( TransactionAttributeType . project = : project " . find ( Bug . 174 www. javax . RolesAllowed . manager . } public void edit ( Bug bug ) { this . com . find ( Project . ejb . annotation . util . sessionbeans . class . project ) . TypedQuery < Bug > query = this . return query .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 .br . manager . List < Bug > bugs = query . Project . @Stateless @RolesAllowed ({ " ADMIN " . createQuery ( " select x from Bug x " . manager . class . Bug . return query . entities . TypedQuery . remove ( bug ) . manager . Stateless . id ) . setParameter ( " project " .k19. TransactionAttributeType . merge ( bug ) . remove ( project ) .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 . Bug . query . persistence .

public void save () { if ( this . projectRepository . k19 . projectRepository . @Named @RequestScoped public class ProjectMB { @Inject private ProjectRepository projectRepository . } } Código Java A. add ( this . } } www. Named . private Project project = new Project () . Project . import br . this . import javax . entities . } return projects . inject .com/k19treinamentos 175 . List . } public Project getProject () { return project . import br . projects = this . sessionbeans . util . inject . } this . context . getId () == null ) { this .java P ROJETO 8 Crie um pacote chamado br. ProjectRepository . } else { this .managedbeans no projeto bugWeb. projects == null ) { this . projects = null . projectRepository . } public void delete ( Long id ) { this . Adicione ness pacote um Managed Bean CDI para oferecer para as telas JSF as funcionalidades de CRUD relacionadas aos projetos. removeById ( id ) . import java . project = new Project () . k19 . } public void prepareEdit ( Long id ) { this . managedbeans . k19 . com . import javax .k19. findById ( id ) . Inject . id ) . edit ( this .175 4 41 42 43 44 45 46 } @TransactionAttribute ( TransactionAttributeType . manager . getProject () . com . this . getProject () ) .4: BugRepository. private List < Project > projects .facebook. projectRepository . } public List < Project > getProjects () { if ( this . class . projects = null . findAll () .com. 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 . NOT_SUPPORTED ) public Bug findById ( Long id ) { return this . enterprise . import javax . project = this . RequestScoped . projectRepository . find ( Bug . com . getProject () ) .

private Long projectId . findAll () . getBug () . util . Project . bugRepository . com . k19 . k19 . managedbeans . k19 . br . } this . edit ( this . add ( this . bugs == null ) { this . entities . bugRepository . import javax . bug .k19. private List < Bug > bugs . import javax . this . projectRepository . bug = this . getBug () ) . } return bugs . com .java Adicione no pacote br. projectId ) .P ROJETO 176 Código Java A. this . Named . com . enterprise . @Inject private ProjectRepository projectRepository . inject . sessionbeans . findById ( id ) . } public void prepareEdit ( Long id ) { this . bugs = null . context .k19.com. } public List < Bug > getBugs () { if ( this . k19 . } else { this . getBug () ) . } public Bug getBug () { return bug . @Named @RequestScoped public class BugMB { @Inject private BugRepository bugRepository . br . ProjectRepository . bug = new Bug () . inject . entities . } public void delete ( Long id ) { this . findById ( this .br . bugs = null . import javax . removeById ( id ) . Bug . bugRepository . bugRepository . getId () == null ) { this . import java . sessionbeans . com . if ( this . RequestScoped . setProject ( project ) .com. 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 . List . com . k19 . this . public void save () { Project project = this . bugs = this . bugRepository . BugRepository . import import import import br . Inject . private Bug bug = new Bug () .managedbeans um Managed Bean CDI para oferecer para as telas JSF as funcionalidades de CRUD relacionadas aos bugs. br .5: ProjectMB. 176 www.

login ( this . @Named @RequestScoped public class AuthenticatorMB { private String username . ServletRequest . username . inject . com .k19. getCurrentInstance () . servlet . ServletException . managedbeans . request . } // GETTERS AND SETTERS } Código Java A. javax . import import import import import javax . getRequest () . k19 . www. ServletException .7: AuthenticatorMB. } } Código Java A.6: BugMB. filters .managedbeans um Managed Bean CDI para implementar o processo de login e logout. javax . RequestScoped . public String login () throws ServletException { FacesContext context = FacesContext . } public Long getProjectId () { return projectId . FacesContext . private String password . context . servlet . com . getExternalContext () . getRequest () . javax .java P ROJETO 10 Adicione no pacote br. 11 1 2 3 4 5 6 7 8 package br . FilterConfig . logout () . getExternalContext () . this . } public String logout () throws ServletException { FacesContext context = FacesContext . request .com. enterprise . faces . 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 . Named .com/k19treinamentos 177 .filters no projeto bugWeb. HttpServletRequest .java Crie um pacote chamado br. k19 . javax . import import import import javax . HttpServletRequest request = ( HttpServletRequest ) context . servlet . servlet .k19. http .facebook.com. context . HttpServletRequest request = ( HttpServletRequest ) context . javax . projectId = projectId . javax . servlet . io . IOException . import java . getCurrentInstance () . return " / login " .177 61 62 63 64 65 66 67 68 69 7 } public void setProjectId ( Long projectId ) { this . servlet . return " / projects " . password ) . Adicione nesse pacote um Filtro para verificar a autenticação dos usuários. javax . FilterChain .

8: AuthenticatorFilter. response ) . ServletException { HttpServletRequest req = ( HttpServletRequest ) request . Adicione um arquivo chamado login. w3 . annotation . servlet . FilterChain chain ) throws IOException .br . http . xhtml " > Bugs </ h : outputLink > </ h : panelGrid > </ h : form > </ ui : composition > Código XHTML A. w3 . WebFilter . xhtml " > Projects </ h : ← outputLink > <h : outputLink value = " #{ request . 12 1 2 3 4 5 6 7 8 9 1 11 12 13 14 15 < ui : composition xmlns = " http :// www . sendRedirect ( req . if ( req .java Crie um menu para as telas da aplicação bugWeb.xhtml 13 Crie um tela de login na aplicação bugWeb. Adicione um arquivo chamado menu. http . res . com / jsf / core " > <h : form > <h : panelGrid > <h : commandLink action = " #{ authenticatorMB . com / jsf / html " xmlns : f = " http :// java .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 .xhtml na pasta WebContent do projeto bugWeb. org /1999/ xhtml " 178 www. contextPath }/ bugs . org /1999/ xhtml " xmlns : ui = " http :// java . dtd " > < html xmlns = " http :// www . javax . ServletResponse . servlet . servlet . javax . } else { chain . servlet . getRemoteUser () == null && ! req .xhtml na pasta WebContent do projeto bugWeb. w3 . doFilter ( request . ← getContextPath () + " / login . ServletResponse response . HttpServletResponse . xhtml " ) . sun .k19. sun . 178 @WebFilter ( servletNames = { " Faces Servlet " }) public class AuthenticatorFilter implements javax . servlet . org / TR / xhtml1 / DTD / xhtml1 . logout } " > logout </ h : commandLink > <h : outputLink value = " #{ request .com. } } @Override public void init ( FilterConfig filterConfig ) throws ServletException { } @Override public void destroy () { } } Código Java A. 1 2 3 4 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1.1: menu. javax .transitional . xhtml " ) ) { HttpServletResponse res = ( HttpServletResponse ) response . Transitional // EN " " http :// www . endsWith ( req . com / jsf / facelets " xmlns : h = " http :// java . HttpServletRequest . Filter { @Override public void doFilter ( ServletRequest request . getRequestURI () . getContextPath () + " / login . sun . contextPath }/ projects .

com / jsf / core " > <h : head > < title > Projects </ title > </ h : head > <h : body > < ui : include src = " / menu . project . project . description } " / > <h : commandButton action = " #{ projectMB . password } " / > <h : commandButton action = " #{ authenticatorMB . sun . sun .xhtml na pasta WebContent do projeto bugWeb. sun . com / jsf / html " xmlns : f = " http :// java . login } " value = " login " / > </ h : panelGrid > </ h : form > </ h : body > </ html > Código XHTML A. 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. projects } " border = " 1 " > <h : column > www. username } " / > <h : outputLabel value = " Password : " / > <h : inputSecret value = " #{ authenticatorMB . 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 . com / jsf / facelets " xmlns : h = " http :// java . name } " / > <h : outputLabel value = " Description : " / > <h : inputTextarea value = " #{ projectMB . Adicione um arquivo chamado projects. project . org /1999/ xhtml " xmlns : ui = " http :// java .2: login. com / jsf / facelets " xmlns : h = " http :// java .facebook. projects } " var = " project " rendered = " #{ not empty projectMB . w3 . save } " value = " Save " / > </ h : panelGrid > </ h : form > < hr / > < h1 > Project List </ h1 > <h : dataTable value = " #{ projectMB . xhtml " / > < hr / > < h1 > New Project </ h1 > <h : form > <h : panelGrid > <h : inputHidden value = " #{ projectMB . w3 .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 . dtd " > < html xmlns = " http :// www .transitional .com/k19treinamentos 179 . Transitional // EN " " http :// www . sun . sun . id } " / > <h : outputLabel value = " Name : " / > <h : inputText value = " #{ projectMB . sun . com / jsf / html " xmlns : f = " http :// java .xhtml P ROJETO Crie uma tela para administrar os projetos. org / TR / xhtml1 / DTD / xhtml1 .

com / jsf / core " > <h : head > < title > Bugs </ title > </ h : head > <h : body > < ui : include src = " / menu . prepareEdit ( project . xhtml " / > < hr / > < h1 > New Bug </ h1 > <h : form > <h : panelGrid > <h : inputHidden value = " #{ bugMB . id } " / > <h : outputLabel value = " Severity : " / > <h : selectOneMenu value = " #{ bugMB . com / jsf / html " xmlns : f = " http :// java . bug . w3 . sun . description } </ h : column > 180 <h : column > <f : facet name = " header " > Delete </ f : facet > <h : form > <h : commandLink action = " #{ projectMB . id } </ h : column > <h : column > <f : facet name = " header " > Name </ f : facet > #{ project . bug . org /1999/ xhtml " xmlns : ui = " http :// java .com. name } </ h : column > <h : column > <f : facet name = " header " > Description </ f : facet > #{ project . id ) } " > delete </ h : commandLink ← > </ h : form > </ h : column > <h : column > <f : facet name = " header " > Edit </ f : facet > <h : form > <h : commandLink action = " #{ projectMB .br . org / TR / xhtml1 / DTD / xhtml1 . Transitional // EN " " http :// www . severity } " > <f : selectItem itemValue = " LOW " / > <f : selectItem itemValue = " MEDIUM " / > <f : selectItem itemValue = " HIGH " / > </ h : selectOneMenu > 180 www. Adicione um arquivo chamado bugs. delete ( project . id ) } " > edit </ h : ← commandLink > </ h : form > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML A.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 .transitional . w3 .3: projects. sun . dtd " > < html xmlns = " http :// www . 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. sun .xhtml na pasta WebContent do projeto bugWeb.xhtml Crie uma tela para administrar os bugs.k19. com / jsf / facelets " xmlns : h = " http :// java .

delete ( bug .facebook. id } " / > </ h : selectOneMenu > <h : commandButton action = " #{ bugMB . bugs } " border = " 1 " > <h : column > <f : facet name = " header " > Id </ f : facet > #{ bug .xhtml P ROJETO Crie uma tela para os erros internos e os erros de autorização. dtd " > < html xmlns = " http :// www . w3 . 16 1 2 3 4 5 6 7 8 <! DOCTYPE html PUBLIC " -// W3C // DTD XHTML 1. Adicione um arquivo chamado error. com / jsf / facelets " xmlns : h = " http :// java . sun .transitional . id ) } " > edit </ h : commandLink > </ h : form > </ h : column > </ h : dataTable > </ h : body > </ html > Código XHTML A.com/k19treinamentos 181 . description } </ h : column > <h : column > <f : facet name = " header " > Delete </ f : facet > <h : form > <h : commandLink action = " #{ bugMB . bug . bugs } " var = " bug " rendered = " #{ not empty bugMB .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 . name } " itemValue = " #{ project . name } </ h : column > <h : column > <f : facet name = " header " > Severity </ f : facet > #{ bug . description } " / > <h : outputLabel value = " Project : " / > <h : selectOneMenu value = " #{ bugMB . severity } </ h : column > <h : column > <f : facet name = " header " > Description </ f : facet > #{ bug . org / TR / xhtml1 / DTD / xhtml1 . project .xhtml na pasta WebContent do projeto bugWeb. sun . id } </ h : column > <h : column > <f : facet name = " header " > Project </ f : facet > #{ bug . save } " value = " Save " / > </ h : panelGrid > </ h : form > < hr / > < h1 > Bug List </ h1 > <h : dataTable value = " #{ bugMB .4: bugs. sun . w3 . projects } " var = " project " itemLabel = " #{ project . com / jsf / core " > www. Transitional // EN " " http :// www . org /1999/ xhtml " xmlns : ui = " http :// java . projectId } " > <f : selectItems value = " #{ projectMB . prepareEdit ( bug . id ) } " > delete </ h : commandLink > </ h : form > </ h : column > <h : column > <f : facet name = " header " > Edit </ f : facet > <h : form > <h : commandLink action = " #{ bugMB . com / jsf / html " xmlns : f = " http :// java .

xml 18 Teste a aplicação!!! 182 www.page > < exception .xml do projeto bugWeb. lang .5: web.type > < location >/ error . Exception </ exception . Adicione o seguinte trecho de código nesse arquivo. 17 1 2 3 4 < error .com.br .k19.xhtml 182 Configure a página de erro no arquivo web. xhtml </ location > </ error .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 > Código XHTML A.5: error.page > Código XML A.type > java .