Baixe o app para aproveitar ainda mais
Prévia do material em texto
Introdução ao java EE Enterprise Java Beans Métodos Assíncronos Injeção de Dependência e JNDI ENC Agendamento Interceptadores Transações Segurança Empacotamento Erick Ferreira Macedo Introdução ao java EE Razões para usar EJBs • Escalabilidade é obrigatória , EJBs podem ser distribuídos em múltiplos computadores enquanto permanecem transparente para o clientes • Transações são obrigatórias. • Diferentes tipos de cliente podem acessar a aplicação , EJBs podem ser acessados de múltiplas maneiras ; EJBs Local e Remoto , e WebService Soap e Rest. • Gerenciamento de concorrência é desejável. O Container EJB gerencia a concorrência. • Segurança é obrigatória, disponível como segurança declarativa não afetando a implementação , também permite segurança programática • Portabilidade em diferentes servidores é desejável. Razões para não usar EJBs • Container EJB não é desejado. • Container EJB não está disponível • Uma ou mais das restrições de programação EJB não pode ser respeitada. Como alternativa você pode usar um servidor de aplicação que contem um container embeddable EJB 3.1 que permite somente o uso do EJB Lite EJB Restrições Programática Há uma série de restrições de programação que um desenvolvedor EJB deve seguir, a fim de garantir a portabilidade entre diferentes Container Programming Restriction Motivation Um EJB não deve usar campos estáticos graváveis. Garantir a consistência em um ambiente distribuído. Um EJB não deve usar primitivas de thread synchronization para sincronizar a execução de múltiplas instâncias, exceto se o EJB é um bean de sessão Singleton com bean managed concurrency. Não vai funcionar em um ambiente distribuído. Um EJB não deve usar a funcionalidade de AWT para gerar a saída para um monitor ou obter entrada de um teclado. Servidores geralmente não permitem o acesso ao teclado ou a tela de um programa aplicativo. Um EJB não deve acessar arquivos e diretórios no sistema de arquivos diretamente. Os componentes de negócios deve usar uma API do gerenciador de recursos, tais como JDBC, para acessar os dados persistentes. Um EJB não deve agir como um servidor de rede, escuta em um soquete, aceitar conexões em um soquete ou usar um soquete para múltiplos cast. Conflitos com os deveres do servidor de aplicativos. Ele pode atuar como um cliente socket de rede. Poderia comprometer a segurança. Um EJB não deve tentar definir a fábrica de soquete usado por ServerSocket e soquete ou tentar definir a fábrica de manipulador de fluxo usado por URL. Poderia comprometer a segurança. Interfere com a capacidade do container para gerenciar o ambiente de tempo de execução. Um EJB não deve tentar gerenciar threads ou grupos de threads. Interfere com a capacidade do container para gerenciar o ambiente de tempo de execução. Um EJB não deve tentar ler ou escrever um descritor de arquivo diretamente. Poderia comprometer a segurança. Um EJB não deve tentar obter as informações de política de segurança para uma fonte de código particular. Poderia comprometer a segurança. Um EJB não deve tentar carregar uma biblioteca nativa. Poderia comprometer a segurança. Um EJB não deve tentar burlar as regras da linguagem de programação Java ao acessar pacotes e classes. Poderia comprometer a segurança. Um EJB não deve tentar definir uma classe em um pacote. Poderia comprometer a segurança. Um EJB não deve tentar acessar ou modificar os objetos de configuração de segurança (Policy, Security, Provider, Signer e Identity). Poderia comprometer a segurança. Um EJB não deve tentar usar a subclasse ou recursos objeto de substituição do Protocolo de serialização Java. Poderia comprometer a segurança. Um EJB não deve passar isso como um argumento de método ou resultado. Em vez disso, utilizar o resultado de um dos métodos getXXXObject no SessionContext ou classe EntityContext. O container pode usar um mecanismo de proxy para, por exemplo, controlar o acesso simultâneo da instância EJB. A referência injetado em clientes do EJB é uma referência para o proxy e não a uma instância da classe de implementação EJB. Container EJB Lite VS EJB Full EJB Lite é um subconjunto da API do EJB 3.1 , permitindo que os desenvolvedores de EJB reduza a dimensão e complexidade enquanto continua sendo compatível com e especificação EJB 3.1. Feature Full EJB 3.1 API EJB 3.1 Lite API Java Persistence 2.0 Disponível Disponível Session beans local/no interface client view. Disponível Disponível Session beans 3.0 remote client view. Disponível Não Disponível Session beans 2.x remote client view. Disponível Não Disponível Session beans exposed as JAX-WS web service endpoints. Disponível Não Disponível Session beans exposed as JAX-RPC web service endpoints. Disponível Não Disponível EJB timer service. Disponível Não Disponível Asynchronous invocation of session beans. Disponível Não Disponível RMI-IIOP interoperability. Disponível Não Disponível Message driven beans. Disponível Não Disponível Interceptors Disponível Disponível Bean and container managed transactions. Disponível Disponível Declarative and programmatic security. Disponível Disponível Embeddable API. Disponível Disponível Session Beans - Stateful, Stateless ou Singleton Existe três tipos de EJB Session Beans – Stateful , Stateless ou Singleton Stateful Session Beans Beans de sessão com estado, mantem o estado de conversação com um único cliente , as razões para escolher são : - O EJB precisa manter o estado com o cliente entre diferentes invocações - O EJB fica transparente para o cliente. - O EJB gerencia o fluxo de outros EJBs. Stateless Session Beans Beans de sessão sem estado pode existir em um pool no qual o Container pode escolher qualquer Bean para servir a requisição. Stateless pode manter o estado de uma variável de instancia mais não com um cliente especifico, as razões para escolher são : - O EJB não precisa manter um estado especifico com o cliente. - O EJB tem uma melhor escalabilidade - O EJB tem uma melhor performance - O EJB pode ser exposto com um WebService - O EJB executa tarefas genéricas que pode ser terminado em uma única invocação de método Singleton Session Beans Beans Singleton são Beans o quais existe somente uma única instancia por aplicação , eles podem ser configurados para permitir acesso concorrente , porem cuidados especiais devem ser tomados quando se projeta um EJB Singleton afim de proteger recursos que não deve ter acesso concorrente, as razões para escolher são : - O EJB compartilha o estado por toda aplicação - O EJB é acessado por varia threads simultaneamente - O EJB pode ser usado para inicializar ou finalizar uma tarefa no contexto da aplicação. - O EJB pode ser exposto com um WebService Tipos de acesso do Cliente (Local , Remote ou WebService) - Local : é acessado na mesma aplicação , mesma JVM Ex: Web Componente e EJBs. - Remote : é acessado na mesma JVM ou VMs que estão em outro computadores Ex:Web Componente, EJBs e aplicação clientes. - WebService : Um Session Bean pode ser exposto como SOAP ou RESTful e permite acesso a qualquer WebService cliente em qualquer linguagem. Message Driven Beans Beans MDB são EJB para processar mensagens, as razões para escolher são : - O EJB pode ser invocado por mensagem assíncrona. - O EJB pode executar processo de negócio de longa duração sem afetar o cliente. - O EJB mantem baixo acoplamento com cliente, pois o cliente não se relaciona com o EJB. Enterprise Java Beans Session Beans Utilizando a arquitetura EJB, as regras de negócio são implementadas em componentes específicos que são chamados de SessionBeans. O Container EJB administra esses componentesoferecendo diversos recursos a eles. As características dos EJBs favorecem a escalabilidade da aplicação pois, de acordo com a demanda, o Container EJB cria novas instâncias e cada instância pode atender vários clientes. O Container EJB administra as instâncias criadas através de um Pool. Cada servidor de aplicação oferece configurações específicas para melhorar a eficiência no atendimento das chamadas. Na versão 3.1, o acesso a um EJB local não necessita de uma interface java nem a utilização da anotação @Local, então basta criar uma classe java anotada com a anotação @Stateless e somente método públicos do bean serão visíveis, como alternativa poderá ser usado a anotação @LocalBean, o resultado em ambos os casos é o mesmo, o EJB fica visível apenas na JVM que estiver sendo executado [visibilidade local]. Além disso, as regras de empacotamento foram simplificadas, os Session Beans podem ser empacotados em um módulo web. Uma interface de negocio pode ser uma interface remota ou local, mais não ambas. Quando o cliente invoca um método em uma interface remota do Bean de sessão, os valores são passado por valores, isso é independente se o cliente está na mesma VM ou em outra maquina da rede. Beans de entidades são objetos Java simples, eles podem ser serializados pela rede como objetos java simples, deste que implementam java.io.Serializable ou Externalizable. Descritor de implantação O EJB tem um descritor de implantação XML opcional definido no arquivo META-INF/ejb-jar.xml do arquivo JAR do EJB Ex: <ejb-jar> <enterprise-beans> <session> <ejb-name>PaymentBean</ejb-name> <remote>br.PaymentRemote</remote> <local>br.PaymentLocal</local> <ejb-class>br.PaymentBean</ejb-class> <session-type>Stateless</session-type> <resource-ref> <res-ref-name>dsOracle</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <mapped-name>java:/DefaultDS</mapped-name> <injection-target> <injection-target-class>com.Bean</injection-target-class> <injection-target-name>oracleDB</injection-target-name> </injection-target> </resource-ref> <env-entry> <env-entry-name>minNumber</env-entry-name> <env-entry-type>java.lang.Integer</env-entry-type> <env-entry-value>2000</env-entry-value> <injection-target> <injection-target-class>com.Bean</injection-target-class> <injection-target-name>minNumber</injection-target-name> </injection-target> <env-entry> </session> </enterprise-beans> </ejb-jar> O element <enterprise-beans> contido em <ejb-jar> define um conjunto de EJBs. O elemento <session> denota que você está implantando um bean de sessão. O elemento <ejb-name> fornece uma identidade ao bean de sessão que você pode referenciar. Os elementos <remote> e <local> identificam a interface de negocio do bean. O elemento <ejb-class> declara a classe do bean. O elemento <session-type> declara o tipo do bean Os elementos <resource-ref> e <env-entry> inicializa os campos dsOracle e minNumber da classe do bean. O descritor de implantação XML também suporta definições XML parciais. <ejb-jar> <enterprise-beans> <session> <ejb-name>PaymentBean</ejb-name> <env-entry> <env-entry-name>minNumber</env-entry-name> <env-entry-type>java.lang.Integer</env-entry-type> <env-entry-value>250</env-entry-value> </env-entry> <session> <enterprise-beans> </ejb-jar> EJBContext e SessionContext EJBContext Fornece uma visualização do ambiente container Definição da interface javax.ejb.EJBContext Métodos • getCallerPrincipal : é utilizado para obter o objeto java.security.Principal que representa o cliente • isCallerInRole : informa se o cliente que acessa o bean é membro de um nível de regra especifico, identificado pelo nome da regra. • getRollbackOnly() : método transacional, retorna true se a transação foi marcada para rollback, utilizado somente em CMT • setRollbackOnly() : método transacional, um EJB consegui vetar uma transação que é marcada para rollback e não pode ser confirmada por nenhum outro participante da transação, incluindo o container, utilizado somente em CMT • getUserTransaction(): método transacional para controlar programaticamente as transações, utilizado somente em BMT • getTimerService : retorna a referencia do TimerService do container, que permite que o bean sem informação de estado configure notificações dos eventos sincronizados para ele mesmo que atualmente está acessando o bean • lookup : é um método conveniente que permite pesquisar entradas no ENC do EJB. • getContextData() : O método getContextData habilita um método de negócio, o método do ciclo de vida, ou método de timeout , para recuperar qualquer contexto interceptores / webservices associada à sua invocação. • getEnvironment() ,isCallerInRoler(Identity role), getCallerIdentity(), getEJBHome(),getEJBLocalHome() estão obsoletos e uma RuntimeException é lançada se esses métodos forem executados. SessionContext A interface javax.ejb.SessionContext extends javax.ejb.EJBContext fornece uma visualização do ambiente do container EJB SessionContext permite obter informações como o usuário atual que está invocando no EJB ou pesquisar entradas dentro do ENC do EJB. Quando um instancia é trocada seu SessionContext muda para refletir o contexto do objeto EJB e o cliente que invoca o método. Definição da interface javax.ejb.SessionContext Métodos • EJBLocalObject e getEJBObject : deprecated, lança uma exceção se invocado. • getMessageContext : O método getMessageContext retorna a interface javax.xml.rpc.handler.MessageContext de um bean de sessão sem estado que implementa um JAX-RPC web service endpoint • getInvokedBusinessInterface : permite determinar se seu EJB foi invocado por meio de uma interface local, remota ou serviço web. Ele retorna a interface de negocio invocada como uma classe. • getBusinessObject : retorna uma referência ao EJB atual que pode ser invocado por outros clientes, já que é ilegal que uma instancia de bean passe uma referencia this a um outro bean, o parâmetro businessInterface precisa ser uma das interfaces Local ou Remota do EJB. • wasCancelCalled : É usado para verificar se o cliente cancelou o método assíncrono Regras EJB • A classe do Bean deve ser concreta, não pode ser final ou abstrata, uma vez que o container precisa manipular ela. • Deve ter um construtor sem argumentos, o container invoca esse construtor para criar o Bean, observe que o compilador insere o construtor sem argumentos padrão. • Um EJB pode ser uma subclasse de outro EJB ou de um POJO • Os métodos de negocio e callback do EJB serão herdados de uma super classe, ou seja, podem ser definidos em uma superclasse • As anotações @Stateless e @Statefull na superclasse, será ignorada na subclasse e somente método de ciclo de vida e atributos de recursos • são herdados. • Os nomes dos método de negocio não devem começar com "ejb", mais podem. • Os métodos de negocio, devem ser públicos não finais ou estáticos, gera conflitos. • Argumentos de método com EJB remoto deve implementar Serializable. • Você não pode marcar a mesma interface com mais de uma anotação • Você não pode ter mais de um método de ciclo de vida na mesma classe EJB. Erros : Caused by: java.lang.RuntimeException: br.PaymentEJBBean is final Caused by: java.lang.RuntimeException: Could not create an instance for bean class: class br.PaymentBean (se abstract) Caused by: java.lang.RuntimeException: Could not create no-interface view for bean class: class br.PaymentEJBBean (semconstructor default) Caused by: javax.ejb.EJBException: Cannot invoke method imprimir on nointerface view (caso protected) Caused by: java.lang.RuntimeException: More than one 'post-construct' method in PaymentEJBSingleton Caused by: java.lang.RuntimeException: More than one 'pre-destroy' method in PaymentEJBStateless Interface local não é necessária estender a nenhuma outra interface. No EJB 2.1 ou anterior era obrigatório estender a javax.ejb.EJBLocalObject. Interface remota não é necessária estender a nenhuma outra interface. No EJB 2.1 ou anterior era obrigatório estender a javax.ejb.EJBObject Existe três tipos de Session Beans (Stateless , Stateful , Singleton) • Stateless : O Bean não mantem o estado e server qualquer cliente • Stateful : O Bean mantem o estado com um único cliente • Singleton : O Bean é compartilhado entre todos cliente, permite gerenciamento concorrente pelo bean ou container. As classes de implementação dos Session Beans são anotadas com @Stateful, @Stateless ou o @Singleton. Elas contem os seguintes elementos opcionais. Elemento Opcional Descrição description Descrição sobre o Session Bean mappedName Usado para especificar ao fornecedor informações de para deploy, o uso desse elemento não torna o EJB portátil name O EJB-name do bean. O padrão é o nome não qualificado da classe <?xml version="1.0" encoding="UTF-8"?> <ejb-jar version="3.1" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb- jar_3_1.xsd"> <enterprise-beans> <session> <ejb-name>StatefulSession1</ejb-name> <local>com.ivan.scbcd6.StatefulSession1Local</local> <ejb-class>com.core.StatefulSession1Bean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> </enterprise-beans> ... </ejb-jar> O <session-type> pode conter os seguintes valores Singleton, Stateful e Stateless Visualização dos Sessions Beans As anotações @LocalBean, @Local e @Remote são usada para especificar a disponibilidade dos session beans . @LocalBean : Essa anotação é usada na classe de implementação para disponibilizar uma visualização Local sem interface, está anotação não contem atributos. Ex: @LocalBean @Local : Essa anotação é usada para anotar uma interface que será implementada pela classe no Bean ou na própria classe do Bean para especificar a interface, disponibiliza uma visualização Local com interface, está anotação contem o atributo value que recebe um array de classes (Class[]). Ex : @Local({IStatefulSessionLocal 1.class , IStatefulSessionLocal 2.class} ) @Remote : Essa anotação é usada para anotar uma interface que será implementada pela classe no Bean ou na própria classe do Bean para especificar a interface, disponibiliza uma visualização Remota com interface, está anotação contem o atributo value que recebe um array de classes (Class[]). Ex : @Remote(value = {IStatefulSessionRemote1.class , IStatefulSessionRemote2.class} ) No descritor de implantação os elementos <local-bean>, <local> e <remote>, pode ser usado para especificar os diferentes tipo visualização dos Session Beans Exemplo de um descritor de implantação para a anotação @LocalBean Configuração no deployment descriptor (ejb-jar.xml) um EJB no-interface <ejb-jar .> <enterprise-beans> <session> <ejb-name>StatelessSessionBean </ejb-name> <local-bean />// equivalente @LocalBean <ejb-class>com.StatelessSessionBean</ejb-class> <session-type>Stateless</session-type> </session> </enterprise-beans> </ejb-jar> Ciclo de vida • @PostConstruct : Invocado depois da instancia ser criada e antes de ser usada, permite inicializações para o Bean. Disponível em Stateless, Statefull, Singleton e MDB. • @PreDestroy : Invocada quando a instancia do Bean está sendo retirada pelo Container, usado para liberar recursos. A classe do bean só pode definir um método PreDestroy. A especificação não garante que o @PreDestroy será invocado se o Bean lançar exceções de sistemas , ou o container travar ou timeout ocorrer quando o Stateful estivar passivado. Disponível em Stateless, Statefull Singleton e MDB • @PrePassivate : Invocado antes do Stateful ser passivado. o container pode decidir desativar uma instancia temporariamente se não estiver em uso, usado para liberar recursos e manipular, salvar dados de objetos que não podem ser serializados. Disponível em Stateful • @PostActivate : Invocado depois do Stateful ser ativado, o container pode decidir ativar novamente quando o cliente precisar dela, usado para realocar recursos e reconstituir objetos que não foram serializados na passivação. Disponível em Stateful Os métodos de ciclo de vida pode ser definidos na classe do EJB ou nas classes interceptadoras, podem ser público, protegido, privado ou protegido por pacotes deve ser void não ter nenhum parâmetro e não pode lançar exceções verificadas Exemplo de @PostConstruct @PostConstruct public void init() {..} <ejb-jar> <enterprise-beans> <session> <ejb-name>BeanEJB</ejb-name> <post-construct> <lifecycle-callback-method>init</lifecycle-callback-method> </post-construct> </session> </enterprise-beans> </ejb-jar> Exemplo de @PreDestroy @PreDestroy public void clear{…} <ejb-jar> <enterprise-beans> <session> <ejb-name>BeanEJB</ejb-name> <pre-destroy> <lifecycle-callback-method>clear</lifecycle-callback-method> </pre-destroy> </session> </enterprise-beans> </ejb-jar> Exemplo de @PrePassivate @PrePassivate public void passive(){…} <pre-passivate> <lifecycle-callback-method>passive</lifecycle-callback-method> </pre-passivate> Exemplo de @PostActivate @PostActivate public void active(){…} <post-activate> <lifecycle-callback-method>active</lifecycle-callback-method> </post-activate> Stateful Session Bean Concurrency Os Statefull são thread-safe por natureza , mesmo se o cliente chamar dois métodos de uma única vez, esses métodos serão executado de forma síncrona, ou seja, serão executado um por vez. Se anotarmos um Stateful com ConcurrencyManagement(ConcurrencyManagement Type.BEAN) o seu comportamento não muda, assim podemos concluir que concorrência gerenciado por Bean não se aplica a Steteful. Stateless Session Bean Concurrency Os Stateless são thread-safe por natureza , se o cliente chamar dois métodos de uma única vez, esses métodos será executada de forma assíncrona, porem cada um será executada em instancias diferentes do bean. Se anotarmos um Stateless com ConcurrencyManagement(ConcurrencyManagement Type.BEAN) o seu comportamento não muda, assim podemos concluir que concorrência gerenciado por Bean não se aplica a Stateless. Singleton Session Bean Concurrency Os Singleton Session Beans são thread-safe se a concorrência for gerenciada pelo Container se for gerenciada pelo Bean o Container não garante o acesso thread-safe e fica por obrigação do Bean fazer isto. Inicializações de Session Beans A especificação EJB 3.1 recomenda que qualquer código de inicialização de uma instância de bean de sessão deve ser colocada em um método anotado com a anotação @PostConstruct e não em um construtor do Bean. Injeção de dependência e Resource Lookup Tipo de Injeção de Dependência Exemplo Simple Environment Entries @Resource int myConfigParam = 5; @Resource public void setMyConfigParam(int inMyConfigParam) ... EJB References @EJB private MySuperBean mMyBean; @EJB public void setMyBean(MySuperBean inMyBean) ... Web Service References @WebServiceRef MyService serviceRefResource Manager Connection Factory Resources @Resource javax.sql.DataSource myAppDB; Resource Environment References @Resource SomeRsrcEnvRef myRsrcEnvRef; Message Destination References @Resource javax.jms.Queue workQueue; Persistence Unit References @PersistenceUnit(unitName="Wareh ouseManagement") EntityManagerFactory warehouseEMF; Persistence Context References @PersistenceContext(type=EXTEND ED) EntityManager myEntityMgr; UserTransaction Interface @Resource UserTransaction transaction; //Somente disponível para Session e MDB com contexto de transação gerenciados por Bean ORB References @Resource ORB corbaOrg; TimerService References @Resource TimerService mTimerService; EJBContext References @Resource SessionContext mSessionBeanContext; Exceções Exceções de aplicação (não RuntimeException ) não fazem com que uma transação seja revertida. Uma exceção de aplicativo é propagada ao cliente exatamente como ela está, quaisquer variáveis de instancia que você incluir nessas exceções devem ser serializáveis Exceções de sistemas (RuntimeException) quase sempre são empacotadas em uma EJBException. Isso significa que qualquer exceção que você chamar que seja ou estenda a RuntimeException será capturada pelo Container EJB e empacotada em um EJBException. Isso é importante para beans de sessão que interagem com entidades , pois todas as exceções chamadas pelas interface JPA são runtimes . O comportamento de uma exceção pode ser modicada usando @ApplicationException ou configurada no descritor de implantação Stateless Session Beans A característica fundamental dos Satateless é que eles não armazenam estado conversacional Beans de sessão sem informação de estado também podem ter um período tempo limite e pode ser removida pelo cliente, mais o impacto do tempo limite ou remoção é diferente daquele sobre um bean de sessão com estado. Uma operação com tempo limite ou remoção invalida a referencia do objeto EJB à aquele cliente, a instancia do bean não é destruída e fica livre para atender outras solicitações. Qualquer coisa que você referencia na variáveis de instancia devem ser genéricas , a única exceção é o SessionContext do JNDI ENC ou referencias do ambiente injetada diretamente na classe do Bean que não é compartilhado entre cliente Ciclo de vida. Existe dois estado para o cliclo de vida de um Stateless Session Bean Does Not Exist : Quando um bean está no estado Does Not Exist ele não é uma instancia na memoria do sistema. Em outras palavras, ele ainda não foi referenciado. Method-Ready Pool : O bean entra neste estado quando o Container precisa dele. Quando o servidor é iniciado pela primeira vez, ele pode criar algumas instancias de um bean sem informação de estado e colocá-las no Method-Ready Pool. Quando uma instancia migra do estado Does Not Exist para o Method-Ready Pool , três operações são realizadas nela. • O container chamar o Class.newInstance() e o construtor sem argumento roda. • O container injeta os recursos (ID) • O container chamar os métodos de callbacks (@PostConstruct ) Depois que uma instancia está no Method-Ready Pool ela está pronta para servir solicitações dos clientes, quando ela está servindo o cliente a instancia fica indisponível para uso dos outros objetos EJB, somente depois de terminar a solicitação, ela é desassociada do objeto EJB e retorna ao Method- Ready Pool . Quando o cliente precisa da referencia do bean usando ID ou JNDI. A referencia retornada não faz com que uma instancia do bean de sessão seja criada nem retirada do pool até um método ser invocada nela Instancia de bean passam do Method-Ready Pool para Does Not Exist quando o servidor não precisa mais dela, isto é, quando o servidor decide reduzir o tamanho total do Method-Ready Pool removendo uma ou mais instancia da memoria .O processo inicia quando o @PreDestroy é desencadeado Operações permitidas : Se um bean de sessão sem estado tenta executar uma operação não permitida, uma IllegalStateException será lançada Situações: Se invocar um método não permitido da interface SessionContext Se invocar um método não permitido da interface Timer ou TimerService Bean Method(s) Allowed Operations Constructor None. Dependency injection methods (setter methods). SessionContext: getEJBHome, getEJBLocalHome, lookup. JNDI Access: Available PostConstruct, PreDestroy methods (lifecycle callback methods). Métodos não usados do contexto (getRollbackOnly, setRollbackOnly, wasCancelCalled, getInvokedBusinessInterface , getCallerPrincipal, getCallerIdentity(), isCallerInRole(String), isCallerInRole(Identity), getEnvironment(), getMessageContext()) SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getEJBObject, getEJBLocalObject, lookup, getContextData, getTimerService, getUserTransaction (BMT only). JNDI Access: Available EntityManagerFactory: Accessible. Business method from any view or business method interceptor method. Métodos não usados do contexto ( getCallerIdentity(), isCallerInRole(Identity), getEnvironment(), getMessageContext()) SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getInvokedBusinessInterface, wasCancelCalled, getTimerService, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer and TimerService methods: Accessible. UserTransaction methods: Accessible (BMT only). Business methods from web service endpoint. Métodos não usados do contexto ( getCallerIdentity(), isCallerInRole(Identity), getEnvironment(),getInvokedBusinessInterface , wasCancelCalled) SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getTimerService, getMessageContext, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). MessageContext methods: Available JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer and TimerService : Accessible. UserTransaction methods: Accessible (BMT only). Timeout callback method. Métodos não usados do contexto ( getCallerIdentity(), isCallerInRole(Identity), getEnvironment(),getInvokedBusinessInterface , wasCancelCalled, getMessageContext()) . SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getTimerService, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer and TimerService methods: Accessible. UserTransaction methods: Accessible (BMT only). Além disso, os métodos da interface SessionContext getRollbackOnly e setRollbackOnly pode só ser chamado de dentro de um método em um contexto de transação, caso contrário uma IllegalStateException será lançada. Stateful Session Beans A ideia fundamental por trás dos Stateful é a necessidade de manter estado conversacional. Um bean de sessão que mantem o estado com um único cliente pelo tempo de vida da instancia do bean, no entanto isto tem um preço, a instancia não pode ser devolvida para o pool e reutilizada , ao contrario dos beans sem estado e consequentemente as instancia do beans com estado são retidas na memoria. Grande quantidade de usuário simultaneamente pode ter uma base de memoria significativa e o container utiliza técnicas de otimizaçãocoma a passivação e ativação para amenizar este problemas. Beans de sessão com informação de estado podem ter um período de tempo limite, se o cliente não conseguir utilizar o bean com informação de estado antes dele expirar, a instancia desse bean é destruída e a referencia ao objeto EJB é invalidada. O beans de sessão com estado são ideais para fluxo de trabalho de diversas etapas. Toda vez que você pesquisa um bean de sessão com informação de estado no JNDI, uma nova sessão é criada. A maior diferença entre o bean de sessão com informação de estado e os outro tipos de beans é que beans de sessão com informação de estado não necessariamente utilizam um pool de instancia. Observações • As variáveis de instancia para armazena o estado devem ser tipos primitivos ou objetos java serializáveis • O cliente pode utilizar o @Remove para destruir o bean, se o método remove não fosse uma opção o cliente não conseguiria dizer ao container para remover o bean, consequentemente cada instancia deveria esperar o tempo de expiração para se passivada e outro tempo de expiração para ser realmente destruída, em um sistema altamente concorrente isso poderia resultar em um drástico desempenho. • Possui callbacks adicionais • Pode possuir interfaces de negocio local e remota, não pode possuir uma interface de webservice • Não pode usar Timers • Você pode injetar um StatefullB em outro StatefullA, no caso o StatefullA é cliente do StatefullB, quando o container remover o StatefullA também irá remover o StatefullB. • Você pode mais não deve injetar um Statefull em um bean sem estado (Stateless, Servlets) pois estes compartilhar vários clientes e os dados dos Statefull não será íntegros. • Você pode injetar Stateless em Statefull Se o cliente estive ocioso , o container pode decidir passivar a instancia do bean, essencialmente passivação significa que o bean foi removido da memoria ativa e serializado e armazenado fisicamente temporariamente, se o cliente invocar o método novamente, o bean será ativado, se o cliente não invocar o método por um determinado período , o bean será destruído , se o cliente solicitar a remoção do bean, ele primeiro será ativado, para depois ser destruído Ciclo de vida O ciclo de vida das instâncias de um Stateful basicamente possui três estados, porem pode existir um comportamento especial caso ele implemente a interface javax.ejb.SessionSynchronization. Does Not Exist : Quando um bean está no estado Does Not Exist ele não é uma instancia na memoria do sistema. Em outras palavras, ele ainda não foi instanciado. Method-Ready Pool : O bean entra neste estado para servir solicitações de seus cliente. As instancias do bean saem do Method-Ready Pool e entram no Passivate ou no estado Does Not Exist. O Bean entra no estado Does Not Exist se o cliente invocar o método @Remote do EJB ou timeout expirar. Quando o timeout ocorrer o Container pode mais não é obrigatorio chamar o @PreDestroy.Um Statefull não pode expirar enquanto uma transação está em progresso. Passivate : Durante o ciclo de vida do Bean pode haver períodos de inatividade , quando a instancia do bean não esta servindo método do cliente, Para conservar os recursos, o container pode apassivar o bean, preservando seu estado conversacional e removendo a instancia do bean da memoria .Uma estado conversacional do bean pode consistir em valores primitivos, objetos serializáveis e os tipos especiais abaixo: • SessionContext • UserTransaction • javax.naming.Context (somente quando ele referencia o JNDI) • EntityManager • EntityManagerFactory • Referencias de recursos gerenciados (Ex: javax.sql.DataSource) • Referencias a outros EJB, incluindo remotas. Quando o container faz um solicitação em um EJB cujo bean está apassivado, o container ativa a instancia. Isso implica em deserializar a instancia do bean e reconstruir. O @PostActive é executado e o bean volta para o Method-Ready Pool A ativação de uma instancia de bean segue as regras de serialização padrão Java, independente de como os estado do bean real foi armazenado (arquivo, DB, cache, etc). A exceção a isso são campo transitórios . Na serialização Java campos transitorios são configurados com seus valores padrão. No EJB campos transitórios podem conter valores arbitrários quando o bean é ativado O container também pode mover a instancia do bean do estado Passivate para Does Not Exist se o bean expirar. Quando ocorre timeout no estado Passivate o método PreDestroy não é chamado. Exceção Quando uma exceção de sistema é chamada por um método do EJB, o container invalida o objeto EJB e destrói a instancia do bean. A instancia move-se diretamente para o estado Does Not Exist o método PreDestroy não necessariamente é chamado O Statefull é o único EJB que tem permissão para injetar um contexto estendido por meio da anotação @PersistenceContext e Statefull aninhados Locais compartilha o mesmo contexto de persistencia, o compartilhamento não acontece quando uma interface remota for aninhada NoSuchEJBException é lançado de um Statefull ao chamar um método cujo EJB tenha ultrapasso o tempo do timeout ou chamado o @remove @StatefulTimeout - Esta anotação é usada para informar ao Container o tempo máximo ocioso depois que uma instância ser usada. Ex: @StatefulTimeout(value = 2 , unit=TimeUnit.DAYS) Quando um session bean tem uma visão no-interface, os métodos de negócios são todos públicos na classe de implementação do bean Configuração no deployment descriptor (ejb-jar.xml) um EJB no-interface <ejb-jar> <enterprise-beans> <session> <ejb-name>StatefulSession4Bean</ejb-name> <local-bean /> <ejb-class>com.ivan.scbcd6.StatefulSession4Bean</ejb-class> <session-type>Stateful</session-type> </session> </enterprise-beans> </ejb-jar> Operações permitidas : Se um bean de sessão com estado tenta executar uma operação não permitida, uma IllegalStateException será lançada Situações: Se invocar um método não permitido da interface SessionContext Se invocar um método não permitido da interface Timer Bean Method(s) Allowed Operations Constructor None. Dependency injection methods (setter methods). SessionContext: getEJBHome, getEJBLocalHome, lookup. JNDI Access: Available PostConstruct, PreDestroy, PrePassivate, PostActivate methods (lifecycle callback methods). Métodos não usados do contexto (getRollbackOnly, setRollbackOnly, wasCancelCalled, getInvokedBusinessInterface , getCallerIdentity(), isCallerInRole(Identity), getEnvironment(), getMessageContext() , getTimerService()) SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getUserTransaction (BMT only). JNDI Access: Available Resource managers: Accessible. EntityManagerFactory: Accessible. Business method from any view or business method interceptor method. Métodos não usados do contexto ( getCallerIdentity(), isCallerInRole(Identity), getEnvironment(), getMessageContext() , getTimerService()) SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getInvokedBusinessInterface, wasCancelCalled, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer methods: Accessible. UserTransaction methods: Accessible (BMT only). afterBegin and beforeCompletion (when EJB implements the SessionSynchronization interface) or methods in the EJB annotated with @AfterBegin and @BeforeCompletion Métodos não usados do contexto ( wasCancelCalled, getInvokedBusinessInterface , getCallerIdentity(),isCallerInRole(Identity), getEnvironment(), getMessageContext() , getTimerService(), getUserTransaction()) ONLY AVAILABLE TO CMT EJBs! SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData, getRollbackOnly, setRollbackOnly. JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer methods: Accessible. afterCompletion (when EJB implements the SessionSynchronization interface) or method annotated with @AfterCompletion Métodos não usados do contexto ( wasCancelCalled, getInvokedBusinessInterface , getCallerIdentity(), isCallerInRole(Identity), getEnvironment(), getMessageContext() , getTimerService(),getRollbackOnly, setRollbackOnly, getUserTransaction()) ONLY AVAILABLE TO CMT EJBs! SessionContext: getBusinessObject, getEJBHome, getEJBLocalHome, getCallerPrincipal, isCallerInRole, getEJBObject, getEJBLocalObject, lookup, getContextData. JNDI Access: Available. Além disso, os métodos da interface SessionContext getRollbackOnly e setRollbackOnly pode só pode ser chamado de dentro de um método em um contexto de transação, caso contrário tão um IllegalStateException será lançada. Também não é permitido o uso de Timers em Stateful Singleton Session Beans A ideia fundamental dos Singleton Session Beans é a necessidade de compartilhar dados transientes entre todos os usuários de uma aplicação EJB. Este tipo de session bean surgiu na versão 3.1 da especificação Enterprise Java Beans. Pode ser usado como repositório ou para executar alguma coisa na inicialização da aplicação. Como Stateful e Stateless , os Singleton Session Bean pode ter três diferentes tipos de visualização , local no-interface view , local bussines interface view e remote bussines interface view Características de Singleton Session Bean : • Uma instancia existente por aplicação. Se a aplicação é distribuída então existe uma instancia por JVM • Pode ser compartilhada • Suporta acesso concorrente • Uma instancia somente é destruída quando a aplicação é finalizada. A instancia ainda sobrevive por exceções de sistema em método de negocio e de call-back • Pode manter o estado, porem não quando o Container desliga ou trava. Inicialização do Singleton Session Bean O Container pode decidir inicializar os Singleton Session Bean por demanda, porem podemos forçar uma inicialização antecipada (eager) usando a anotação @Startup ou configurando o DD com a propriedade <init-on-startup> true</init-on-startup> Não apenas podemos dizer ao Container inicializar um singleton session bean antecipadamente como também podemos dizer para o Container que um singleton session bean precisar se inicializado antes de outro singleton session bean, podemos usar a anotação @DependsOn ou configurar no DD a propriedade <depends-on> @Singleton @LocalBean @Startup @DependsOn("SingletonSessionBeanB") public class SingletonSessionBeanA{...} Neste exemplo o SingletonSessionBeanB é inicializados antes do SingletonSessionBeanA Quando um Container é desligado o SingletonSessionBeanA é destruído antes do SingletonSessionBeanB, isto acontece porque o Container tem que garantir que todos singleton session bean a quais o singleton session bean depende, deve está presente durante sua destruição Dependências cíclicas não são permitidas e pode causar erros de implantação. Ciclo de Vida As instâncias dos Singleton Session Beans são administradas pelo EJB Container. Devemos entender o de ciclo de vida desses objetos para utilizar corretamente a tecnologia EJB. Para entender mais facilmente o ciclo de vida das instâncias dos Singleton Session Beans, devemos sempre ter em mente que o EJB Container cria apenas uma instância de cada session bean desse tipo. O ciclo de vida do Singleton e quase idêntico a um Stateless com exceção de que a instância não é destruída quando o uma system exception é lançada do método de negocio ou call-back. O ciclo de vida das instâncias dos Singleton Session Beans possui dois estados. Does Not Exist Method-Ready Pool Não existe -> pronto Antes de ser criada, dizemos que uma instância de um Singleton Session Bean se encontra no estado NÃO EXISTE. Obviamente, nesse estado, uma instância não pode atender as chamadas dos clientes da aplicação. O EJB Container cria apenas uma instância para cada Singleton Session Bean. Por padrão, o EJB Container é quem decide quando a criação da instância de um Singleton Session Bean deve ser realizada. Contudo, é possível determinar que essa criação seja realizada na inicialização da aplicação através da anotação @Startup. Quando a instância de um Singleton Session Bean é criada, ela passa para do estado NÃO EXISTE para o estado PRONTO e pode atender as chamadas dos clientes da aplicação. Pronto -> não existe Quando a aplicação é finalizada, o EJB Container destrói as instâncias dos Singleton Session Beans. Dessa forma, elas passam do estado PRONTO para o NÃO EXISTE. Callbacks @PostConstruct e @PreDestroy ambos quando transações são gerenciadas pelo Container (CMT) somente são permitido os seguintes atributos transacionais: REQUIRED , REQUIRES_NEW e NOT_SUPPORTED Concorrência Enquanto acesso concorrente em Stateless e Stateful e controlado pelo Container, Singleton permite um maior controle nesta área. Um Singleton Session Bean suporta acesso concorrente. Em outras palavras, a instância de um Singleton Session Bean pode processar diversas chamadas a métodos de negócio simultaneamente. O modo de gerenciamento de concorrência pode ser configurados usando a anotação @ConcurrencyManagement ou <concurrency-management-type> no elemento ejb-jar.xml deployment descriptor. Está anotação tem um único elemento value Há dois modos de gerenciamento de acesso à instância de um Singleton Session Bean: • ContainerManaged Concurrency (CMC) este é o default • BeanManaged Concurrency (BMC) O modo padrão de gerenciamento é o CMC. Opcionalmente, podemos declarar o modo CMC através da anotação @ConcurrencyManagement. Ex: @Singleton @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) ContainerManaged Concurrency CMC O Container gerencia a concorrência , No modo CMC, todo método de negócio é associado ao Read Lock ou ao Write Lock. @Lock Read Lock : ser executadas em threads simultaneamente Write Lock : somente execução de uma thread de cada vez. Regras referente a herança • O padrão é @Lock(LockType.WRITE) tanto em nível de classe quanto a nível de método. • A subclass pode anotar métodos sobrescrevendo com a anotação @Lock, se não anotar o padrão @Lock(LockType.WRITE) é implícito Ex: @Singleton @Singleton @Lock ( LockType . WRITE ) Ou @Lock ( LockType . READ ) @AccessTimeout No padrão LockType.WRITE Threads não são permitidas executar até o método ser desbloqueado, com exceção quando especificamos um timeout usando a anotação @AccessTimeout, pois ela define um tempo limite para o bloqueio e caso o tempo é ultrapassado uma javax.ejb.ConcurrentAccessTimeoutException é lançada. Está anotação pode ser usada tanto em nível de classe quanto a nível de método, quando usado no nível de método a anotação tem precedência. Regras : • The @AccessTimeout annotation on methods in the superclass is inherited to methods defined in the superclass • Está anotação não herda os sobrescrito na subclasse. A anotação tem dois elementos value : valor do tempo unit : unidade de medida Ex: @Singleton @LocalBean @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) @Lock(LockType.WRITE) @AccessTimeout(value=3 , unit=TimeUnit.SECONDS) public class PaymentEJBSingleton {...} Por padrão, no CMC, os métodos são associadosao Write Lock. Opcionalmente, podemos declarar o tipo de Lock através da anotação @Lock. Mas, lembre-se que não é necessário pois o Write Lock é associado aos métodos de negócio por padrão. A anotação @Lock pode ser aplicada na classe do session bean ou diretamente nos métodos de negócio. As seguintes observações se aplica a um métodos de um sinleton session bean sendo chamados por um outro método no sinleton session bean: • Se o método chamando detém o bloqueio WRITE lock na mesma thread e chama um método com o bloqueio READ lock, então a chamada procede imediatamente, sem soltar o original WRITE lock. • Se o método chamando detém o bloqueio WRITE lock na mesma thread e chama um método com o bloqueio WRITE lock, então a chamada procede imediatamente, sem soltar o original WRITE lock • Se o método chamando detém o bloqueio READ lock na mesma thread e chama um método com o bloqueio READ lock então a chamada procede imediatamente, sem soltar o original READ lock. • Se o método chamando detém o bloqueio READ lock na mesma thread e chama um método com o bloqueio WRITE lock, então uma IllegalLoopbackException pode ser lançada(no jboss e glassfish não lançou Exception). BeanManaged Concurrency (BMC) No modo BMC, o Container permite acesso concorrente e o controle de concorrência deve ser implementado dentro dos métodos de negócio pelo desenvolvedor. Você pode utilizar a instrução synchronized ou os recursos do pacote java.util.concurrent. Para isso, você precisa ter bons conhecimento de programação concorrente. Operações permitidas : Se um bean de sessão Singleton tenta executar uma operação não permitida, uma IllegalStateException será lançada Situações: Se invocar um método não permitido da interface SessionContext Se invocar um método não permitido da interface Timer ou TimerService Bean Method(s) Allowed Operations Constructor None. Dependency injection methods (setter methods). SessionContext: lookup. JNDI Access: Available PostConstruct, PreDestroy, PrePassivate, PostActivate methods (lifecycle callback methods). SessionContext: getBusinessObject, lookup, getContextData, getTimerService, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer service & methods: Accessible. UserTransaction methods: Accessible (BMT only). Business method from any view or business method interceptor method. SessionContext: getBusinessObject, getCallerPrincipal, isCallerInRole, lookup, getContextData, getInvokedBusinessInterface, wasCancelCalled, getTimerService, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer service & methods: Accessible. UserTransaction methods: Accessible (BMT only). Business methods from web service endpoint. SessionContext: getBusinessObject, getCallerPrincipal, isCallerInRole, lookup, getContextData, getTimerService, getMessageContext, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). MessageContext methods: Available JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer service & methods: Accessible. UserTransaction methods: Accessible (BMT only). Timeout callback method. SessionContext: getBusinessObject, getCallerPrincipal, isCallerInRole, lookup, getContextData, getTimerService, getUserTransaction (BMT only), getRollbackOnly (CMT only), setRollbackOnly (CMT only). JNDI Access: Available Resource managers: Accessible. Other EJBs: Accessible. EntityManagerFactory: Accessible. EntityManager: Accessible. Timer service & methods: Accessible. UserTransaction methods: Accessible (BMT only). Além disso, os métodos da interface SessionContext getRollbackOnly e setRollbackOnly pode só pode ser chamado de dentro de um método em um contexto de transação, caso contrário tão um IllegalStateException será lançada. Message Drive Beans – MDB O bean baseado em mensagem foi introduzido no EJB 2.0 para suportar o processamento de mensagens assíncronas de um provedor JMS. O EJB 2.1 expandiu a definição do bean baseado em mensagem de modo que ele pudesse suportar qualquer sistema de mensagens, não só JMS, mais outros sistemas por meio do JCA. O EJB 3 não expande o conjunto de recursos da versões da especificação anterior, mais simplifica a configuração com o uso de anotações A especificação garante que todos fornecedores suporta um provedor JMS diretamente ou por meio do JCA. O JMS é uma API para envio/recebimento de mensagens assíncronas que não exige um Contâiner EJB e é independente do fornecedor que pode ser utilizada para acessar sistemas de mensagens corporativos. Sistema de mensagens corporativos, conhecidos como MOM (Middleware Orientado à Mensagem) facilitam a troca de mensagens entre aplicativos de software por uma rede. Exemplo de MOM são JBossMQ, MQSeries , JMS WebLogic, SonicMQ e o Sun ONE Message Queue. Uma aplicação JMS pode ser construída programaticamente obtendo os recursos por lookup e utilizando a API JMS ou com a facilidade dos Message Driven Beans (MDB), onde é possível injetar os recursos necessários e as facilidades do Container (segurança, transação, etc) Aplicativos que usam o JMS são chamados de cliente JMS, e o sistema de mensagens que trata o roteamento e a entrega das mensagens é chamado de provedor JMS (MOM).Um cliente JMS que envia uma mensagem é chamado de produtor, e um cliente JMS que recebe a mensagem é chamada de consumidor. Um único cliente pode ser tanto um produtor como um consumidor. A especificação EJB 3.1 afirma explicitamente que o MDB não deve usar a API JMS (método acknowledge)para confirmação de mensagem. Esta é uma tarefa que está a ser tratado pelo Container EJB Modelo de sistema de mensagem JMS O JMS fornece dois tipos de modelo de mensagem : publicação e assinatura (pub/sub) e ponto a ponto( P2P ou PTP) Publicação e assinatura No sistema de mensagem publicação e assinatura , um produtor pode enviar uma mensagem a muitos consumidores por meio de um canal virtual chamado Topic. Os consumidores podem se inscreverem em um tópico e quaisquer mensagem endereçadas ao tópico são entregues a todos os consumidores registrado neste tópico. Este modelo é um modelo baseado em push, no qual as mensagens são transmitidas automaticamente ao consumidores sem que estes precisem requisitar ou consultar novas mensagens. Por padrão as assinaturas não são duráveis, ou seja, se no momento da entrega um consumidor que se registrou no tópico estiver indisponível ele não receberá a mensagem em nenhum momento posterior, porem existe a possibilidade do cliente JMS que utiliza pub/sub estabelecer assinaturas duráveis, desta forma o provedor JMS mantém a mensagem até o consumidor ficar disponível para receber a mensagem. Ponto a ponto O modelo de sistema de mensagem ponto a ponto permite que cliente JMS enviem e recebam mensagens síncronas e assíncronas via canais virtuais conhecido como Queue, este modelo é tradicionalmente baseado em push ou pull, em que as mensagens são solicitadas a partir da fila em vez de adicionadas ao cliente automaticamente. Uma fila pode ter múltiplos receptores, mais somente um receptor pode receber cada mensagem, e a mensagem é escolhida de forma aleatória. O provedor JMS cuida da distribuição das mensagens entre os cliente JMS, assegurando que cada mensagem seja consumida somente por um cliente JMS. API Java Message Service Para enviar uma mensagem JMS precisamos de uma conexão com o provedor JMS e de um endereço de destino para a mensagemjavax.jms.ConnectionFactory Uma fabrica de conexões JMS utilizado para criar o Connection que é uma conexão real com um provedor JMS. javax.jms.Connection Uma coneão real com um provedor JMS. O método connect.createConnection(true , 0) cria um javax.jms.Session, o primeiro argumento identifica se a sessão é transacional ou não e o segundo argumento identifica o modo de reconhecimento da mensagem. esse argumento são usados pela API do JMS, mais ignorados quando usado pelo Container EJB, porque o Container gerencia a transação e o modo de reconhecimento de qualquer recurso JMS obtido através do JNDI ENC. javax.jms.Session Permite agrupar as ações de envio e recebimento de mensagem. O objeto Session utilizam um modelo de um único thread, que proíbe acesso com corrente a um único Session a partir de múltiplas threads, se você deseja produzir e consumir mensagens utilizando multithreading, você deverá criar um objeto Session diferente para cada thread. javax.jms.Queue : Endereço de destino javax.jms.Topic : Endereço de destino javax.jms.MessageProducer : este objeto é criado pela Session e é utilizado para enviar mensagens ao destino especificado pelo Topic ou Queue . javax.jms.MessageConsumer :este objeto é criado pela Session e é utilizado para consumir mensagens ao destino especificado pelo Topic ou Queue, possui três métodos convenientes para receber mensagens. receive() : bloqueia a thread até o recebimento de uma mensagem. receive(long timeout) : bloqueia a thread até o recebimento da mensagem ou timeout. receiveNoWait() : lê mensagem se já existir, caso contrário, não bloqueia a thread Mensagens JMS : javax.jms.TextMessage com o método setText(String message) javax.jms.MapMessage com o método setDouble(String key, Double message), setInt, etc… javax.jms.ObjectMessage com o método setObject(Object obj) , este objeto deve ser Serializado. javax.jms.BytesMessage javax.jms.StreamMessage Tipo de Mensagem No JMS, uma mensagem é um objeto Java formado por três partes:, cabeçalho, propriedades e corpo. O cabeçalho é composto de meta-dados e das informações de roteamento e entrega. Uma dessas informações é o JMSReplyTo, um remetente da mensagem pode configurar o atributo JMSReplyTo como um destino qualquer acessível a seu provedor JMS, esse destino é necessário quando você precisa de um feedback sobre o processamento das mensagens, por exemplo você pode configurar o JMSReplyTo para uma fila, no qual o processamento das mensagens resultou em algum erro. Produtor Produtor pode ser criado programaticamente sem o uso do Container ou dentro do Container EJB. @Resource(mappedName = "jms/TopicConnectionFactory") ConnectionFactory connectionFactory; @Resource(mappedName = "jms/QueueDestination") Queue destination; public void enviarMensagem() { try { // Obtem recursos necessarios...e a sessao a partir de uma conexao Connection conn = connectionFactory.createConnection(); Session session = conn.createSession(true, 0); // Cria mensagem TextMessage msg = session.createTextMessage(); msg.setText("Minha mensagem"); // Enviar mensagem MessageProducer producer = session.createProducer(destination); producer.send(msg); conn.close(); } catch (JMSException theException) { theException.printStackTrace(); } } Consumidor Consumidor pode ser criado programaticamente sem o uso do Container ou dentro do Container EJB. Beans de sessão podem mais não devem receber mensagens. Ex : Session Bean consumindo mensagem. @Resource(mappedName = "jms/TopicConnectionFactory") ConnectionFactory connectionFactory; @Resource(mappedName = "jms/QueueDestination") Queue destination; public void recuperarMenssgem() { try { // Obtem recursos necessarios...e a sessao a partir de uma conexao Connection conn = connectionFactory.createConnection(); Session session = conn.createSession(true, 0); // Recebe mensagem MessageConsumer consumer = session.createConsumer(destination); TextMessage msg = (TextMessage) consumer.receive(); conn.close(); } catch (JMSException theException) { theException.printStackTrace(); } } O método MessageConsumer.receive(), bloqueia a thread até a mensagem tornar-se disponível . Se a mensagem nunca for entregue, a thread permanecerá bloqueada infinitamente! Se ninguém enviar uma mensagem à fila, o MessageConsumer simplesmente espera eternamente, existe outras versões do método receive() menos perigosa, por exemplo receive(long timeout) permite especificar um tempo no qual o MessageConsumer deve parar de bloquear a thread e há também o receiveNoWait(), que verifica uma mensagem e retorna null se nenhuma estiver esperando. Mesmo assim não escreva código complexo para tentar forçar os beans de sessão a receber mensagem. Ex: Consumidor sem uso Container EJB. public class MyMessageListener implements MessageListener { public void onMessage(Message message) { // do something... } } public void main() { // Obtem recursos necessarios..Obtem sessao a partir de uma conexao Connection conn = connectionFactory.createConnection(); Session session = conn.createSession(true, 0); // Seta listener para receber mensagem MessageConsumer consumer = session.createConsumer(destination); consumer.setMessageListener(new MyMessageListener()); conn.start(); } Ex : Consumidor com MDB @MessageDriven(activationConfig = {@ActivationConfigProperty(propertyName = "destinationType", propertyValue="javax.jms.Topic")}, mappedName = "jms/TopicDestination", name="TopicListener1") public class TopicListenerEJB implements MessageListener { @Override public void onMessage(Message arg0) {} } Usaremos o descritor de implantação para cria três EJB com a mesma classe de implantação <ejb-jar> <enterprise-beans> <message-driven> <ejb-name>TopicListener1</ejb-name> <ejb-class>com.scbcd6.ejbs.TopicListenerEJB</ejb-class> </message-driven> <message-driven> <ejb-name>TopicListener2</ejb-name> <ejb-class>com.scbcd6.ejbs.TopicListenerEJB</ejb-class> </message-driven> <message-driven> <ejb-name>TopicListener3</ejb-name> <ejb-class>com.scbcd6.ejbs.TopicListenerEJB</ejb-class> </message-driven> </enterprise-beans> </ejb-jar> Message Driven Beans MDB MDBs são identificados utilizando-se a anotação @javax.ejb.MessageDriven ou o elemento <message-driven> no descritor de implantação. MDBs baseados em JCA não necessariamente utiliza o JMS como serviço de mensagem. Ciclo de vida Assim como beans de sessão tem ciclo de vida, os MDB também tem, O ciclo de vida da instancia MDB tem dois estados : Does Not Exist e Method-Ready Pool Does Not Exist Quando uma instancia MDB está no estado Does Not Exist, ela não é uma instancia na memória do sistema. Em outras palavras, ele ainda não foi instanciado. Method-Ready Pool Instancia MDB entram no estado Method-Ready Pool quando o Container precisa delas. Quando o servidor EJB é iniciado pela primeira vez, ele pode criar algumas instancia e fazer com que elas entrem no estado Method-Ready Pool (O comportamento real depende do fornecedor), quando o número de instancia MDB que tratam mensagens entrantes for insuficientes, mais instancias podem ser criadas e adicionadas ao pool. Quando uma instancia entra neste estado, três operações são realizadas, a instancia do bean é criada invocando o Class.newInstance(), o container injeta os recursos via anotação ou descritor de implantação e por fim o container invocar os métodos de callback do ciclo de vida se houver. Quando uma mensagem é delegada a uma instancia pelo Container, a instanciaMDB MessageDrivenContext muda para refletir o novo contexto da transação. Durante os métodos de eventos do ciclo de vida @PreDestroy e @PostConstruct , o MessageDrivenContext e o acesso ao JNDI ENC continuam disponível à instancia do bean. Características do MDB Algumas características do MDB • Mensagens enviadas para o bean são invisíveis aos clientes. No caso do uso de JMS, um cliente só sabe sobre a fábrica de conexões e um destino fila ou tópico. Ele não tem conhecimento do receptor das mensagens que produz. • Mensagens enviadas para o bean não tem estado conversacional relacionada a um cliente específico. Informações de estado podem ser armazenados em variáveis de instância, mas não está relacionada a um cliente específico. • Processamento de mensagens assíncronos . Clientes enviar mensagens para uma fila ou tópico e continua sem esperar por respostas. As mensagens são processadas em algum momento no futuro, por uma ou mais instâncias de mensagem de beans. Os mecanismos normais de processamento de mensagens não gera qualquer resposta. • Várias instâncias da mesma mensagem dirigida bean pode processar mensagens em paralelo Alguns desvantagens do MDB • Requer um container EJB. • Não pode "agir" a menos que uma mensagem é recebida. • Só pode ouvir as mensagens para um único destino. • Nenhum modo de colocar uma mensagem recebida de volta na fila a menos fazendo com que a transação sofra rollback. • Não é possível enviar as exceções de volta para os clientes. • Não é possível manter o estado relacionada com o cliente. Um MDB pode receber uma mensagem de qualquer cliente enviado para o destino do bean. • Não há meios padronizados de englobar informações de segurança em mensagens para MDB • ordenação mensagem não é garantida. Message Driven Beans e o Container • A mensagem do cliente pode ser entregue a qualquer instância de um MDB. • A classe que implementa MDB deve ser anotado com a anotação @MessageDriven ou definido no descritor de implementação ejb-jar.xml. • Um MDB deve utilizar um dos seguintes meios para especificar o tipo de mensagens que ele usa. No caso de JMS, esta é a interface javax.jms.MessageListener. • Implementar o próprio message listener interface. • Usar messageListenerInterface da anotação @MessageDriven. • Usar o elemento <messaging-type> no ejb-jar.xml. • Se um MDB implementa mais de uma interface diferente Serializable, Externalizable e as interfaces no pacote javax.ejb, então a interface listener de mensagens devem ser especificados usando a anotação @ MessageDriven ou descritor de implementação ejb-jar.xml. • A classe de um MDB deve se • Ser public, mas não deve ser final ou abstract. • Ter nenhum construtor ou um construtor sem argumentos. • Não deve definir o método finalize. • Métodos de listener de MDB deve ser público, mas não deve ser final ou estatic. • MDB pode usar os mecanismos de injeção de dependência e de lookup. • Apenas PostConstruct PreDestroy são suportados para o ciclo de vida de MDBs. • Método de negócios, método de timeout e eventos de interceptores ciclo de vida interceptores pode ser aplicado a MDB • Invocações de um MDB é serializado pelo contêiner. Além disso, podem existir várias instâncias de uma classe MDB processando mensagens em paralelo. MDB não precisa considerar invocações de reentrada. • Mensagens são entregue de forma aleatória. • MDB usando JMS não deve usar a API JMS (acknowledgement ) para reconhecimento de mensagem. Objeto do contexto em beans baseados em mensagens Beans baseados em mensagens também têm um objeto do contexto que é semelhante em funcionalidade àquela do SessionContext, este objeto pode ser injetado utilizando a anotação @Resource. O javax.ejb.MessageDrivenContext simplesmente e extende a javax.ejb.EJBContex e não adiciona nenhum método novo. Somente os métodos transacionais do qual o MessageDrivenContext é herdado estão disponível para os beans baseados em mensagens, chamar qualquer outro método , lança uma RuntimeException. MDBs Baseados em Conector A partir do EJB 2.1 com JCA 1.5 MDBs podem suportar qualquer tipo de mensagens que contem um adaptador de recurso. Um adaptador de recurso pode ser um jar, war , etc. Ele possui uma interface de mensagem análago à javax.jms.MessageListener Ex: public class MyMessageHandler implements com.vendorx.EmailListener { public void onEmailMessage(com.vendorx.Message) { // do something... } } Configurações de Mensagens @ActivationConfigProperty é utilizado para configurar um MDB e possui os atributos propertyName e propertyValue. ActivationConfigProperty é um elemento do atributo activationConfig da anotação @MessageDriven @MessageDriven(activationConfig ={ @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue") }, mappedName = "jms/QueueDestination", name="QueueListener1") public class QueueListenerEJB implements MessageListener {...} O EJB 3.0 define um conjunto de propriedade fixas para MDBs baseados no JMS, essas propriedades são acknowledMode, messageSelector, destinationType e subscriptionDurability. Nome da propriedade Descrição messageSelector Um MDB pode declarar um seletor de mensagem, os seletores de mensagens permite que um MDB seja mais seletivo em relação as mensagens que ele recebem, pois em um fila podemos ter mensagens de canceladas, error, entre outros, esses seletores permitem criar MDBs específicos para cada tipo de mensagem em um mesmo destino. Os seletores utilizam propriedades Message com os critérios na expressões condicionais, essas propriedade podem ter um valor String ou um dos vários valores primitivos. O nome das propriedades, com seus valores e regras de conversão, é estritamente definido pelo JMS. acknowledMode Um reconhecimento JMS significa que o cliente JMS notifica o provedor JMS quando uma mensagem é recebida. No EJB, é responsabilidade do Container EJB enviar um reconhecimento quando ele recebe a mensagem. Reconhecer a mensagem é informar ao provedor JMS de que um container MDB recebeu e processou a mensagem. Dois valores podem ser especificados para o modo de reconhecimento: Auto-acknowledge (padrão) e Dups-ok-acknowledge. Auto-acknowledge instrui o Container enviar o reconhecimento imediatamente quando a mensagem for processada, Dups-ok- acknowledge instrui o container a não enviar o reconhecimento imediatamente, dependendo da demora do reconhecimento o provedor JMS não saberá se a mensagem foi entregue e poderá realizar uma entrega nova entrega , duplicando a mensagem e seu MDB deve saber tratar isto. Tendo dito tudo isso, o modo de reconhecimento é ignorado na maioria das vezes, a menos que o MDB seja executado com transações gerenciadas por bean ou com atributos de transação gerenciado por container como NotSupported.Em todos os outros casos, as transações são gerenciadas pelo container e o reconhecimento acontece dentro do contexto transacional. Se a transação foi bem sucedida, a mensagem será reconhecida, se a transação falhar, a mensagem não será reconhecida. Ex: @ActivationConfigProperty( propertyName = "acknowledMode", propertyValue = "Dups-ok-acknowledge"), subscriptionDurability Indica se a assinatura tópico é durável ou não. A assinatura durável permitir que um MDB receba mensagens publicadas enquanto estiver indisponível. Os valores possíveis são Durable ou NonDurable, padrão: NonDurable . Quando o tipo de destino é uma Queue, a durabilidade não é um fator relevante devida a natureza dos sistemas de mensagens baseado em fila. destinationType Destino da mensagem a partir da qual o MDB recebe mensagens. O valor deve ser javax.jms.Queue ou javax.jms.Topic para um bean acionado por mensagens JMS. Exemplo de MDB @MessageDriven(activationConfig= { @ActivationConfigProperty( propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty( propertyName = "messageSelector", propertyValue = "MessagFormt = '3' '") @ActivationConfigProperty( propertyName = "acknowledMode", propertyValue = "Dups-ok-acknowledge"), @ActivationConfigProperty( propertyName = "subscriptionDurability", propertyValue = "Durable"), }) public class MessageBean implements MessageListener { public void onMessage(Message message) { // do something... } } Ou com Descritor de implantação <ejb-jar> <enterprise-beans> <message-driven> <ejb-name>MyMessageBean</ejb-name> <ejb-class>br.MyMessageBean</ejb-class> <messaging-type>javax.jms.MessageListener</messaging-type> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destionation-type> <activation-config> <activation-config-property> <activation-config-property-name>destinationType</activation-config-property-name> <activation-config-property-value>javax.jms.Queue</activation-config-property-value> </activation-config -property> <activation-config-property> <activation-config-property-name>messageSelector</activation-config-property-name> <activation-config-property-value>MessagFormt='3'</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> </enterprise-beans> </ejb-jar> O elemento <activation-config> em que a configuração de mensagens é especificada aparece no elemento <message-driven> . Link de Mensagem A vinculação de mensagem é um recurso que permite que as mensagens sendo enviadas por qualquer enterprise bean seja roteadas para um bean baseado em mensagem especifico na mesma implantação.Com isso é possível orquestrar um fluxo de mensagens entre componentes no mesmo aplicativo A especificação EJB 3.0 não tem nenhuma anotação para ativar a vinculação da mensagem, portando teremos que criar um descritor de implantação parcial para ativar este recurso. <ejb-jar> <enterprise-beans> <message-driven> <ejb-name>MyMessageBean</ejb-name> <ejb-class>br.MyMessageBean</ejb-class> <message-destination-ref>//Usado somente para fazer a vinculação da msg, n existe @ <message-destination-ref-name>jms/TicketTopic</message-destination-ref-name> <message-destination-type>javax.jms.Topic</message-destination-type> <message-destination-usage>Produces</message-destination-usage> <message-destination-link>Distribuidor</message-destination-link> </message-destination-ref> </message-driven> <message-driven> <ejb-name>MyMessageMDB</ejb-name> <message-destination-link>Distribuidor</message-destination-link> </message-driven> </enterprise-beans> <assembly-descriptor> <message-destination> <message-destination-name>Distribuidor</message-destination-name> <mapped-name>jms/Dest</mapped-name> </message-destination> </assembly-descriptor> </ejb-jar> Para vincular as mensagens de saídas enviada pelo MyBeanEJB com as mensagens entrantes consumidas e processadas pelo MDB do MyMessageMDB, precisamos definir elementos <message- destination-link> do descritor de implantação . O elemento <message-destination-link> é definido pelo elemento <message-destination-ref> do MyBeanEJB. O MyMessageMDB também declara o elemento <message-destination-link> .Esses dois elementos referenciam o mesmo lógico declarado no descritor de assembly. O elemento <message-destination-ref> declara o destino ao qual um enterprise bean envia ou recebe mensagens, quando o <message-destination-ref> inclui um elemento <message-destination-link>, ele quer dizer que os remetentes e os receptores da mensagem compartilharão um destino lógico no descritor assembly. MDBs sempre consumem mensagens a partir do destino defino pelo elemento <message-destination- link> definido diretamente sob o elemento <message-driven>, mais eles também pode produzir mensagens que são enviadas a um destino lógico de mensagens se eles utilizarem a API de mensagem descrita pelo próprio elemento <message-destination-ref>. Message Driven Beans e Exceções A especificação EJB 3.1 faz as seguintes recomendações sobre exceções e Beans controlados por mensagem • Método de Message listener em MDB agora deve lançar uma RemoteException. • MDB não deve lançar RemoteException de qualquer método. Exceções de RuntimeException fará com que o Container destrói a instancia do MDB, se o MDB lançar uma exceção de tempo de execução e usa transações gerenciadas por bean (BMT), o Container não deve reconhecer a mensagem como entregue. • Métodos de listener de mensagem pode lançar exceções de aplicação. Tais exceções são propagadas para o adaptador de recursos Exceções em método timeout e de call-back O forma que o Container manipula exceções de métodos timeout e de callback , são comum para todos os tipo de EJB. Message Driven Beans e Segurança Verificar.. Como o sistema de mensagem é inerentemente desacoplado e assíncrono, as transações e o contexto de segurança do remetente não são propagada ao receptor. A especificação EJB 3.1 não especifica se ou não um Principal estará disponível quando os métodos listener de um MDB são invocados. Aplicando a anotação @RunAs para um MDB fará com que métodos de listener de mensagem e os métodos de timeout é executado com uma função de segurança específica. Message Driven Beans e Transação O contexto transacional é iniciado explicitamente pelo container e pode ter uma transação distribuída com o provedor JMS. Se transação falhar durante o recebimento da mensagem, a mensagem é reentregue pelo MOM. Também é possível iniciar o contexto transacional programaticamente pelo Bean usando a javax.jta.UserTransaction Normalmente existem duas transações diferentes associadas a cada mensagem enviada para um MDB; uma transação em que o produtor envia a mensagem para o destino e uma transação em que o MDB recebe a mensagem. Nesta seção, vamos nos preocupar principalmente com o último transação Método Contexto Transacional PostConstruct life-cycle methods Indefinido PreDestroy life-cycle methods Indefinido Listener method(s) Conforme especificado por anotações ou no ejb-jar.xml REQUIRED ou NOT_SUPPORTED Timeout callback methods Conforme especificado por anotações ou no ejb-jar.xml REQUIRED, REQUIRES_NEW ou NOT_SUPPORTED Constructor Indefinido Dependency injection setter methods Indefinido MessageDrivenContext setter method Indefinido Atributos transacionais No MDB com transações gerenciadas pelo container (CMT), métodos que suportam as transações devem usar os seguinte atributos de transações. • Método de Listener de mensagem : REQUIRED ou NOT_SUPPORTED • Método de callback e timeout : REQUIRED, REQUIRES_NEW ou NOT_SUPPORTED Operações permitidas : Se um Message Driven Beans tenta executar uma operação não permitida, uma IllegalStateException será lançada Situações: Se invocar um método não permitido da interface MessageDrivenContext Se invocar um método não permitido da interface Timer ou TimerService Métodos do Bean Operações permitidas Constructor nenhuma Dependency injection methods (setter methods). MessageDrivenContext: lookup. JNDI Access: Available PostConstruct and PreDestroy methods (lifecycle callback methods). MessageDrivenContext: lookup, getContextData, getTimerService, getUserTransaction (BMT only). JNDI Access: Available
Compartilhar