Visão Geral de EJB 3.0

5,902 views

Published on

Noções de EJB 3.0

  • Be the first to comment

Visão Geral de EJB 3.0

  1. 1. Noções de EJB Mais alguns detalhes...
  2. 2. Três itens relevantes • Anotações (metadados) • Mínimo emprego de descritores (documentos XML) • Injeção de dependência
  3. 3. Anotações • Adiciona informação a classe, interface, método ou variável • A classe abaixo é um POJO com informação adicional para um contêiner: @Stateless public class X {...}
  4. 4. Algumas anotações • javax.annotation.Resource • javax.ejb.EJB • javax.jws.WebServiceRef • javax.persistence.PersistenceContext • javax.persistence.PersistenceUnit • javax.annotation.PostConstruct, ...
  5. 5. Descritores • O nome formal é deployment descriptors • Documentos XML (ou seja, arquivos contendo XML) • Configuram serviços oferecidos pelo contêiner (alternativa para anotações) • Tem precedência sobre anotações
  6. 6. Trecho de um descritor • <enterprise-beans> <sessions> <ejb-name>NomeDoMeuBean</ejb-name> <local>pacote.MinhaInterface</local> <ejb-class>pacote.MinhaClasse</ejb-class> ... </sessions> </enterprise-beans>
  7. 7. Injeção de dependência • Em vez do seu código requisitar, criar, localizar um objeto do qual ele depende, um contêiner injeta esta dependência no seu código • Em vez do código localizar um recurso, ele apenas diz que precisa dele. É função de “outro” código fornecer o recurso.
  8. 8. DI (segunda-parte) • Você “abre mão” de controle • Você não mais decide, alguém decide o que você irá usar • Em geral, o que será empregado é definido em um arquivo de configuração • Ao olhar o código, não se sabe exatamente quem fornecerá serviços
  9. 9. DI (terceira-parte) • Você declara dependências • Contêiner é responsável por instanciar objetos necessários e fornecê-los a quem precisa • Seu código não cria uma instância da interface X, um objeto que implementa esta interface é declarado e o contêiner se encarrega de instanciá-lo (quando preciso)
  10. 10. Exemplo • public class Main { @EJB private static ServicoRemote srv; public static void main(String... args) { System.out.println(srv.toUpper(“casa”)); } } java.lang.NullPointerException
  11. 11. Tipos de beans • Session bean @Stateless ✦ @Stateful ✦ •@MessageDriven •@Entity
  12. 12. Qual a diferença? • Session beans e message-driven beans Lógica de negócio ✦ • Entity beans Persistência ✦
  13. 13. Session beans e MDBs? • Session beans Requisições diretas de funções do cliente ✦ (calcule isto, faça aquilo, ...) • @MessageDriven Processam mensagens indiretas ✦
  14. 14. Requisições diretas!? (session beans) • Quanto custa tal carro? • Qual o saldo desta conta? • Dê-me o PDF do histórico deste aluno! • Altere o endereço de entrega deste pedido! • Acrescente esta disciplina à lista de desejadas! • Qual o próximo pedido a ser atendido?
  15. 15. Requisições indiretas!? (MDBs) • Cadastre requisição de emissão de diploma para o aluno A! Biblioteca verifica pendências ✦ Departamento verifica pendências ✦ DAA verifica pendências ✦ Software inteligente detecta legalidade ✦ • Quando todos sinalizarem “ok”, emissor de diploma imprime propriamente dito o diploma.
  16. 16. Requisições indiretas! @MessageDriven • Em geral as tarefas correspondentes não são executadas de forma síncrona Garçom (atende vários pedidos ✦ simultaneamente) instalação de ADSL, requisição de serviços... ✦ • Contraste com (@Stateless, @Stateful) Atendimento médico ✦ Reserva de voo ✦ Confirmação de inscrição, matrícula, ... ✦
  17. 17. Enfim, session beans ou MDBs? • São opções que visam mais adequadamente tratar problemas distintos • Use o que melhor atende o seu problema • Não é preciso usar ambos
  18. 18. E quanto aos tipos de Session beans? • @Stateless Funções atendidas por uma ✦ requisição • @Stateful Funções que exigem a manutenção de ✦ um diálogo com o cliente
  19. 19. Um exemplo trivial • Conversão de letras minúsculas para letras maiúsculas Definitivamente este não é um exemplo ✦ que justifica o emprego de EJB Registre isto no seu cérebro ✦
  20. 20. Exemplo (Cliente) • public class Main { @EJB private static SessionRemote srv; public static void main(String... args) { System.out.println(srv.toUpper(“casa”)); } } Resultado esperado!!!??? CASA
  21. 21. Exemplo (EJB) (interface) public class Main { @EJB SessionRemote srv; private static public static void main(String... args) { System.out.println(srv.toUpper(“casa”)); } } • @Remote public interface SessionRemote { String toUpper(String entrada); }
  22. 22. Exemplo (EJB) (stateless session bean) • @Stateless(mappedName=”MeuEJB”) public class SessionBean implements SessionRemote { public String toUpper(String entrada) { return entrada.toUpperCase(); } } public class Main { @EJB private static SessionRemote srv; public static void main(String... args) { System.out.println(srv.toUpper(“casa”)); } }
  23. 23. Visão geral do exemplo Não há dependência de Main para SessionBean (objeto de interesse será injetado pelo ACC)
  24. 24. ACC? • Application Client Container • Contêiner para o cliente? Sim! Veja o código! public class Main { @EJB SessionRemote srv; private static public static void main(String... args) { System.out.println(srv.toUpper(“casa”)); } } Quem poderia injetar um objeto que implementa SessionRemote em srv? Observe que este código não será executado pelo EJB contêiner!!!!!
  25. 25. Sou obrigado a usar um ACC? • Não! Contudo, abre-se mão da injeção de dependência!!! • Cliente que não é executado por um ACC JNDI InitialContext ctc = new InitialContext(); SessionRemote srv = (SessionRemote) ctx.lookup(“MeuEJB”); System.out.println(srv.toUpper(“casa”));
  26. 26. Comparando clientes Usa DI public class Main { @EJB Exige contêiner private static SessionRemote srv; public static void main(String... args) { (ACC) System.out.println(srv.toUpper(“casa”)); } } Exige JVM convencional InitialContext ctc = new InitialContext(); SessionRemote srv = (SessionRemote) ctx.lookup(“MeuEJB”); System.out.println(srv.toUpper(“casa”)); Não usa DI (cliente conhece um tal de “MeuEJB”)
  27. 27. @Stateless (atributo mappedName) • Anotações possuem, em geral, atributos • @Stateless possui, entre outros, o atributo mappedName • mappedName especifica o nome empregado por JNDI • Em tempo, JNDI é acrônimo de Java Naming and Directory Interface
  28. 28. JNDI • Associa nome a recurso • Permite a uma aplicação Java descobrir e recuperar um objeto de qualquer tipo • Por exemplo, obter referência para EJB InitialContext ctc = new InitialContext(); SessionRemote srv = (SessionRemote) ctx.lookup(“MeuEJB”); System.out.println(srv.toUpper(“casa”));
  29. 29. Lembra-se da discussão... • Session beans (negócio) @Stateless (ilustrado) ✦ @Stateful (próximo exemplo) ✦ • Message-driven Beans (MDBs) (negócio) Requisição indireta ✦ (processamento assíncrono)
  30. 30. @Stateful • Um diálogo (ou sessão) é mantido Seleciona o modelo ✦ Seleciona o ano ✦ Seleciona a cor ✦ Seleciona opcionais ✦ • Cliente define um estado e, em requisições posteriores, aquele estado está lá
  31. 31. @Stateful • Primeiro momento Cliente requisita um modelo específico ✦ • Segundo momento Cliente requisita um ano específico (esta ✦ requisição se aplica ao modelo selecionado anteriormente) • Ou seja, em um @Stateful bean, o estado anteriormente obtido é mantido em chamadas posteriores
  32. 32. @Stateful (mantendo estando) • Obser ve a classe abaixo (POJO) public class Carro { private String modelo; private int ano; // Métodos get/set para modelo e ano } • Transformado em stateful bean (sufixo Bean é uma convenção) @Stateful public class CarroBean {...}
  33. 33. Cliente public class Main { @EJB private static CarroRemote carro; public static void main(String... args) { exibeCarro(carro); carro.setModelo(“Fusca”); carro.setAno(1969); exibeCarro(carro); } } Ocorre NullPointerException? Não! O modelo se perde após setModelo? Não O ano se perde após setAno? Não! O bean que recebe a mensagem setModelo é o mesmo que responde ao método setAno? Sim! O mesmo bean responde todas as msgs? SIM!
  34. 34. Cliente e beans • Se existe um único cliente e um único bean, então não há como chamar outro bean! • Se existem vários clientes, então um cliente pode alterar o estado de um stateful bean consultado por outro cliente? Não! • Para cada cliente um correspondente stateful bean? Sim! • Quem mantém a correta associação entre clientes e beans? O EJB contêiner!
  35. 35. Clientes de @Stateless • Requisições são tratadas em uma única chamada, ou seja, instâncias de stateless beans podem ser compartilhadas em um pool delas! • Instâncias de stateful beans não podem ser compartilhadas!
  36. 36. Exercício • Qual o resultado da execução do comando abaixo para o código fornecido? java -cp classpath-aqui Main public class Main { @EJB private static CarroRemote carro; public static void main(String... args) { exibeCarro(carro); carro.setModelo(“Fusca”); carro.setAno(1969); exibeCarro(carro); } }
  37. 37. Exercício • Código s1.m1(); s1.m2(); • Um cliente C envia a mensagem m1 para o stateful bean S1 • Em seguida, C envia a mensagem m2 para o stateful bean S1 • Um único objeto, em execução no contêiner EJB, recebe as mensagens m1 e m2?
  38. 38. Problema • Se para cada cliente uma instância de um stateful bean é criada, então teremos um crescimento indefinido do número de instâncias no contêiner EJB?
  39. 39. Resposta • Não. Stateful beans permanecem pelo menos enquanto durar a sessão (o que não é razoável em alguns casos) • Nestes casos, use a anotação @Remove para anotar método que, quando chamado, demarca fim da sessão. • Quando cliente chama método anotado por @Remove, o cliente avisa o contêiner do fim do workflow (sessão e bean podem ser eliminados)
  40. 40. Ou seja • Para este cliente, o contêiner não poderá fazer nada até que a sessão expire, afinal, como o contêiner poderia saber que não mais requisições serão enviadas? public class Main { @EJB private static CarroRemote carro; public static void main(String... args) { exibeCarro(carro); carro.setModelo(“Fusca”); carro.setAno(1969); exibeCarro(carro); } }
  41. 41. Versão alterada • Assumindo que o método fim() está anotado com @Remove, temos abaixo um cliente bem comportado e que respeita o contêiner! public class Main { @EJB private static CarroRemote carro; public static void main(String... args) { exibeCarro(carro); carro.setModelo(“Fusca”); carro.setAno(1969); exibeCarro(carro); carro.fim(); } }
  42. 42. Como executar estes exemplos? Primeiro Passo: Instalar o contêiner
  43. 43. Glassfish (Java EE Application Server) • Obtenha o jar file correspondente https://glassfish.dev.java.net/public/downloadsindex.html • Primeiro passo java -Xmx256m -jar <glassfish-obtido>.jar • Vá para o diretório criado cd glassfish • Se não for usar recursos de clustering ant -f setup.xml
  44. 44. Iniciar/parar o glassfish • Iniciar asadmin start-domain domain1 • Testar Visite http://localhost:8080 Visite http://localhost:4848 (admin/adminadmin) • Parar asadmin stop-domain domain1
  45. 45. Tela de administração Tela de administração
  46. 46. Demais passos • Crie dois beans: um stateless e outro stateful • Criar cliente JNDI e cliente via ACC para usufruir dos dois beans • Realizar a implantação (deployment) • Executar os clientes e obser var os resultados
  47. 47. Refinamento dos passos • Criar classe anotada com @Stateful e @Remove • Criar classe anotada com @Stateless (serviço oferecido por chamada única) • Efetuar o deployment no contêiner EJB (exige instalar e iniciar) • Criar cliente contendo anotação @EBJ (ACC) • Criar cliente que faz uso de JNDI (convém usar atributo mappedName tanto em @Stateless quanto @Stateful)
  48. 48. Revisão • Session beans (camada de negócio) @Stateless ✦ @Stateful ✦ • Message-driven beans (camada de negócio) @MessageDriven ✦ Próximo foco!
  49. 49. Message-Driven Bean (MDB) Finalidade • Integração Sistema A envia mensagem para B ✦ • Processamento assíncrono Serviço é requisitado (ação posterior) ✦ • Distribuição Sistema A comunica-se com B ✦
  50. 50. Comparação • Session bean Processa requisição diretamente enviada ✦ pelo cliente • Message-Driven Bean (MDB) Processa mensagem ✦ (indiretamente recebida) Cliente não sabe quem irá tratar ✦
  51. 51. Como funciona? • Cliente envia msg • “Middleman” encarrega-se de entregar a msg ao destino • “Middleman” é confiável, ou seja, a msg será entregue, mesmo que o destino não esteja disponível no momento em que o cliente envia a msg.
  52. 52. Alguns detalhes • Troca de msgs em Java ocorre via JMS • JMS Java Message Service • MDBs dependem de JMS
  53. 53. Cenário de uso • Lembra-se da compra de automóvel? • Você seleciona o carro desejado, com a configuração desejada e requisita proposta de financiamento. • Requisição pode ser enviada a várias financiadoras (análise pode envolver atividade manual)
  54. 54. Parte do processo... • Coleta dados p/ aquisição (stateful) • Requisita proposta financiamento (pode levar dias a análise, certo?) ou seja, requisição deve ser assíncrona • MDB recebe proposta, avalia risco por perfil e, de forma assíncrona, avalia parecer de profissional (ser humano) • Profissional avalia e autoriza contato de “vendedores” (de forma assíncrona), ...
  55. 55. Graficamente... A partir deste ponto outra aplicação sinalizaria pedido de análise de proposta que, após concluída seria enviada a outro MDB para “despacho” (seria consumida por pessoal de “venda”)
  56. 56. Como é um MDB? • @MessageDriven(mappedName=”jms/Queue”) public class X implements MessageListener { public void onMessage(Message msg) { try { TextMessage txt = (TextMessage) msg; // Processa mensagem... } } }
  57. 57. Como é o “cliente”? • @Resource(mappedName=”jms/Queue”) private Destination geraProposta; @Resource(mappedName=”jms/ConnectionFactory”) private ConnectionFactory cf; // Segue código que // CRIA CONEXÃO // CRIA SESSÃO JMS API // CRIA PRODUTOR DE MENSAGENS // finalmente, ENVIA A MENSAGEM
  58. 58. JMS API!? • Sim! • Qual o package? javax.jms • Onde obter mais informações? http://java.sun.com/products/jms/ ✦
  59. 59. Não esqueça! • Para obter a fábrica de conexões @Resource(mappedName=”x”) ✦ • Para obter o destino da mensagem @Resource(mappedName=”x”) ✦ • Para tratar msgs para um dado destino @MessageDriven(mappedName=”x) ✦
  60. 60. Qual é o processo? • MDBs, quando são criados, dizem qual o destino a partir do qual receberá mensagens • Cliente envia mensagem para destino (destination) • EJB contêiner dispacha (via middleman, o message-orientedmiddleware) a mensagem para o MDB • MDB recebe msg via método onMessage onMessage?
  61. 61. MDBs implementam... • javax.jms.MessageListener (usado para receber msgs assíncronas) • Possui um único método void onMessage(Message msg)
  62. 62. Trate um MDB como • um stateless session bean, ou seja, • não assuma a manutenção de estado
  63. 63. Falta JPA! • Exemplo Isto é suficiente se atributos forem primitivos e todos devem ser persistidos! @Entity public class Aluno { @ID @GeneratedValue private long id; private String nome; ... }
  64. 64. Como usar? • Em algum lugar... • aluno.setNome(“Fulano”); entityManagerInstance.persist(aluno); Cabe ao persistence provider recuperar os atributos de aluno a serem persistidos, gerar um valor único para chave, montar uma sentença SQL compatível com o SGBD empregado e requisitar a execução.
  65. 65. O que foi visto? • Visão geral de conceitos • Visão geral de como funciona Falta uma quantidade significativa de informação que diz como usar!
  66. 66. Prática de EJB 3.0 Sequência elementar
  67. 67. Sequência Zero • Instale o Glassfish e o inicie asadmin start-domain • Verifique (http://localhost:8080) • Vá para a página do administrador http://localhost:4848 • Efetue login admin/adminadmin (conta padrão)
  68. 68. Sequência Um • Crie um stateless session bean (retorna uma frase sorteada dentre um conjunto de pelo menos 5 frases) • Crie um stateful session bean (retorna o valor de um contador que é incrementado a cada chamada) • Crie um MDB (exibe “RECEBI” para cada msg recebida)
  69. 69. Sequência dois • Crie um cliente (ACC) que exercite os três beans criados (um único cliente) • Execute o cliente e observe os resultados
  70. 70. Parabéns, se você está lendo este slide, é porque sobreviveu à iniciação em EJB. Esteja preparado para usufruir do que EJB pode oferecer!

×