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
Um EJB não deve usar campos estáticos
graváveis.
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.
Um EJB não deve usar a funcionalidade
de AWT para gerar a saída para um
monitor ou obter entrada de um teclado.
Um EJB não deve acessar arquivos e
diretórios no sistema de arquivos
diretamente.
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.
Ele pode atuar como um cliente socket de
rede.
Motivation
Garantir a consistência em um ambiente
distribuído.
Não vai funcionar em um ambiente
distribuído.
Servidores geralmente não permitem o
acesso ao teclado ou a tela de um
programa aplicativo.
Os componentes de negócios deve usar
uma API do gerenciador de recursos, tais
como JDBC, para acessar os dados
persistentes.
Conflitos com os deveres do servidor de
aplicativos.
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.
Um EJB não deve tentar gerenciar threads
ou grupos de threads.
Um EJB não deve tentar ler ou escrever
um descritor de arquivo diretamente.
Um EJB não deve tentar obter as
informações de política de segurança para
uma fonte de código particular.
Um EJB não deve tentar carregar uma
biblioteca nativa.
Um EJB não deve tentar burlar as regras
da linguagem de programação Java ao
acessar pacotes e classes.
Um EJB não deve tentar definir uma
classe em um pacote.
Um EJB não deve tentar acessar ou
modificar os objetos de configuração de
segurança (Policy, Security, Provider,
Signer e Identity).
Um EJB não deve tentar usar a subclasse
ou recursos objeto de substituição do
Protocolo de serialização Java.
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.
Poderia comprometer a segurança.
Interfere com a capacidade do container
para gerenciar o ambiente de tempo de
execução.
Interfere com a capacidade do container
para gerenciar o ambiente de tempo de
execução.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
Poderia comprometer a segurança.
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
Java Persistence 2.0
Session beans local/no interface client view.
Session beans 3.0 remote client view.
Session beans 2.x remote client view.
Session beans exposed as JAX-WS web
service endpoints.
Session beans exposed as JAX-RPC web
service endpoints.
EJB timer service.
Asynchronous invocation of session beans.
Full EJB 3.1 API
Disponível
Disponível
Disponível
Disponível
Disponível
EJB 3.1 Lite API
Disponível
Disponível
Não Disponível
Não Disponível
Não Disponível
Disponível
Não Disponível
Disponível
Disponível
Não Disponível
Não Disponível
RMI-IIOP interoperability.
Message driven beans.
Interceptors
Bean and container managed transactions.
Declarative and programmatic security.
Embeddable API.
Disponível
Disponível
Disponível
Disponível
Disponível
Disponível
Não Disponível
Não Disponível
Disponível
Disponível
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
- Remote
: é acessado na mesma aplicação , mesma JVM Ex: Web Componente e EJBs.
: é 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 componentes oferecendo
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 (sem constructor 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
description
mappedName
name
Descrição
Descrição sobre o Session Bean
Usado para especificar ao fornecedor
informações de para deploy, o uso desse
elemento não torna o EJB portátil
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/ejbjar_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
Simple Environment Entries
EJB References
Web Service References
Resource Manager Connection
Factory Resources
Resource Environment References
Message Destination References
Persistence Unit References
Exemplo
@Resource
int myConfigParam = 5;
@Resource
public void setMyConfigParam(int
inMyConfigParam)
...
@EJB private MySuperBean
mMyBean;
@EJB
public void setMyBean(MySuperBean
inMyBean)
...
@WebServiceRef MyService
serviceRef
@Resource javax.sql.DataSource
myAppDB;
@Resource SomeRsrcEnvRef
myRsrcEnvRef;
@Resource javax.jms.Queue
workQueue;
@PersistenceUnit(unitName="Wareh
ouseManagement")
EntityManagerFactory
warehouseEMF;
Persistence Context References
UserTransaction Interface
ORB References
TimerService References
EJBContext References
@PersistenceContext(type=EXTEND
ED) EntityManager myEntityMgr;
@Resource UserTransaction
transaction;
//Somente disponível para Session e MDB
com contexto de transação gerenciados por
Bean
@Resource ORB corbaOrg;
@Resource TimerService
mTimerService;
@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 MethodReady 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)
Constructor
Dependency injection methods (setter
methods).
Allowed Operations
None.
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())
Business method from any view or business
method interceptor method.
Métodos não usados do contexto
( getCallerIdentity(), isCallerInRole(Identity),
getEnvironment(), getMessageContext())
Business methods from web service endpoint.
Métodos não usados do contexto
( getCallerIdentity(), isCallerInRole(Identity),
getEnvironment(),getInvokedBusinessInterface ,
wasCancelCalled)
SessionContext:
getBusinessObject,
getEJBHome,
getEJBLocalHome,
getEJBObject,
getEJBLocalObject,
lookup,
getContextData,
getTimerService,
getUserTransaction (BMT only).
JNDI Access: Available
EntityManagerFactory: Accessible.
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).
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.
Timeout callback method.
Métodos não usados do contexto
( getCallerIdentity(), isCallerInRole(Identity),
getEnvironment(),getInvokedBusinessInterface ,
wasCancelCalled, getMessageContext())
Other EJBs: Accessible.
EntityManagerFactory: Accessible.
EntityManager: Accessible.
Timer and TimerService : Accessible.
UserTransaction methods: Accessible
(BMT only).
. 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ção coma 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)
Constructor
Dependency injection methods (setter
methods).
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())
Business method from any view or business
method interceptor method.
Métodos não usados do contexto
( getCallerIdentity(), isCallerInRole(Identity),
getEnvironment(), getMessageContext() , getTimerService())
Allowed Operations
None.
SessionContext:
getEJBHome,
getEJBLocalHome,
lookup.
JNDI Access: Available
SessionContext:
getBusinessObject,
getEJBHome,
getEJBLocalHome,
getCallerPrincipal,
isCallerInRole,
getEJBObject,
getEJBLocalObject,
lookup,
getContextData,
getUserTransaction (BMT only).
JNDI Access: Available
Resource managers: Accessible.
EntityManagerFactory: Accessible.
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.
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())
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())
EntityManagerFactory: Accessible.
EntityManager: Accessible.
Timer methods: Accessible.
UserTransaction methods: Accessible
(BMT
only).
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.
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
@Lock ( LockType . WRITE )
Ou
@Singleton
@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 associados ao 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)
Constructor
Dependency injection methods (setter
methods).
PostConstruct, PreDestroy, PrePassivate,
PostActivate methods (lifecycle callback
methods).
Business method from any view or business
method
interceptor method.
Allowed Operations
None.
SessionContext:
lookup.
JNDI Access: Available
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).
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 mensagem
javax.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 instancia MDB
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
messageSelector
Descrição
Um MDB pode declarar um seletor de mensagem, os seletores de
acknowledMode
subscriptionDurability
destinationType
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.
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-okacknowledge 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"),
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.
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 <messagedestination-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-destinationlink> 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
PostConstruct life-cycle methods
PreDestroy life-cycle methods
Listener method(s)
Timeout callback methods
Constructor
Dependency injection setter methods
MessageDrivenContext setter method
Contexto Transacional
Indefinido
Indefinido
Conforme especificado por anotações ou no ejb-jar.xml
REQUIRED ou NOT_SUPPORTED
Conforme especificado por anotações ou no ejb-jar.xml
REQUIRED, REQUIRES_NEW ou NOT_SUPPORTED
Indefinido
Indefinido
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
Constructor
Dependency injection methods (setter methods).
PostConstruct and PreDestroy methods
(lifecycle callback methods).
Message listener methods or business method
Operações permitidas
nenhuma
MessageDrivenContext:
lookup.
JNDI Access: Available
MessageDrivenContext:
lookup,
getContextData,
getTimerService,
getUserTransaction (BMT only).
JNDI Access: Available
EntityManagerFactory: Accessible.
MessageDrivenContext:
interceptor method.
Timeout callback methods.
getCallerPrincipal,
isCallerInRole,
lookup,
getContextData,
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).
MessageDrivenContext:
getCallerPrincipal,
lookup,
Accessing Session Beans e Message Driven Beans
Session Beans
Ee três tipo diferentes de clientes para acessar os Session Beans.
•
•
•
Clientes Locais
Cliente Remotos
Cliente WebService
O acesso nunca é feito diretamente na instancia do EJB e sim no (proxy) Objeto EJB.
Cliente Locais de Session Beans
Cliente locais são clientes que são empacotados na mesma aplicação e na mesma JVM
Exemplo de cliente são : outros EJB, Servlets e WebService.
Um Session Bean local é acessado da mesma maneira por diferentes tipo de cliente, o que muda é
como o clientes obtém uma referencia usando injeção de dependência ou JNDI.
Parâmetros e valores de retorna são passados por referencia.
Cliente Remotos de Session Beans
O EJB disponibilizar uma visualização remota independente se o Cliente está em JVM diferentes ou
não.
Cliente existentes para Session Bean remote
Clientes JavaEE localizados no mesmo ou em outro Container, Ex: Servlets, EJB, WebServices.
Clientes Java SE ,Ex: applets e aplicação standalone
Clientes não Java, usando CORBA.
Parâmetros e valores de retorna são passados por valores e devem implementar Seriazable
É possível desenvolver um cliente Java SE que tirar proveito de injeção de dependência. Tal aplicação
cliente é implantado no servidor GlassFish usando o Java Web Start.
Nomes portáteis de JNDI para Session Beans
A especificação Java EE6 defini alguns nomes JNDI padronizados para o qual os Session Beans
devem ser registrar. Está padronização garante que esses nomes seja portáteis em qualquer Container
EJB que aderem a especificação EJB 3.1.
Sintaxe do nome JNDI
java:global[/<appname>]/<modulename>/<
bean-name>[!<fullyqualifiedinterface-name>]
java:app/<modulename>/<beanname>[!<
fully-qualified-interfacename>]
java:module/<beanname>[!<fullyqualifiedinterface-name>]
Scopo
Global
Application.
Clientes e Session
Beans construído
na mesma
aplicação
Module
Clientes e Session
Beans construído
no mesmo modulo
da mesma
aplicação
Observações
Namespace Global.
O app-name é somente
obrigatório se o EJB é
empacotado em um arquivo
EAR.
O modulo de um EJB e o
arquivo WAR ou JAR que ele
está empacotado
O bean-name é o nome do
EJB que pode ser
especificado com a anotação
@EJB
O fully-qualified-interfacename somente deve ser
especificado se o EJB tem
duas ou mais interfaces
Namespace especifico por
aplicação
O module-name é sempre
necessário
Namespace especifico por
modulo.
Em adicional tem o namespace java:comp JNDI todos os componente com exceção dos componentes
em um modulo Web tem um namespace java:comp próprio.
Dependendo do posto de vista apresentado por um Session Bean, o container registra um JNDI
diferente para cada situação.
•
•
•
•
•
Interface de negocio Local.
Interface de negocio Remota
No-Interface (usa o nome da classe)
Interface Local Home EJB 2.x
Interface Remota Home EJB 2.x
A existência do nome JNDI Global para Interface de negocio Local ou No-Interface não significa que
o acesso para essas entradas são permitidas por outro aplicação
Exemplo de quais nomes JNDI um Servelt pode acessar um EJB StatefulSession1Bean
java:global/LocalSessionBeanClientEAR/LocalSessionBeanClient/StatefulSession1Bean
java:global/ LocalSessionBeanClientEAR/
LocalSessionBeanClient/StatefulSession1Bean!com.ivan.scbcd6.StatefulSession1Bean
java:app/LocalSessionBeanClient/StatefulSession1Bean
java:app/LocalSessionBeanClient/StatefulSession1Bean!
com.ivan.scbcd6.StatefulSession1Bean
java:module/StatefulSession1Bean
java:module/StatefulSession1Bean!com.ivan.scbcd6.StatefulSession1Bean
Os nomes JNDI pode ser alterado usando o DD.
Clientes de Session Beans
Tipo de Cliente
Remote
Local
WebService
Observação
O cliente usa uma interface de negocio remota
, a interface não requer que seja estendia a
qualquer outra, o EJB pode ser localizado na
mesma JVM ou em outras JVMs.
O parâmetros são passados por valores ,
parâmetros e retornos devem ser serializable.
O cliente usa uma interface de negocio local
ou nenhuma interface (no-interface).
O no-interface contem os métodos públicos na
classe de implementação do EJB.
A interface não requer que seja estendia a
qualquer outra.
O EJB é localizado na mesma JVM do cliente
e empacotado na mesma aplicação que o
cliente,
Somente Stateless Session Beans e Singleton
Session Beans pode prover ao cliente acesso
via WebService.
A interface de negócios remoto também pode
ser utilizado como o WebService
Em adicional o EJB 2.1 Session Beans também tem interfaces home , remota e locais.
É possível um EJB ter mais de uma interface
Comparando Tipo de EJB
Clientes de Session Beans pode comparar referencias ao invés de usar o método isIdentical das
Interfaces EJBLocalObject ou EJBObject.
Agora é possível usando os métodos equals e hashCode da classe Object.
Regras
•
•
Duas ou mais instância Statelles do mesmo tipos sempre são igual, ou seja tem o mesmo
hashCode
Duas ou mais instância Statelles de diferentes tipos nunca são igual, ou seja não tem o
mesmo hashCode
•
•
•
•
Duas ou mais instância Statefull do mesmo tipos nunca são igual, ou seja não tem o mesmo
hashCode
Duas ou mais instância Statefull de diferentes tipos nunca são igual, ou seja não tem o
mesmo hashCode
Duas ou mais instância Singleton do mesmo tipos sempre são igual, ou seja tem o mesmo
hashCode
Duas ou mais instância Singleton de diferentes tipos nunca são igual, ou seja não tem o
mesmo hashCode
Ex :
***** Stateless bean hash codes:
Stateless1 hash code: 364806942
Stateless2 hash code: 364806942
Stateless local business hash code: 1157496838
***** Stateful bean hash codes:
Stateful1 hash code: 244462009
Stateful2 hash code: 536768552
***** Singelton bean hash codes:
Singleton1 hash code: 2037736064
Singleton2 hash code: 2037736064
Em teste feito com o glassfish o hash code da local interface só é diferente caso a classe esteja
anotada com @LocalBean
Exceções de EJB com visão do Cliente
Um cliente de um EJB pode receber uma exceção de aplicativo ou do sistema nos seguintes casos:
•
•
•
•
A exceção do sistema foi lançado devido a um erro no lado do cliente tentando chamar um
EJB. Qualquer transação não será marcada para rollback ou revertida.
A exceção do sistema foi lançado devido a um erro que ocorre a execução do EJB. Qualquer
transação será marcada para rollback pelo contêiner.
Uma exceção aplicativo foi lançada durante a execução do EJB. Qualquer transação pode ou
não pode ter sido marcada para rollback
A exceção aplicativo pode ter sido configurado (@ ApplicationException) para fazer com que
o Container faça roolback para qualquer transação quando a exceção for lançada.
Exceções de aplicação
Um cliente de um EJB que recebe uma exceção aplicação pode continuar a realizar chamadas de
métodos do EJB.
Exceções de aplicativos para métodos de WebServices de Stateless são mapeados para falhas SOAP
Exceções de sistema
Exceções do sistema podem ser lançadas pelas seguintes razões:
•
Ocorreu um erro do lado do cliente ao fazer uma requisição ao EJB (A transação não sofre
rollback)
•
O correu um erro durante o processamento do EJB (A transação sofre rollback)
A tabela a seguir lista as exceções comuns do sistema
Exception
Status Transaction
As seguintes exceções são exceções básica de sistema
EJBException
Pode ou não pode ter sido
marcada para rollback.
RemoteException
Observação
Não é possível determinar se
o método EJB executou
ou não. O erro pode ter
ocorrido durante a
comunicação com, ou
processamento no EJB.
Veja EJBException.
Pode ou não pode ter sido
marcada para rollback.
As seguintes exceções indica que uma transação foi marcada para sofrer rollback
EJBTransactionRolledba
Revertida ou marcada para
Subclasse de EJBException.
ckException
rollback.
EJB invoked using EJB 3.1
view and EJB executing in
client's
transaction.
TransactionRolledbackL
Revertida ou marcada para
Subclasse de EJBException.
ocalException
rollback.
EJB invoked using EJB 2.1
local client view.
TransactionRolledbackE
Revertida ou marcada para
Subclass of
xception
rollback.
RemoteException. JTA
standard exception.
EJB invoked using EJB 2.1
remote view or web service
view.
As seguintes exceções indica que houve um tentativa de invocar o método que requer o cliente
se um contexto transacional
EJBTransactionRequired
Nenhuma transação.
Subclass of EJBException.
Exception
EJB invoked using EJB 3.1
view.
TransactionRequiredLoc
Nenhuma transação.
Subclass of EJBException.
alException
EJB invoked using EJB 2.1
local client view.
TransactionRequiredExc
Nenhuma transação.
Subclass of
eption
RemoteException. JTA
standard exception.
EJB invoked using EJB 2.1
remote view or web service
view.
As seguintes exceções indicam que foi feita uma tentativa para chamar um método em um
objeto EJB que não existe.
NoSuchEJBException
Revertida ou marcada para
Subclass of EJBException.
rollback.
EJB invoked using EJB 3.1
view.
NoSuchObjectLocalExc
Revertida ou marcada para
Subclass of EJBException.
eption
rollback.
EJB invoked using EJB 2.1
local client view.
NoSuchObjectException
Revertida ou marcada para
Subclass of
rollback.
RemoteException.
EJB invoked using EJB 2.1
remote client view.
RemoteException
O RemoteException ocorre nos seguintes locais relacionados com EJBs:
•
•
•
EJB 2.1 Remote Home Interfaces.
EJB 2.1 Remote Component Interfaces.
JAX-RPC Web Service Endpoint Interfaces.
Interfaces Local no EJB 2.1 e EJB 3.1 métodos de exibição do cliente não pode declarar
RemoteException
Message Driven Beans
Verificar a API JMS na sessão acima.
Os procedimentos para enviar um mensagem JMS são
•
•
•
•
•
•
•
•
Recupera a JMS connection.
Criar uma sessão JMS em que a mensagem será enviada usando a conexão JMS.
Criar um produtor de mensagens JMS que vai ser usado para enviar a mensagem para o seu
destino.
Criar o objeto Java para ser colocado na mensagem JMS e definir suas propriedades.
Criar a mensagem JMS a ser enviada .
Definir o objeto a ser incluído na mensagem JMS.
Enviar a mensagem JMS.
Fechar o produtor de mensagem JMS e a conexão JMS.
Enviando mensagens com cliente JAVA EE.
@WebServlet(name = "MessageProducerServlet", urlPatterns = "/sendmsg.do")
public class MessageProducerServlet extends HttpServlet {
/* Instance variable(s): */
/** Connection factory for queue. */
@Resource(mappedName = "jms/QueueConnectionFactory")
private ConnectionFactory mQueueConnectionFactory;
/** Queue destination. */
@Resource(mappedName = "jms/QueueDestination")
private Queue mQueueDestination;
/** MyMessage number counter. */
private AtomicLong mMessageNumber = new AtomicLong(0);
public MessageProducerServlet() {
super();
}
protected void doGet(HttpServletRequest inRequest,
HttpServletResponse inResponse) throws ServletException,
IOException {
PrintWriter theResponseWriter = inResponse.getWriter();
try {
sendJmsMessage();
theResponseWriter.println("A message: " + new Date());
} catch (JMSException theException) {
theResponseWriter.println("An error occurred" +
theException);
}
}
private void sendJmsMessage() throws JMSException {
MessageProducer producer = null;
Connection conn = null;
try {
/* Retrieve a JMS connection from queue connection
factory. */
theJMSConnection = mQueueConnectionFactory.createConnection();
/*
* Create session; not transacted and with auto- *
acknowledge.
* Session session=
* conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
/* Create a
* JMS message producer for the queue destination.
*/
producer = session.createProducer(mQueueDestination);
/* Create the object to be sent in the message created above. */
MyMessage objeto = new MyMessage();
objeto.setMessageNumber(mMessageNumber.incrementAndGet());
objeto.setMessageString("Hello Message Driven Beans");
objeto.setMessageTime(new Date());
/* Create message used to send a Java object. */
ObjectMessage theJmsObjectMessage =
session.createObjectMessage();
theJmsObjectMessage.setObject(objeto);
/* Send the message. */
producer.send(theJmsObjectMessage);
} finally {
closeJmsResources(theJMSConnection);
}
}
}
Enviando mensagens com cliente JAVA SE.
public class MessageDrivenBeanSEClient {
private final static String JMS_CON_JNDI = "jms/QueueConnectionFactory";
private final static String JMS_DES_QUEUE_JNDI = "jms/QueueDestination";
private ConnectionFactory queueConFactory;
private Queue queueDestination;
private void lookupJmsResources() throws NamingException{
InitialContext theContext = new InitialContext();
queueConFactory=(ConnectionFactory)theContext.lookup(JMS_CON_JNDI);
queueDestination = (Queue) theContext.lookup(JMS_DES_QUEUE_JNDI);
}
private void sendJmsMessage() throws JMSException {
MessageProducer msgProducer = null;
Connection theJMSConnection = null;
Try{
theJMSConnection = queueConFactory.createConnection();
/* Create the JMS session; not transacted and auto- * acknowledge. */
Session theJMSSession = theJMSConnection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
/* Create a JMS message producer for the queue destination. */
msgProducer = theJMSSession.createProducer(queueDestination);
/* Create the object to be sent in the message created above. */
MyMessage theObjectToSend = new MyMessage();
theObjectToSend.setMessageNumber(mMessageNumber.incrementAndGet());
theObjectToSend.setMessageString("Hello Message Driven Beans");
theObjectToSend.setMessageTime(new Date());
ObjectMessage objectMessage = theJMSSession.createObjectMessage();
theJmsObjectMessage.setObject(theObjectToSend);
msgProducer.send(theJmsObjectMessage);
} finally{
Try{
inJMSConnection.close();
} catch (JMSException theException){
}
}
}
public static void main(String[] args) {
MessageDrivenBeanSEClient theClient = new MessageDrivenBeanSEClient();
try {
theClient.lookupJmsResources();
for (int i = 0; i < 10; i++) {
theClient.sendJmsMessage();
}
} catch (Exception theException) {
theException.printStackTrace();
}
System.exit(0);
}
Podemos concluir que a única diferença entre o Java EE e os clientes Java SE é a recuperação de
referência de recurso; nas referências do cliente Java EE são pelas injeção de dependências , enquanto
eles cliente Java SE é usado JNDI.
Exceções
Exceções EJBs são classificados em dois grupos; exceções do aplicativo e exceções do sistema. Esta
classificação aplica-se a todos os tipos de EJBs, não apenas os beans de sessão.
Exceções de aplicação
Exceções de aplicação, são definida pelo bean provider usado para reportar problemas relacionados a
regra de negocio da aplicação, Uma exceção aplicativo não necessariamente causa um processo de
negócio a ser abortado ou revertido, os clientes de EJB deverão ser capazes de capturar e recuperar,
exceções de aplicação.
Exceções de aplicações são :
•
Uma classe java.lang.Exception e subclasses, excluindo java.rmi.RemoteException e suas
subclasses que são exceções de sistemas.
•
Exceções Unchecked (java.lang.RuntimeException e subclasses) anotada com
@ApplicationException ou marcada com o elemento <application-exception> no descritor de
implantação ejb-jar.xml e listada na clausula throws de um ou mais métodos de negocio.
•
•
•
Uma classe javax.ejb.CreateException e subclasse
Uma classe javax.ejb.RemoveException e subclasse
Uma classe avax.ejb.FinderException e subclasse
Exceções de aplicativos são normalmente incluídos na cláusula throws de métodos nos diferentes
tipos visualização que podem ser apresentados por um EJB.
A anotação @ApplicationException é usada para marcar uma exceção em uma exceção de
aplicação e deve ser repassado ao cliente sem wrapped, esta anotação tem o seguintes
elementos opcionais :
Elemento
inherited
rollback
Descrição
Indica se subclasses também deveria
tornar-se exceções de aplicativos
Valor default: true
Indica se reversão(rollback) de transação
deve ser causado quando exceção é lançada.
Valor default : false
O elemento <application-exception> no descritor de implantação ejb-jar.xml tem as
possibilidades de configuração correspondentes
Exceções de aplicação e transação
Exceções de aplicação por padrão não resulta em um rollback na transação, a não ser que essa
exceção seja anotada com a anotação @ApplicationException ou configurado o elemento
<application-exception> como true.
Ex:
@ApplicationException(inherited=true, rollback=true)
public class StatefullEJB {...}
<assembly-descriptor>
<application-exception>
<exception-class>package.RTExceptionA</exception-class>
<rollback>true</rollback>
<inherited>true</inherited>
</application-exception>
</assembly-descriptor>
Antes de lançar uma exceção de aplicação, o bean provider deve fazer um dos seguintes
procedimentos:
•
Garantir que o estado da instancia do EJB é consistente, a fim de permitir o uso contínuo da
instância EJB.
•
Marcar a transação para sofrer rollback, não é necessário se a exceção lançada causará
reversão de transação, isto para evitar que a transação é confirmada e causando perda de
integridade dos dados.
Exceções de sistema
Exceções de sistema geralmente indicam que houve um problema desconhecido que o EJB ou o
container EJB lançou uma exceção que não foram capazes de se recuperar do problema inesperado.
Exceções de sistemas são :
•
•
A classe java.rmi.RemoteException e subclasses
Exceções Unchecked (java.lang.RuntimeException e subclasses) que não são
marcadas com a anotação @ApplicationException e nem com o elemento
<application-exception> ejb-jar.xml no deployment descriptor, Essas exceções não
devem ser listados cláusulas throws de métodos de negócio.
A especificação EJB dá as seguintes recomendações a respeito de como as exceções devem ser
tratadas em um EJB:
•
•
Exceções de sistemas devem ser propagadas pelo container , ou seja, não há necessidade de
capturar e tentar lidar com exceções do sistema em um EJB.
Se o EJB não é capaz de recuperar-se de uma exceção verificada, então deve ser wrapped em
EJBException e lançada.
•
Outros erros inesperados deve resultar em EJBException sendo lançada.
Note-se que EJBException é uma exceção não verificada.
Uma instancia de EJB que lança um exceção de sistema é destruída , a não ser que o EJB é um
Singleton Session Bean, assim, apenas Singleton Session Bean precisa ter certeza que o
estado do EJB é consistente antes de lançar uma exceção do sistema, já que o bean continuará
a servindo todos os pedidos futuros.
Uma tentativa de invocar um session bean com estado que tenha jogado uma exceção de
sistema resultará em uma NoSuchEJBException sendo lançada.
Exceções de sistemas e transações
O Container marcar qualquer transação para sofrer rollback se uma transação de sistema for lançada
de dentro do método do EJB
Tratamento de Exceções em Session Bean
Interface de negocio e no-interface no método para tratamento de exceções
Visualização de cliente Web Service e visualização de cliente EJB 2.1
Tratamento de exceções nos métodos de call-back PostConstruct e PreDestroy
Estes métodos não estão autorizados a jogar aplicação exceções.
Tratamento de exceções nos métodos de call-back Timeout
O tratamento de exceções se aplica a todos os tipos de EJBs, não apenas os beans de sessão. Note-se
que está imagem descreve a semântica de manipulação de exceção do contêiner para os métodos de
timeout em todos os tipos de EJBs.
Tratamento de exceções em outros métodos de call-back
O tratamento de exceções se aplica a todos os tipos de EJBs, não apenas os beans de sessão.
A figura abaixo mostra a manipulação de exceções lançadas a partir de outros métodos de retorno
invocadas pelo contêiner. Todos exceção são tratados da mesma maneira. Tais métodos são os
seguintes:
•
•
•
•
•
•
•
•
•
Método de injeção de dependências.
Os seguinte métodos na interface EntityBean
• ejbActivate
• ejbPassivate
• ejbLoad
• ejbStore
• setEntityContext
• unsetEntityContext
Métodos PostActivate.
métodos PrePassivate.
Os seguinte métodos na interface SessionBean
• ejbActivate
• ejbPassivate
• setSessionContext
O método setMessageDrivenContext na interface MessageDrivenBea.
Os seguinte métodos session synchronization:
- afterBegin
- beforeCompletion
- afterCompletion
Para uma EJBException ou RemoteException ser lançada, depende de:
• Se visualização do cliente remoto EJB 2.1 ou visualização do cliente de serviço da
Web JAX-RPC é utilizado. um RemoteException é lançada.
• Se uma visualização do cliente local no EJB 2.1 é usado, uma EJBException é
lançada.
• No EJB 3.1 se qualquer visualização do cliente é usado, uma EJBException é
lançada.
Para uma EJBTransactionRolledbackException, TransactionRolledbackException ou
TransactionRolledbackLocalException ser lançada, depende de:
• Se o EJB é executado com uma transação do cliente, uma
EJBTransactionRolledbackException é lançada.
• Se uma visualização de cliente remoto no EJB 2.1 ou uma visualização de
cliente WebService for usada, uma TransactionRolledbackException é lançada
•
Se uma visualização de cliente local no EJB 2.1 é usada, uma
TransactionRolledbackLocalException é lançada
Métodos Assíncronos
A partir da versão 3.1 do EJB, podemos definir métodos assíncronos nos session beans. Geralmente,
métodos assíncronos são utilizados para implementar tarefas demoradas. Para definir um método
assíncrono, basta utilizar a anotação @Asynchronous. Se essa anotação for aplicada na classe que
define um session bean, todos os métodos de negócio desse session bean serão assíncronos. Por outro
lado, podemos aplicar essa anotação somente nos métodos de negócio que devem ser assíncronos e
também podemos usar o elemento <async-method> no descritor de implantação.
Somente métodos exposto por no-interface, interface Local e interface Remota pode ser assíncronos ,
nenhum método do EJB 2.X é permitido processamento assíncronos .
Ex :
@Asynchronous
public Future<String> metodoAssincrono2 () {...}
Métodos @Asynchronous podem ter um retorno void ou um java.util.concurrent.Future<T> , onde T
é o tipo de resultado produzido pelo método. Essa interface permite verificar se a tarefa já foi
concluída através do método isDone() e também permite que o resultado seja recuperado através do
método get(). Na API do EJB 3.1 foi incluida a classe javax.ejb.AsyncResult<T> que implementa a
interface java.util.concurrent.Future<T>.
Método assíncronos com retorno void não pode declarar qualque exceção.(no jboss funciona....)
Método com tipo de retorno Future<T> pode declarar exceçoes de aplicação.
A anotação @Asynchronous não tem nenhum elemento adicional.
Descritor de implantação
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>DDConfigedStatelessBean</ejb-name>
<local-bean />
<ejb-class>br.com.core.StatelessBean</ejb-class>
<session-type>Stateless</session-type>
<async-method>
//Especifica o nome do método, * para todos métodos
<method-name>metodoAss</method-name>
//Opcional, para diferenciar assinaturas de métodos
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</async-method>
</session>
</enterprise-beans>
</ejb-jar>
Transações é Metodo Assíncronos
Contexto de transação não se propaga na invocações de método assíncronos.
Transaction Attribute Transaction in Asynchronous Method
NOT_SUPPORTED
REQUIRED
SUPPORTS
REQUIRES_NEW
MANDATORY
NEVER
Não existe no contexto de transação do método.
Um contexto de transação será criado.
Não existe no contexto de transação do método.
Um novo contexto de transação será criado
Uma exceção será lançada, indicando que um
contexto de transação é necessária.
Não existe no contexto de transação do método.
Um método sem um contexto de transação irá lançar uma exceção se for feita uma tentativa de, por
exemplo, chamar o método SessionContext.getRollbackOnly () ou outros métodos que necessita de
um contexto de transação.
Segurança e Metodo Assíncronos
O contexto de segurança é propagado da mesma maneira que acontece com os métodos síncronos.
Exceções e Metodo Assíncronos
Quando um cliente de um bean de sessão invoca um método assíncrono, as seguintes exceções podem
ser lançadas em diferentes estágios da invocação:
Etapa
Exceção
Preparação da invocação
do método assíncronos
EJBException ou
RemoteException (se a interface de
negocio estender a Remote)
Execução do método
assíncrono
Exceção de Aplicação
Execução do método
assíncrono
Exceção de Sistema
Valores de retorno de Métodos Assíncronos
Cliente obtém o retorno como Future<T>, no qual pode ser usado para :
•
•
•
•
Determinar quando a operação foi completada
Recuperar o valor do resultado do método
Determinar se o método foi concluído de forma normal ou anormal (exceção gerada).
Tentativa de cancelar uma invocação contínua.
O container pode lançar uma exceção sistema do tipo EJBException como resultado de chamar o
método assíncrono, se houver qualquer problema quando se prepara para invocar o método
Abaixo métodos da interface java.util.concurrent.Future e a descrição da semântica de como usar com
métodos assíncronos dos session beans
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
V get();
V get(long timeout, TimeUnit unit);
boolean isCancelled();
boolean isDone();
}
Assinatura do método
Descrição
boolean cancel(boolean mayInterruptIfRunning); : Container vai tentar cancelar o
método invocação só se ele não tiver sido já despachado, retorna true se a invocação de cancelamento
foi bem sucedida, false para o contrario.
Se a invocação já foi despachada, o bean de sessão só conseguirá através do método
SessionContext.wasCancelCalled() verificar sobre a tentativa de cancelamento se configurar a tag
mayInterruptIfRunning para true.
V get();: Espera a invocação do método ser completada e recupera o valor do resultado ou uma
exceção da invocação do metodo assíncrono.
Exceções
CancellationException : se a invocação foi cancelada
ExecutionException : se o método lançou exceção
InterruptedException :Se a thread do cliente foi interrompida
V get(long timeout, TimeUnit unit); : Espera a invocação do método ser completada até o
tempo expirar , se não, uma TimeoutException é lançada
Exceções
CancellationException : se a invocação foi cancelada
ExecutionException : se o método lançou exceção
InterruptedException :Se a thread do cliente foi interrompida
TimeoutException : Se a espera expirou
boolean isCancelled(); : Retorna true se a invocação de método foi cancelado
e não foi concluída normalmente.
boolean isDone(); : Retorna true se a invocação de método foi concluída. Conclusão pode ser
devido ao processamento normal , uma exceção ou cancelamento.
Injeção de Dependência e JNDI ENC
Cada container EJB que é implantando em um servidor de aplicação tem seu próprio registro interno
chamado de ENC. Este ENC é implementado pelo JNDI e é um local em que o Container mantem
referencias especificas ao seu ambiente.
ENC é um contexto no mundo JNDI, é como um alias que faz referencia no Container EJB, cada EJB
tem seu ENC, o ENC é controlado pelo container e alcançado por beans usando JNDI.
O namespace java:comp/env/ é o ENC.
Muitos itens diferentes podem ser registrado no ENC, referencia a qualquer interface EJB, uma fila ou
tópico JMS, fabricas de conexões JMS, origem de dados, qualquer recurso JCA, valores primitivos ,
serviços JEE como UserTransaction, TimerService e ORB.
O ENC é preenchido de duas maneiras , via XML ou via anotações, qualquer referencia que você
declara no XML a um serviço ou recurso preenche automaticamente o JNDI ENC com o nome dessa
referencia, qualquer anotação de ambiente que você utiliza também faz com que o ENC seja
preenchido, depois que um item é vinculado ao JNDI ENC do container, ele pode ser referenciado por
uma pesquisa JNDI
Exemplo de registro usando XML
<ejb-jar>
<enterprise-beans>
<ejb-name>MyEJB</ejb-name>
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBSession</ejb-ref-name>
<ejb-ref-type>session</ejb-ref-type>
<local>MyEJBSessionLocal</local>
<ejb-link>myId</ejb-link>
</ejb-local-ref>
</enterprise-beans>
</ejb-jar>
O elemento <ejb-local-ref> instrui o contaneir EJB que o MyEJB quer um referencia ao
MyEJBSession EJB, assim um referencia do MyEJBSession é registra no ENC MyEJB pelo nome
ejb/MyEJBSession, isto é definido pelo elemento <ejb-ref-name>
Exemplo de registro usando anotação
@Stateless
@EJB(name = "ejb/MyEJBSession"
beanInterface = MyEJBSessionLocal.class,
beanName = "myId")
public class MyEJB {...}
Cada anotação possui o elemento name que especifica o nome JNDI ENC ao qual você quer que a
referencia de serviço seja vinculada.
Qualquer coisa registrada no ENC pode ser pesquisada pelo nome sub contexto java:comp/env usando
o lookup do InitialContext, este método lança um exceção de aplicação NamingException e dever ter
o contexto do ENC completo , o nome JNDI é resolvido para um ENC diferente dependendo de onde
você invoca a pesquisa, pois cada EJB tem um ENC próprio.
O EJBContext tem um método de pesquisa conveniente, esse método é um pouco mais simples do que
uma pesquisa JNDI direta, porque ele não lança um exceção de aplicação e adiciona um nome relativo
ao ENC, ou seja, você não precisa informa o contexto java:comp/env
Nome ENC padrão
Anotando um campo ou método setter de uma classe EJB também cria uma entrada no ENC para o
elemento injetado, isso acontece para todas anotações de injeção, se o elemento name da anotação de
injeção for especificado, a referencia será armazena no ENC sob este nome, se nenhum nome for
especificado, o ENC então será extraído do nome do campo anotado ou método setter. Neste caso, um
nome ENC padrão é derivado do nome de classe completamente qualificado mais o nome do campo
ou método setter(sem o prefixo set).
O nome ENC torna-se bem importante quando você quer sobrescrever uma anotação de injeção no
XML.
Injeção via XML
<injection-target>
<injection-target-class>br.com.MyBean</injection-target-class>
<injection-target-name>my</injection-target-name>
</injection-target>
O elemento <injection-target> é usado para injetar uma referencia ao campo ou método setter da
classe EJB, este elemento aparecerá como um sub elemento da referencia a ser injetada.
O elemento <injection-target-class> especifica a classe em que o campo o método setter é declarado,
isto pode parecer desnecessário, mais torna-se necessário quando há hierarquia de herança.
O elemento <injection-target-name> especifica o nome no campo ou método setter.
Você não pode injetar um campo ou método setter com o mesmo nome.
Sobrescrições em XML
A especificação EJB permite sobrescrever anotação usando o descritor de implantação, determinado
pelo elemento name da referencia. O XML sempre tem precedência sobre os meta-dados da anotação
O elemento <ejb-link>
O elemento <ejb-link> fornece uma referencia mais especifica ao EJB, ou seja, especifica a classe de
implementação do EJB.
Injeção e herança
É possível que um EJB seja parte de uma hierarquia de EJBs, se um campo ou método tiver anotação
de injeção, eles ainda serão preenchidos, mais certas regras de injeção devem ser seguidas.
•
•
•
Subclasses herdam recursos injetados (se não privado).
Subclasses podem sobrescrever injeção (injetando outra implementação, por exemplo), mas
se recurso do pai for privado, não é herdado.
Se a superclasse tiver um recuso privado e a subclasse tentar sobrescrever este recurso, serão
criada duas referencias ao ENC, uma da superclasse e outra da subclasse.
Nomes EJBs ambíguos e reusáveis (overloaded)
O elemento <ejb-name> e quaisquer atributos @Stateless.name() , @Stateful.name() ,
@Singleton.name() e @MessageDriver.name() devem ser único dentro de uma dada implantação EJB
JAR, infelizmente, esse não é o caso para todos os EJB JARs implantado em um EAR. Em um
arquivo EAR nomes podem ser duplicados em diferentes EJB-JAR.
Para diferenciar referencias como nome EJBs duplicados em, EAR, especificação EJB tem um sintaxe
estendida para o atributo <ejb-link> e o atributo beanName() da anotação @EJB, essa sintaxe
estendida tem um caminho relativo para o JAR em que o EJB está localizado, seguida pelo caractere
#, seguido pelo nome EJB do bean referenciado.
Ex, um EJB PersonEJB localizado em um arquivo JAR cadastro-ejb.jar , seria injetado da seguinte
maneira :
@EJB(beanName=”cadastro-ejb.jar# PersonEJB”)
PersonEJB personEJB;
Outros exemplo de uso de EJBs
Usando anotação
@Stateless
@EJB(name = "ejb/MyOtherBean",
beanInterface = MyOtherBean.class,
beanName = "otherBean")
public class MyBean {
@EJB
private MyOtherBean other;
}
Usando XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<ejb-ref>
<ejb-ref-name>ejb/MyOtherBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>br.com.MyOtherBean</remote>
<injection-target>
<injection-target-class>br.Bean</injection-target-class>
<injection-target-name>other</injection-target-name>
</injection-target>
<ejb-link>otherBean</ejb-link>
<ejb-ref>
</session>
<session>
<ejb-name>otherBeann</ejb-name>
...
</session>
</enterprise-beans>
</ejb-jar>
A anotação @Resource
Usada para injetar e declarar recursos externos, e pode ser aplicada em :
Classes : Declara um recurso que o aplicativo irá procurar(lookup) em tempo de execução, quando
usado na classe, os atributos name() e type() são obrigatórios
Campo da classe : Declara um campo com qualquer modificador de acesso, que pode ser injetado
com um recurso especificado quando uma instancia da classe é inicializada.
Métodos setter : Um método que defini um recurso especifico quando uma instancia da classe é
inicializada
A anotação @Resource tem os seguintes elementos opcionais :
Nome do elemento
authenticationType
Comentários
Identifica quem é responsável por autenticar o
recurso, o container ou a aplicação.
Possíveis valores:
Resource.AuthenticationType.CONTAINER,
Resource.AuthenticationType.APPLICATION
Valor default:CONTAINER
description
mappedName
Descrição do recurso, para o desenvolvedor
Nome especificado do recurso que está mapeado
no fornecedor, não portátil.
Default : “”
Nome JNDI ENC do recurso , relativo ao contexto
name
java:comp/env, obrigatório quando usado a nível
de classe.
Default : “”
Booleano que indica se o recurso pode ser usado
shareable
simultaneamente por mais de um componente
EJB.
Default : true
Tipo de recurso java, declara o nome
type
completamente qualificado do recurso, obrigatório
quando usado a nível de classe.
Default : java.lang.Object
Para alguns tipos de recursos, os elementos shareable e authenticationType não deve ser utilizado,
uma vez que os recursos desse tipo não exige autenticação e não são compartilháveis.
A anotação @Resource só pode ser usada um vez a nível de classe, quando você precisa referenciar
múltiplos recurso utilize a anotação @Resources
@Stateful
@Resource(name = "jdbc/Oracle",
type = javax.sql.DataSource,
mappedName = "java:/DefaultDS")
public class MyBean {
@Resource
private DataSource oracleDB;
}
Ou com XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Bean</ejb-name>
<resource-ref>
<res-ref-name>jdbc/Oracle</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<mapped-name>java:/DefaultDS</mappedName>
<injection-target>
<injection-target-class>br.Bean</injection-target-class>
<injection-target-name>oracleDB</injection-target-name>
</injection-target>
<resource-ref>
</session>
</enterprise-beans>
</ejb-jar>
Elementos
<resource-ref>
Descrição
define uma referencia a um dado recurso
<res-ref-name>
É equivalente ao atributo name da anotação
@Resouce
É equivalente ao atributo type da anotação
@Resouce
É semelhante ao atributo authenticationType(),
pode ter dois valores, Container ou Application
<res-type>
<res-auth>
<res-sharing-scope>
<mapped-name>
<injection-target>
<description>
Obrigatório
Sim
Especifico do fornecedor, equivalente ao
mappedName() da anotação @Resouce
É utilizado para injetar o recurso no EJB
Para o desenvolvedor
Sim
Sim
Sim
Não
Não
Não
Não
A anotação @EJB
Local de Uso
Class
Efeito
Registra uma referencia ao
ENC do EJB.
Campos obrigatórios
name()
beanInterface()
Caso o container não
consiga resolver o tipo,
os elemento beanName()
e mappedeName()
devem ser utilizados para
fornecer um identificador
único.
Method
Indica uma dependência de um Nenhum elemento é
EJB que será
obrigatório deste que a
injetado, invocando o método
interface do negocio
anotado.
possa ser determinada
pelo tipo do parâmetro do
método
Instance field
Indica uma dependência de um Nenhum elemento é
EJB que será
obrigatório deste que a
Injetado, pela definição do
interface do negocio
campo de instancia.
possa ser determinada
pelo tipo do campo
Entradas declaradas na classe com está anotação pode ser looked usando EJBContext.lookup
ou API JNDI.
Elementos opcionais da anotação @EJB
Elemento
beanInterface
Tipo
Class
Descrição
É a interface em que você
está interessada, pode ser
uma Local business interface,
remote business interface,
bean class (no-interface view),
local home interface (EJB 2.1),
remote home interface (EJB
2.1).
beanName
String
O nome do EJB do EJB
referenciado, ele é igual o
valor que é especificado na
anotação Stateless.name(),
ou <ejb-name> no XML, ou
seja o nome do EJB.
description
String
Descrição do EJB, para o
desenvolvedor
lookup
String
mappedName
String
name
String
O nome do JNDI portátil do
EJB
Específico do produto, nãoportátil, nome do EJB para
que este referência é
mapeado.
Nome que o JNDI ENC terá
para o EJB referenciado ,
este nome é relativo ao
contexto java:comp/env.
Ao usar a anotação @EJB para realizar a injeção de dependência, podemos usar o beanName
ou o elemento lookup , mais não ambos.
Declarando nome JNDI com a anotação @EJB
@EJB(name=”ejb/BookingPerson”, beanInterface=BookingPersonHome.class)
@Stateless
public class BookingServiceBean implements BookingService{...}
Neste caso a anotação @EJB é usada para declarar a entrada “java:comp/env/ejb/BookingPerson” de
ambiente JNDI que refere a interface home de outro EJB. Esse nome JNDI pode ser usado de dentro
da classe do EJB BookingServiceBean para realizar o lookup referente a interface home do outro EJB.
A anotação @EJB pode ser utilizada somente uma vez na classe EJB, quando é necessário referenciar
múltiplos EJBs, deve usar a anotação javax.ejb.EJBs
Métodos Setter usando a injeção da anotaçõa @EJB
@Stateful
@LocalBean
public class StatefulSession1Bean {
...
@EJB(beanName="DummyStatelessBean")
public void setDummyReference(DummyStatelessBean inBeanReference){...}
}
Neste caso a anotação @EJB é usada para injetar uma referencia a outro EJB em um método set, a
injeção de dependência ocorre antes de qualquer método @PostConstruct ser invocado. Como
alternativa ao elemento beanName o elemento lookup ou name podem ser usados para especificar
nome JNDI completo ou o nome JNDI relativo ao “java:comp/env” usado para procurar referencias
do bean a ser injetado.
Instancia de campo usando a injeção da anotação @EJB
@Stateful
@LocalBean
public class StatefulSession1Bean {
@EJB
private DummyStatelessBean mDummyStatelessRef;
}
Neste caso a anotação @EJB é usada para injetar uma referencia a outro EJB em um campo, a injeção
de dependência ocorre antes de qualquer método @PostConstruct ser invocado.Como alternativa ao
elemento beanName o elemento lookup ou name podem ser usados para especificar nome JNDI
completo ou o nome JNDI relativo ao “java:comp/env” usado para procurar referencias do bean a
ser injetado.
Declarando referencias remotas a EJBs usando XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<ejb-ref>
<ejb-ref-name>ejb/Bean2</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>br.com.IBean2</remote>
</ejb-ref>
</session>
</enterprise-beans>
</ejb-jar>
Elementos
<ejb-ref>
<ejb-ref-name>
<ejb-ref-type>
<remote>
<home>
<ejb-link>
<mapped-name>
<injection-target>
<description>
Descrição
define uma referencia a EJBs remotos.
Nome que será vinculado ao ENC, equivalente ao
atributo name da anotação @EJB, é relativo ao
contexto ENC
Pode ter dois valores, Session ou Entity (interface
home do bean de entidade do EJB 2.x)
Especifica o nome completamente qualificado da
classe da interface remota do bean, se tiver usando
o EJB 2.x o elemento <home> é necessário
No EJB 2.x é necessário para fornecer o nome
totalmente qualificado da interface home
Classe de implementação de um EJB especifico ,
equivalente ao atributo beanName() da anotação
@EJB
Especifico do fornecedor, equivalente ao
mappedName() da anotação @EJB
É utilizado para injetar a referencia EJB em um
campo método setter da classe do bean.
Para o desenvolvedor
Obrigatório
Sim
Sim
Sim
Sim
Não
Não
Não
Não
Declarando referencias locais a EJBs usando XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<ejb-local-ref>
<ejb-ref-name>ejb/Bean2</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>br.com.IBean2</local>
</ejb-local-ref>
</session>
</enterprise-beans>
</ejb-jar>
Elementos
<ejb-local-ref>
Descrição
define uma referencia a EJBs locais.
<ejb-ref-name>
Nome que será vinculado ao ENC, equivalente ao
atributo name da anotação @EJB, é relativo ao
contexto ENC
Pode ter dois valores, Session ou Entity (interface
home do bean de entidade do EJB 2.x)
Especifica o nome completamente qualificado da
classe da interface local do bean, se tiver usando o
EJB 2.x o elemento <local-home> é necessário
<ejb-ref-type>
<local>
Obrigatório
Sim
Sim
Sim
Sim
<local-home>
<ejb-link>
<mapped-name>
<injection-target>
<description>
No EJB 2.x é necessário para fornecer o nome
totalmente qualificado da interface home
Classe de implementação de um EJB especifico ,
equivalente ao atributo beanName() da anotação
@EJB
Especifico do fornecedor, equivalente ao
mappedName() da anotação @EJB
É utilizado para injetar a referencia EJB em um
campo método setter da classe do bean.
Para o desenvolvedor
Não
Não
Não
Não
Os EJBs declarados nos elementos <ejb-local-ref> são beans locais, portanto eles não requerem o uso
do método javax.rmi.PortableRemoteObject.narrow() para recuperar a referencia ao tipo apropriado.
Injeção usando o descritor de implantação
Injeção de recursos, podem ser usado se anotações, usando o ejb-jar.xml. Uma vez este é comum a
todos os diferentes tipos de referência de recursos.
O elemento <injection-target> aparece como um elemento filho de um elemento de referencia de
recursos e especifica a classe e a instância do nome do campo em que a referência de recurso deve ser
injetado.
Ex:
...
/* simples entrada de ambiente de injeção por anotações */
private int filter = 99;
...
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
...
<env-entry>
<env-entry-name>filter</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>15</env-entry-value>
<injection-target>
<injection-target-class>br.com.BeanEJB
</injection-target-class>
<injection-target-name>filter</injection-targetname>
</injection-target>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
O valor injetado pelo descritor de implantação sobrescreverá o valor do campo, tenha em mente que
se você não injetar o valor com o descritor de implantação e tentar fazer um lookup acontecera um
erro . O tipo de campo de instância deve corresponder ao tipo de referência de recursos.
Lookup usando o InitialContext
Lookup um nome JNDI usa o InitialContext
Context initialContext = new InitialContext();
Context compEnv = (Context)initialContext.lookup("java:comp/env");
ReferencedLocal localRef = (ReferencedLocal)
compEnv.lookup("ejb/OutroBean");
Criamos um initialContext, depois obtemos um sub contexto “java:comp/env”. O sub-cotexto procura
a referencia do EJB, podemos eliminar o sub-contexto é ir direto para referencia do EJB.
Lookup usando o EJBContext
@Stateful
public class StatefulSession2Bean{
@Resource
private SessionContext sessionBeanContext;
}
Existem quatro tipos diferentes de contextos EJB, que podem ser injetados.
Tipo de Contexto EJB
EJBContext
EntityContext
Pode ser injetado dentro
Session beans, message driven
beans, entity beans
Entity beans.
MessageDrivenContext
Message driven beans.
SessionContext
Session beans.
Comentários
Tipo de contexto básico, usado
dentro de qualquer EJB.
Contém métodos adicionais
para, por exemplo, a recuperação de
uma chave primária da entidade.
Nenhuma funcionalidade adicional,
comparado com EJBContext
Contém métodos adicionais
para, por exemplo, a recuperação de
interface de negócios,
cancelamento de métodos
assíncronos chamado no EJB.
Disponível na EJBContext, e, portanto, em todos os tipos de contextos, é o método de lookup, que
podemos usar para procurar um referências de recursos. Três coisas devem ser tomadas em
consideração quando se utiliza.
•
•
•
Estreitando referências a casas remotos e interfaces remotas usando o
PortableRemoteObject.narrow método não é necessário.
Se a pesquisa for realizada para um recurso no qual o EJB se refere, então podemos omitir o
“java:comp/env/”.
Se a pesquisa for realizada para um recurso fora do EJB, então “java:comp/env/” é necessário.
Ex:
Integer filter = (Integer)sessionContext.lookup("filter");
ReferencedLocal localRef = (ReferencedLocal)
sessionContext.lookup("OutraBeanRef");
Ambas as referências acima foram declarados no descritor de implementação ejb-jar.xml; o primeiro
utilizando um elemento <env-entry> e o segundo, utilizando um elemento <ejb-local-ref>.
Referencias de Ambientes
Entradas de ambientes, são valores dos seguintes tipos : String, Character, Integer,
Boolean, Double, Byte, Short, Long, Float , esses valores são definidos no descritor de implantação
usando o elemento <env-entry>.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
<!-- Simple environment entry. -->
<env-entry>
<env-entry-name>filterFlag</env-entry-name>
<env-entry-type>java.lang.Boolean</env-entry-type>
<env-entry-value>true</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
Elementos
<env-entry>
<env-entry-name>
<env-entry-type>
<env-entry-value>
Descrição
define entradas de ambientes
Obrigatório
Sim
Define a entrada no JNDI ENC e é relativo ao
contexto java:comp/env
String, Character, Integer,
Boolean, Double, Byte, Short, Long, Float
O valor definido
Sim
Sim
Não
Esta entrada de ambiente pode ser injetada no campo/método , usando o elemento <injection-target>
no descritor de implantação ou a anotação @Resource. Ao usar a anotação @Resource para anotar
um campo de instância ou setter método de entrada de ambiente, os elementos authenticationType
shareable da anotação não deve ser utilizado, uma vez que as entradas ambiente simples não exigi
autenticação e nem são compartilháveis
<injection-target>
<injection-target-class>br.com.StatBean</injection-target-class>
<injection-target-name>filterActive</injection-target-name>
</injection-target>
ou
...
@Resource(name="filterFlag ")
private boolean filterActiv
...
Quando usamos a anotação @Resouce em variáveis de ambiente, somente o elemento name está
disponível e se não houver declaração sobre o ENC no xml, somente a anotação não criara uma
entrada no ENC do EJB.
Também podemos recuperar essa entrada de ambiente pelo EJBContext.lookup ou usando o
InitialContext.
Referencias EJB
Referencia de EJB, são referencias a business interfaces, no-interface views ou home interfaces de
outros EJB.
Definindo referencia usando anotações de injeção
Quando injetamos uma referencia de outro EJB dentro de um EJB em um campo ou método setters,
podemos injetar um tipo que pode ser no-interface view, uma local ou remote interface de negocio
.Quando queremos prover um nome personalizado de um EJB que pode ser injetado, nos usamos o
elemento name da anotação @Stateful ou @Stateless.
@Stateless(name=beanRef")
public class Bean implements BeanLocal {…}
@EJB(beanName="beanRef")
private BeanLocal bean;
...
Definindo referencia usando o descritor de implantação
Uma referencia de outro EJB dentro de um EJB pode ser referenciado também pelo descritor de
implantação, os elementos <ejb-ref> ou <ejb-local-ref> fazem essa referencia.
Um classe anotada com a anotação @EJB também pode ser usado para declarar referências a outros
EJBs.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
...
<ejb-local-ref>
<ejb-ref-name>AnotherReferencedBeanRef</ejb-ref-name>
Especifica o nome de EJB para injetar referência
<ejb-link>BeanRef</ejb-link>
pode ser usado, ao invés do elemento ejb-link
<lookup-name>java:global/EJbInj/BeanRef</lookup-name>
</ejb-local-ref>
</session>
</enterprise-beans>
</ejb-jar>
Desta forma podemos obter a referencia do EJB programaticamente pelo lookup ou usando o
elemento <injection-target> para referencia um campo/método dentro da classe EJB.
Sobreescrevendo a anotação @EJB com o descritor de implantação
Existem as seguintes regras relativas para sobrescrever uma anotação @EJB com um descritor de
implantação:
•
•
O elemento name das anotações @Stateless, @Stateful, @Singleton ou @MessageDriven
deve ser o mesmo que o elemento <ejb-name> usado no descritor de implantação.
O tipo do elemento especificado no descritor de implantação, <remote>, <local>, <remotehome> ou <local-home> e qualquer bean referenciado pelo elemento <ejb-link> deve ser
atribuído para o tipo especificado por:
• O elemento beanInterface da anotação @EJB
• O tipo da instancia do campo anotado com a anotação @EJB
• O tipo do parâmetro do método setter anotado com a anotação @EJB
Ou seja, você só pode substituir um EJB que está sendo injetado em um outro EJB que pode
ser atribuído ao mesmo campo ou é compatível com o tipo de parâmetro do método setter.
•
•
Qualquer description no descritor de implementação substitui o elemento de description na
anotação @ EJB
Se um elemento <injection-target> é especificado no descritor de implementação, ele deve
nomear exatamente o campo de instância ou setter método anotado com a anotação @EJB.,
Referencias WebService
Usando a anotação @WebServiceRef ou @WebServiceRefs, uma ou mais referencia de WebService
pode ser injetadas dentro de EJB.
Referências de recurso Connection Factory gerenciado.
Um recurso de fabrica de conexão gerenciado, é por exemplo um objeto javax.sql.DataSource que é
uma fabrica que cria conexões “java.sql.Connection” a um gerenciado de recurso.
As referências a essas fábricas de conexão são entradas especiais no ambiente EJB.
Definindo referencia de recurso de fabricas de conexões gerenciadas usando anotações de
injeção
Usando a anotação @Resource em uma instancia de campo ou em um método setter, permite
referências ao recurso gerenciado de connection factories a ser injetados dentro do EJB.
O elemento authenticationType pode ser especificado se o container ou a aplicação é responsável pela
autenticação, o elemento shareable indica se as connections obtidas da factory pode ser
compartilhadas ou não.
Ex:
@Stateless
public class WarehouseInventoryBean {
...
/* connection factory. */
@Resource(name=”jdbc/FactoryDS”)
javax.sql.DataSource factoryDS;
...
public int countItems(ItemId inItemId) {
...
java.sql.Connection connection = factoryDS.getConnection();
...
}
}
Definindo referencia de recurso usando o descritor de implantação
Recursos connection factory gerenciados são definidos no descritor de implantação usando o
elemento <resource-ref>.
Ex:
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
<resource-ref>
<res-ref-name>jdbc/FactoryDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<!-- indica se uma conexão obtida a partir da
fábrica de conexão pode ser compartilhada por outros EJBs na mesma
aplicação utilizando o mesmo recurso na mesma transação contexto. O padrão
é shareable. -->
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
...
</session>
</enterprise-beans>
</ejb-jar>
Está referencia de recurso pode ser injetada diretamente no campo/método com o elemento
<injection-target>
Recuperando programaticamente um recurso connection factory gerenciado
Para ser capaz de recuperar um recurso gerenciado programaticamente de dentro do código EJB, o
bean deve seguir alguns procedimentos :
•
•
•
•
Declarar um recurso connection factory gerenciado no descritor de implantação.
Não é obrigatório, mais é recomendado que o recurso seja organizado em diferentes contextos
• JDBC DataSource no subcontexto “java:comp/env/jdbc”
• JMS connection factories no subcontexto “java:comp/env/jms”
• JavaMail connection factories no subcontexto “java:comp/env/mail”
• URL connection factories no subcontexto “java:comp/env/url”
No código, o recurso pode ser procurado usando JNDI ou o método lookup do EJBContext.
Invocar o recurso connection factories gerenciado para obter uma ou mais conexões,Ex:
@Stateless
public class BeanDB {
@Resource
private SessionContext sessionContext;
public void update(ItemId id, String name){
/*Lookup usando o JNDI name, note que o prefixo
“java:comp/env/” é embutido*/
javax.sql.DataSource factoryDS = sessionContext.lookup("jdbc/AppDB"));
java.sql.Connection connection = factoryDS.getConnection();
}
}
Referencia de recursos de ambientes
Para injetar uma referencia de um recurso de ambiente também usamos a anotação @Resource no
campo ou no método setter. Os recursos de ambientes ,não são compartilhados e não requer
autenticação, então os elementos authenticationType e shareable da anotação @Resource não deve
ser usados .
A única coisa que diferencia uma injeção de recurso de ambiente(resource environment) de recurso de
entradas (resource entries) é o tipo de dados que é injetados não é permitido com injeção de entradas.
Definindo referencia de recurso de ambiente usando anotações de injeção
Para injetar uma referencia de recurso de ambiente, usamos a anotação @Resource especificando o
name JNDI referente ao recurso a ser injetado.
Ex:
@Stateful
@LocalBean
public class Bean {
@Resource(name="resref/ConfigEnvRef ")
private Properties configEnvRef;
...
}
Definindo referencia de recurso de ambiente usando o descritor de implantação
Referencia de recursos de ambiente podem também ser declarados usado o elemento <resource-envref> no descritor de implantação
<ejb-jar>
<enterprise-beans>
<session>
<!-- name ejb para sobreescrever a configuração da anotação-->
<ejb-name>Bean</ejb-name>
<resource-env-ref>
<!-- JNDI name relativo a java:comp/env . Obrigatório. -->
<resource-env-ref-name>resref/ConfigEnvRef</resource-env-refname>
<!-- Tipo de referencia . Opcional . -->
<resource-env-ref-type>java.util.Properties</resource-env-reftype>
<injection-target>
<injection-target-class>br.com.Bean</injection-targetclass>
<injection-target-name>configEnvRef</injection-targetname>
</injection-target>
</resource-env-ref>
</session>
</enterprise-beans>
</ejb-jar>
A referência de recurso de ambiente também devem ser definidas no servidor de aplicativos em que o
EJB é para ser executado.
Recuperando programaticamente referencia de recurso de ambiente
As referencias de recursos de ambiente pode ser recuperadas usando InitialContext ou EJBContext
Os procedimentos para definir e acessar um referencia de recurso de ambiente são:
•
•
Definir o recurso no container aonde a aplicação está executando
No descritor de implantação declarar o elemento <resource-env-ref> no EJB que será lookup
o recurso
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
<resource-env-ref>
JNDI name relativo a java:comp/env, obrigatório. -->
<resource-env-ref-name>resref/ConfigEnvRef</resourceenv-ref-name>
Tipo de referencia, opcional se um injection target é
especificado , caso contrário é obrigatório -->
<resource-env-ref-type>java.util.Properties</resourceenv-ref-type>
</resource-env-ref>
</session>
</enterprise-beans>
</ejb-jar>
Referencia de Message Destination
Message Destination são referencias para destino de mensagens, geralmente Topic JMS ou Queue
JMS, que o EJB pode usar para produzir ou consumir mensagens. Uma referencia de message
destination adiciona um nome para o ambiente EJB, pelo qual o EJB pode procurar referencias de fila
ou tópico para consumir ou produzir mensagens. Além disso, a fila ou tópico deve ser criado no
servidor de aplicativos, exceto no caso especial com links de destino da mensagem.
Configurar uma referencia de Message Destination no descritor de implantação
Configuração de referência de message destination usando o descritor de implementação ejb-jar.xml
oferece a funcionalidade adicional, em comparação a configuração baseada em anotação:
•
•
Link de message destinations
Permite a criação de transmissão de mensagens em um aplicativo local entre os EJBs, um
EJB produz uma mensagem para fila ou tópico que é procurado usando um nome JNDI que
não existe fora do aplicativo. A mensagem é consumido por um EJB na mesma aplicação, que
utiliza o mesmo o nome JNDI.
Especificar se uma referência de message destination é usado para produzir ou consumir
mesagens ou ambos.
Ex:
<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>ListenerFacadeMDB</ejb-name>
<message-destination-link>ListenerMsgDest</message-destination-link>
<message-destination-ref>
<!-- Nome JNDI usado no EJB para procurar o destino
referência. Note-se que este nome não tem de corresponder
para um destino no servidor de aplicativos se uma mensagem
link de destino é usado. Quando um link de destino da mensagem é
usado, esta referência tem a ser pesquisado por meio de programação
ou de ser injetado do descritor de implementação e não pode ser
injetado usando anotações. -->
<message-destination-ref-name>jms/sTopic</message-destination-ref-name>
<!— ambos elementos opcionais -->
<message-destination-type>javax.jms.Topic</message-destination-type>
<message-destination-usage>Produces</message-destination-usage>
<!—habilita o link Message destination ligando o produtor e o
consumidor de mensagem, este elemento é definido no produtor -->
<message-destination-link>ListenerMsgDest</message-destination-link>
</message-destination-ref>
</message-driven>
...
</enterprise-beans>
<assembly-descriptor>
<!— Este elemento é usado para especificar um link entre um nome
logico de messade destinations usado no elemento <messagedestination-link> e o nome físico JNDI -->
<message-destination>
<!—nome lógico -->
<message-destination-name>ListenerMsgDest</message-destination-name>
<!— Nome físico definido no servidor de aplicação -->
<lookup-name>jms/StockInfo</lookup-name>
</message-destination>
</assembly-descriptor>
</ejb-jar>
Elementos
<message-destination-ref>
<message-destination-ref-name>
<message-destination-type>
<message-destination-usage>
<message-destination-link>
<mapped-name>
<injection-target>
Descrição
define uma referencia ao destino de uma
mensagem JMS
É o nome JNDI ENC ao qual será vinculado, é
relativo ao contexto java:comp/env
javax.jms.Queue ou javax.jms.Topic
Especifica de consome ou produz mensagem para
o destino
Cria um fluxo de mensagens
Mapeamento especifico do fornecedor
Injeta o recuso de destino
Obrigatório
Sim
Sim
Sim
Sim
Não
Não
Não
Injetar uma referencia de Message Destination usando anotações
O seguinte exemplo mostra uma connection factory JMS e uma message destination JMS é injetada
dentro de um servlet usando a anotação @Resource
...
@WebServlet(name = "MyServlet", urlPatterns = {"/MyServlet"})
public class PostMessage extends HttpServlet{
@Resource(mappedName = "jms/MyConnectionFactory")
private ConnectionFactory mMyConnectionFactory;
@Resource(mappedName = "jms/MyQueue")
private Queue mMyQueue;
...
}
Quando usamos o message destination links, o nome JNDI especificado em <message-destinationrefname> deve obrigatoriamente procurado usando lookup programaticamente ou injetado usado o
elemento <injection-target> como subelemento de <message-destination-ref> no descritor de
implantação
Recuperando referencias Message Destination programaticamente
As referencias de recursos message destination pode ser recuperadas usando InitialContext ou
EJBContext.
Referencias Persistence Unit
Referencia de unidades de persistências são referencias do ambiente de um EJB que se refere as
fabricas do gerenciador de entidades JPA. Fabricas de gerenciador de entidades (persistence contexts)
são configuradas no arquivo persistence.xml.
A fabrica do gerenciador de entidades JPA é usada para criar entity manager no JPA, também
chamado de contexto de persistência, entity manager são usado para realizar CRUD nas entidades.
Referenças persistence unit são menos usadas comparada com persistence contexts.
Referencias Persistence Unit no descritor de implantação
Se por alguma razão nos não queremos usar anotação para injetar uma referencia de persistence unit,
então nos podemos declarar no descritor de implantação afim de procurar programaticamente dentro
do código EJB.
O elemento <injection-target> do elemento <persistence-unit-ref> permite injetar dependência
diretamente no campo/método-setter da classe.
<ejb-jar>
<enterprise-beans>
<message-driven>
<ejb-name>NewMessageMDB</ejb-name>
<persistence-unit-ref>
<!-- Anexado ao "java:comp/env", torna-se um name JNDI referente ao
persistence unit pode ser feito lookup -->
<persistence-unit-ref-name>persistence/MyDB</persistence-unit-ref-name>
<!—nome persistence unit, definido no persistence.xml -->
<persistence-unit-name>AppOnlinePU</persistence-unit-name>
</persistence-unit-ref>
</message-driven>
</enterprise-beans>
</ejb-jar>
Quando sobrescrevemos uma anotação @PersistenceUnit usando o descritor de implantação , algumas
regras existe :
•
•
•
O container usa o nome JNDI, seja ele o nome padrão ou um nome fornecido da anotação
PersistenceUnit para determinar se a entrada <persistence-unit-ref> sobrescreve a anotação
O valor do elemento unitName na anotação @PersistenceUnit é sobrescrito pelo valor do
elemento <persistence-unit-name> no descritor de implantação.
O injection target se usando, deve especificar exatamente o nome do campo ou método setter
anotado.
Injeção de referencias Persistence Unit usando anotações
Injeção de referencias de persistence unit dentro de campo e métodos setters é realizada pela anotação
@PersistenceUnit, para especificar o nome da unidade de persistência é usado o elemento unitName.
Ex
...
@PersistenceUnit(unitName="AppOnlinePU ", name="persistence/MyDBFactory ")
private EntityManagerFactory factory;
...
Opcionalmente, o elemento name da anotação pode ser usado para definir um nome JNDI pelo qual
pode ser realizado um lookup, Ex: podemos realizar um lookup no seguinte nome JNDI
“java:comp/env/persistence/MyDBFactory”.
Recuperando programaticamente uma referencia em um persistence unit.
As referencias de recursos persistence unit pode ser recuperadas usando InitialContext ou
EJBContext.
Referencias Persistence Context
Referencia de unidades de persistências são referencias do ambiente de um EJB que se refere os
gerenciador de entidades JPA. Gerenciador de entidades (entity manager) são configuradas no arquivo
persistence.xml. Entity manager são usado para realizar CRUD nas entidades.
EntityManager não são thread-safe , EntityManagerFactory são thread-safe
Referencias Persistence Context no descritor de implantação
Se por alguma razão nos não queremos usar anotação para injetar uma referencia de persistence
contexto (entity manage), então nos podemos declarar no descritor de implantação afim de procurar
programaticamente dentro do código EJB.
O elemento <injection-target> do elemento <persistence-context-ref> permite injetar dependência
diretamente no campo/método-setter da classe.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
<persistence-context-ref>
<!-- JNDI name relativo a java:comp/env-->
<persistence-context-ref-name>persistence/MyPC</persistence-context-ref-name>
<!-- Nome do persistence unit, especificado em persistence.xml.-->
<persistence-unit-name>MsgDrvEx2PU</persistence-unit-name>
<!-- Tipo context de persistence (default: Transaction:
Transaction - Transaction-scoped persistence context.
Extended - Extended scope persistence context.
Contexto Extended somente pode ser usado em Statefull
-->
<persistence-context-type>Extended</persistence-context-type>
</persistence-context-ref>
</session>
</enterprse-beans>
</ejb-jar>
Quando sobrescrevemos uma anotação @PersistenceContext usando o descritor de implantação ,
algumas regras existe :
•
•
O container usa o nome JNDI, seja ele o nome padrão ou um nome fornecido da anotação
@PersistenceContext para determinar se a entrada <persistence-context-ref> sobrescreve a
anotação
O valor do elemento unitName na anotação @PersistenceContext é sobrescrito pelo valor do
elemento <persistence-unit-name> no descritor de implantação
•
•
•
Se o elemento <persistence-context-type> é especificado, então ele substitui o elemento type
da anotação
Qualquer elemento <persistence-property> introduzido no descritor de implantação, são
adicionados aos especificados na anotação, a menos que as propriedades têm o mesmo nome
que aqueles na anotação, neste caso as propriedades na anotação será sobrescrita.
O injection target se usando, deve especificar exatamente o nome do campo ou método setter
anotado.
Injeção de referencias Persistence Context usando anotações
Injeção de referencias de persistence context dentro de campo e métodos setters é realizada pela
anotação @PersistenceContext, para especificar o nome da unidade de persistência é usado o
elemento unitName.
.....
@PersistenceContext(unitName = "MyPU", type = PersistenceContextType.EXTENDED,
name="persistence/MyEntityMgr")
private EntityManager mSomeEntityMgr;
.....
Opcionalmente, o elemento name da anotação pode ser usado para definir um nome JNDI pelo qual
pode ser realizado um lookup, Ex: podemos realizar um lookup no seguinte nome JNDI
“java:comp/env/persistence/MyEntityMgr”.
O elemento type da anotação @PersistenceContext é usado para especificar o escopo do
EntityManager injetado. O valor default é PersistenceContextType.TRANSACTION.
Os possíveis valores são :
Tipo de Persistence Context
PersistenceContextType.TRANSACTION
PersistenceContextType.EXTENDED
Observações
Entity manager em scopo de transação.
Pode ser usado com qualquer tipo de EJB, é o
valor padrão.
Dá a capacidade de gerenciar o estado da
entidade em um âmbito que abrange método
várias chamadas em uma EJB, mesmo que os
métodos seja executados em diferentes
transações. Só pode ser usando em EJB Stateful.
O elemento properties permite especificar pares nome-valor para as propriedades que são passados
para o container ou provedor de persistência. Propriedades com nomes que não são reconhecidos são
ignorados.
Interface UserTransaction
EJBs com gerenciamento de transações sendo realizada por beans (BMT) pode requisitar um objeto
que implementa a interface UserTransaction e pode ser injetada ou procurada usando o nome JNDI.
Este objeto permite que o EJB gerencie os limites das transações programaticamente.
Para usar o objeto UserTransaction devemos configurar o EJB para tornar-se BMT.
Anotando a classe do EJB com @TransactionManagement
@TransactionManagement(TransactionManagementType.BEAN)
ou usando o elemento <transaction-type> no descritor de implantação
<transaction-type>Bean</transaction-type>
Caso não seja realizado essas configurações será lançada uma exceção em tempo de execução ao
tentar uma a injeção ou o lookup JND.
Referencia ao objeto UserTransaction no descritor de implantação.
Referencias do objeto UserTransaction são declaradas no ejb-jar.xml no descritor de implantação, da
mesma maneira que referencia de recusos de ambiente.
<session>
<!-- Fornecendo o nome do EJB o qual quer sobreescrever a configuração
da anotação -->
<ejb-name>BeanSt</ejb-name>
<resource-env-ref>
<!-- JNDI name da referencia. obrigatório. -->
<resource-env-ref-name>java:comp/UserTransaction</resource-env-refname>
<!-- Type da referencia. opcional. -->
<resource-env-ref-type>javax.transaction.UserTransaction</resourceenv-ref-type>
<injection-target>
<injection-target-class>br.com.BeanSt</injection-target-class>
<injection-target-name>transaction</injection-target-name>
</injection-target>
</resource-env-ref>
</session>
...
Referencia ao objeto UserTransaction injetada usando anotação.
Injetando referencia do objeto UserTransaction dentro do campo ou método setter é realizada pela
anotação @Resource. O elemento authenticationType e o shareable não deve ser usados.
@Stateful(name = "StatefulSession2Bean")
@TransactionManagement(TransactionManagementType.BEAN)
public class StatefulSession2Bean {
@Resource
private UserTransaction mUserTransaction;
...
}
Recuperando programaticamente referencia ao objeto UserTransaction.
As referencias do objeto UserTransaction podem ser recuperadas usando InitialContext ou método
lookup do EJBContext, usando um nome especial "java:comp/UserTransaction" ou o método
getUserTransaction() do objeto EJBContext
Referencias ORB
EJBs que querem usar ORB CORBA pode requisitar um objeto do tipo org.omg.CORBA.ORB para
ser injetado ou com lookup usando um nome JNDI especial "java:comp/ORB".
A referência para o ORB só pode ser utilizado dentro do EJB na qual a referencia foi injetado ou
realizado o lookup
Referencia ORB no descritor de implantação
Referencias ORB são declaradas no descritor de implantação da mesma maneira que os recurso
connection factories gerenciados.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Bean</ejb-name>
<!-- Injeta uma referencia ORB dentro do EJB. -->
<resource-ref>
<res-ref-name>java:comp/ORB</res-ref-name>
<res-type>org.omg.CORBA.ORB</res-type>
<!-- requisita uma referencia ORB que não é compartilhada,
padrão para ORB é shared-->
<res-sharing-scope>Unshareable</res-sharing-scope>
<injection-target>
<injection-target-class>br.com.Bean</injection-target-class>
<injection-target-name>corbaOrb</injection-target-name>
</injection-target>
</resource-ref>
...
</session>
</enterprise-beans>
</ejb-jar>
Injetando Referencia ORB usando anotações
Injetando referencia ORM dentro do campo ou método setter é realizada pela anotação @Resource. O
elemento authenticationType não deve ser usado.
O elemento shareable pode ser usado para requisitar uma referencia ORM não compartilhada,
configurando o valor para false.
@Stateful(name = "StatefulBean")
public class StatefulBean {
@Resource(shareable=false)
private ORB corbaOrb;
...
}
Recuperando programaticamente referencia ORB.
As referencias ORB podem ser recuperadas usando InitialContext ou método lookup do EJBContext,
usando um nome especial "java:comp/ORB".As referências ORB obtidos a partir de um JNDI pode
ser sempre compartilhada.
Referencias TimerService
EJBs que querem agendar um processamento de negocio, podem requisitar um objeto que implementa
a interface javax.ejb.TimerService e pode ser injetada ou lookup pelo nome especial JNDI
"java:comp/TimerService".
Referencias TimerService no descritor de implantação
Referencias TimerService são declaradas no descritor de implantação da mesma maneira que os
referencias de recurso de ambiente.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Bean</ejb-name>
<!-- Inject referente ao TimerService. -->
<resource-env-ref>
<!-- JNDI name da referencia. Obrigatório. -<resource-env-ref-name>java:comp/TimerService</resource-env-refname>
<!-- Type da referencia. Optional. -->
<resource-env-ref-type>javax.ejb.TimerService</resource-env-reftype>
<injection-target>
<injection-target-class>br.com.Bean</injection-target-class>
<injection-target-name>timerService</injection-target-name>
</injection-target>
</resource-env-ref>
</session>
</enterprise-beans>
</ejb-jar>
Injeção de TimerService usando anotação
Injetando TimerService dentro do campo ou método setter é realizada pela anotação @Resource. O
elemento authenticationType e o shareable não deve ser usados.
@Stateful(name = "Bean2")
public class StatefulSession2Bean {
@Resource
private TimerService timerService;
...
}
Recuperando programaticamente referencia TimerService.
As referencias TimerService podem ser recuperadas usando InitialContext ou método lookup do
EJBContext, usando um nome especial "java:comp/TimerService".
Referencia EJBContext
EJBs que querem acessar em tempo de execução o contexto fornecido pelo container EJB, podem
requisitar um objeto que implementa a interface javax.ejb.EJBContext e pode ser injetado ou lookup
usando um nome JNDI especial "java:comp/EJBContext".
Dependendo do tipo de EJB, os subtipos EntityContext, MessageDrivenContext e
SessionContext podem serem usados.
Referencias EJBContext no descritor de implatação
Referencias EJBContext são declaradas no descritor de implantação da mesma maneira que os
referencias de recurso de ambiente.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatefulSession2Bean</ejb-name>
<!-- Inject referente ao EJBContext. -->
<resource-env-ref>
<!-- JNDI name da referencia. Obrigatório. -->
<resource-env-ref-name>java:comp/EJBContext</resource-env-ref-name>
<!-- Tipo da referencia. Optional. -->
<resource-env-ref-type>javax.ejb.EJBContext</resource-env-ref-type>
<injection-target>
<injection-target-class>br.com.Bean2</injection-target-class>
<injection-target-name>ejbContext</injection-target-name>
</injection-target>
</resource-env-ref>
...
</session>
</enterprise-beans>
</ejb-jar>
Injetando referencia EJBContext usando anotação
Injetando EJBContext dentro do campo ou método setter é realizada pela anotação @Resource. O
elemento authenticationType e o shareable não deve ser usados.
@Stateful(name = "Bean2")
public class StatefulSession2Bean {
@Resource
private EJBContext ejbContext;
...
}
Recuperando programaticamente referencia EJBContext .
As referencias EJBContext podem ser recuperadas usando InitialContext com um nome especial
"java:comp/EJBContext".
Transações
Tipicamente é uma execução de unidade de trabalho que acessa um ou mais recursos compartilhados
normalmente (bases de dados, filas de mensagens, sistemas corporativos de informação - EIS, entre
outros). Unidade de trabalho é um conjunto de atividades inter-relacionadas que devem ser
completadas juntas.
ACID
Quatro características que as transações devem seguir para o sistema ser considerado seguro
Atomicidade: Todos os passos de uma transação devem ser executados com sucesso para que
a própria transação seja executada com sucesso. Se algum passo falhar a transação falhará e
todos os passos realizados até o momento da falha serão desfeitos.
Consistência: Não pode existir inconsistência nos dados da aplicação nem antes nem depois
da execução de uma transação. Ou seja, uma transação leva a aplicação de um estado
consistente para outro estado consistente, isso deve ser imposto tanto pelo sistema
transacional quanto pelo programador.
Isolamento: Alterações realizadas por uma transação não finalizada não podem afetar
operações que não fazem parte da transação. Em outra palavras, os dados que uma transação
acessa não podem sofrer interferência de qualquer outra parte do sistema até a transação ou
unidade de trabalho ser completada.
Durabilidade: Após a confirmação de uma transação, as modificações realizadas por ela
devem ser refletidas nos resources mesmo que aconteça uma falha de hardware.
Isolamento
Dirty Reads: ocorre quando uma transação lê dados ainda não comitados feitos por outra transação
(se a transação for rolledBack, os dados ficarão inconsistentes).
Repeatable Reads: garante que mesmas leituras na mesma transação retornem sempre o mesmo
resultado. Pode ser feito com lock, que impede outra transação de alterar ou com snapshot do dado,
que retorna os mesmos dados durante a transação.
Phantom Reads: no curso de uma transação, duas leituras iguais apresentam resultados diferentes
porque outra transação alterou os dados.
Locks
Controlam como transações acessam dados concorrentemente.
Read Locks: transações podem ler dados, mas não escrever (pode ser em nível de registro, bloco de
registros ou tabela).
Write Locks: previne outras transações de fazer escritas, mas a transação com o lock pode, o que
pode gerar dirty reads (ler dados não comitados) pelas outras transações e pela própria que escreve.
Exclusive Write Locks: não permite que outras transações leiam ou escrevam até a transação com o
lock acabar
Snapshots: cada transação trabalha com um snapshot do início da transação.
Níveis de isolamento de transações
Read uncommited: permite ler dados não comitados.
Read commited: dados sendo alterados por outras transações não podem ser lidos.
Repeatable reads: dados sendo lidos por outras transações não podem ser alterados.
Serializable: a transação possui privilégios de leitura e escrita exclusivos.
Consistência e performance são inversamente proporcionais.
O nível de isolamento pode ser definido na API de banco (JDBC):
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE).
JTS (Java Transaction Service) e JTA (Java Transaction API)
JTA fornece uma interface padrão e permite que você demarcar transações de uma forma que é
independente da execução do gerenciador de transações.
O JEE implementa o gerenciador de transações com JTS que é a implementação java do OTS (Object
Transaction Service). Mas o código não chamar os métodos JTS diretamente. Em vez disso, ele
chama os métodos JTA, que, em seguida, chamar os de nível mais baixo rotinas JTS. Portanto, JTA é
uma interface de transação de alto nível que o aplicativo usa para controlar a transação. e JTS é uma
interface de operação de baixo nível e EJB usa nos bastidores (o código do cliente não interage
diretamente com JTS. Baseia-se em serviço de transação objeto (OTS), que faz parte do CORBA.
Transação Local ou Distribuída
Quando as alterações realizadas por uma transação afetam apenas um resource (bases de
dados, filas de mensagens, sistemas corporativos de informação - EIS, entre outros), dizemos
que a transação é local. Caso contrário, se dois ou mais resources são modificados por uma
única transação ela é dita distribuída.
@TransactionManagement : especifica se CMT ou BMT será usado por um bean.
Exemplo de mapeamento com anotação:
@TransactionManagement(TransactionManagementType.BEAN)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Stateful
public class StatefullEJB {...}
Exemplo de mapeamento com XML
<ejb-jar>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>TravelAgentEJB</ejb-name>
<method-param>*</method-param>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Em MDBs apenas NOT_SUPPORTED e REQUIRED podem ser utilizados, já que os outros estados
se referem ao cliente chamador, que o MDB não tem.
Em EJB Endpoints não se pode usar MANDATORY, pois não propaga a transação do cliente.
Container Managed Transaction (CMT)
O Container inicia, comita e faz roolback usando JTA, tudo que você precisa dizer ao
container é como gerenciar a transação usando anotações ou configuração no DD. O
Container automaticamente assume que você está usando CMT
@javax.ejb.TransactionAttribute: especifica com o Container deve tratar as transação, pode
ser usado em um método especifico ou em um bean inteiro, o padrão é REQUIRED.
O atributo é definido utilizando a enumeração javax.ejb.TransactionAttributeType que são :
Atributos Transacional
Atributo
Transacional
REQUIRED
REQUIRED
REQUIRES_NEW
REQUIRES_NEW
SUPPORTS
SUPPORTS
MANDATORY
MANDATORY
NOT_SUPPORTED
NOT_SUPPORTED
NEVER
NEVER
Já existia uma
transação
aberta?
NÃO
SIM
NÃO
SIM
NÃO
SIM
NÃO
SIM
NÃO
SIM
NÃO
SIM
O que o EJB Container faz?
Abre uma nova transação
Usa a transação que já estava aberta
Abre uma nova transação
Abre uma transação e Suspende a que estava aberta
Não faz nada
Usa a transação que já estava aberta
Lança EJBTransactionRequiredException
Usa a transação que já estava aberta
Não faz nada
Suspende a que estava aberta
Não faz nada
Lança EJBException
REQUIRED : caso a transação propagada a partir do cliente e o método indica que a transação deveria
ser desfeita, o container não só desfaz a transação inteira como lança um
javax.transaction.RollbackException para o cliente.
REQUIRED_NEW : caso a transação propagada a partir do cliente ele suspende a transação e inicia
uma nova, isso significa que o sucesso ou fracasso da nova transação não traz nenhum efeito para o
cliente, use quando não queira afetar o cliente.
SUPORTS : Usualmente usado para leitura
MANDATORY : Usualmente usado quando quiser assegurar que o cliente falhe caso a transação
também falhe.
NOT_SUPPORTED : Usualmente usado quando requer performance e também é usado tipicamente
pelo MDB
NEVER : Usualmente usado quando você quer assegurar que o cliente não acesse o método
transaccionalmente, este atributo é pouco usado
Obs: MDB só permite o uso de REQUIRED e NOT_SUPPORTED
Obs: MANDATORY não pode ser usado em WebService
Rollback com SessionContext em um CMT
Usado quando queremos gerar um rollback devido algum erro que é identificado pela aplicação, não
podemos lançar uma exceção de aplicação porque o rollback não será feito.
Podemos marcar a transação corrente para rollback através do setRollbackOnly() do Session Context
que pode ser obtido através de injeção com a anotação @Resource, porem a transação não é revertida
imediatamente, mais uma flag é definido no container para fazer o rollback de fato quando estiver na
hora de finalizar a transação, ou seja, depois que o método retorna. Esteja seguro de estar em um
contexto transacional ao marca a transação para sofrer rollback, tipicamente você só pode estar seguro
usando (REQUIRED, REQUIRED_NEW ou MANDATORY), se não estiver em um contexto
transacional, uma java.lang.IllegalStateException é lançada.
o setRollbackOnly() destrói a instancia do bean?
setRollbackOnly() e getRollbackOnly() só podem ser usado em CMT contra atributos transacionais
(REQUIRED, REQUIRED_NEW ou MANDATORY) caso contrario uma uma
java.lang.IllegalStateException é lançada.
Definir o tempo limite de uma transação usando CMT é suportado somente por DD ou anotação
especifica do servidor
Bean Managed Transaction (BMT)
As operações de transações como iniciar, comitar e fazer roolback fica de responsabilidade do EJB
(Session Beans e MDBs)usando a UserTransaction e não do Container.Bem de entidade nunca podem
ser beans BMT
A UserTransaction pode ser obtida através da busca JNDI (o servidor da aplicação disponibilizada a
UserTransaction pelo nome JNDI java:comp/UserTransaction, este código pode ser usado fora do
EJB) , EJBContext (context.getUserTransaction(), só pode usar este método se estiver usando BMT
caso contrario é lançada uma java.lang.IllegalStateException) ou injetando @Resource.
Somente beans BMT podem usar essa interface.
Chamadas repetitivas ao método EJBContext.getUserTransaction() retorna uma referencia ao mesmo
objeto UserTransaction.
A interface UserTransaction
void begin() throws IllegalStateException, SystemException – IllegalStateException se já existe uma
transação.
void commit() throws IllegalStateException, SystemException, TransactionRolledbackException,
HeuristicException, HeuristicMixedException – IllegalStateException se não associado a uma
transação.
int getStatus() – retorna uma constante javax.transaction.Status com os seguintes void rollback()
throws IllegaStateException, SecurityException, SystemException
void setRollbackOnly() throws IllegalStateException, SystemException
void setTransactionTimeout(int seconds) throws SystemException
begin : cria uma transação de baixo nível e o associa à thread concorrente, se chamar o begin mais de
uma vez na thread atual um NotSupportedException é lançada, uma vez que Java EE não suporta
transações aninhadas, o método “commit” e “rollback” remove a transação anexada a thread,
enquanto o commit envia um sinal de sucesso para o gerenciador de transação o rollback abandona a
transação atual. Não confunda o setRollbackOnly da interface UserTransaction com a do
EJBContext.
O getStatus() é uma versão mais robusta do getRollbackOnly() no mundo CMT, ao invés de retornar
um boleano retorna um inteiro com status da transação corrente
A interface javax.transaction.Status
STATUS_ACTIVE : A transação associada está ativa.
STATUS_COMMITTED : A transação associada foi comitada
STATUS_COMMITTING : A transação está em processo de commit
STATUS_MARKED_ROLLBACK : A transação está marcada para fazer rollback
STATUS_NO_TRANSACTION : Não há transação associada a thread corrente
STATUS_PREPARED : A transação associada esta em estado de preparação porque
todos recursos concorda em fazer commit
STATUS_PREPARING : A transação associada esta se preparando para ser comitada e
espera a resposta de recursos subordinados
STATUS_ROLLEDBACK : A transação associada foi revertida
STATUS_ROLLING_BACK : A transação está em processo de rollback
STATUS_UNKNOWN : A transação está em status desconhecido
BMT nunca pode juntar a uma transação existente, Transação existente são sempre suspensa quando
um BMT é chamado.//Verificar se isto está correto.
Exceptions e Transação
Quando exceptions ocorrem, transações podem ser abortadas pelo EJB Container. Devemos entender
a classificação das exceptions para saber quando as transações serão abortadas.
Na arquitetura EJB, as exceptions são classificadas em dois grupos:
System Exceptions: Todas Unchecked Exceptions e as java.rmi.RemoteException, por padrão, são
consideradas System Exceptions.
O Container trata exceções de sistemas automaticamente e sempre fara isto :
- Reverter a transação
- Registrar Log
- Descartar a instancia
Ao descartar a instancia, no caso do Stateful destrói o estado conversacional com o cliente e
invocações subsequentes do cliente resultam em uma NoSuchEJBException que é uma subclasse de
RuntimeException, no caso do MDB o bean seria descartado e se fosse um bean BMT a mensagem
poderia ou não ser entregue dependendo do modo de reconhecimento com o provedor JMS, no caso
do bean CMT o container reconheceria como não entregue.
No beans de sessão, quando um exceção de sistema ocorre a instancia é descartada, uma runtime é
chamada ser o cliente for local ou remote.
Se o cliente iniciou a transação, que então foi propagada para o EJB uma exceção de sistema será
capturada pelo Container e será relançada com um javax.ejb.EJBTransactionRolledbackException é
um subtipo de runtime.
Se o cliente não propagou a exceção então é lançado como EJBException.
Descartar a instancia tanto chamadas em método de negócio quando chamados em métodos de callback.
Application Exceptions: Todas Checked Exceptions exceto as java.rmi.RemoteException, por
padrão, são consideradas Application Exceptions.
Por padrão, quando um método de um Session Bean lança uma system exception, o EJB Container
aborta a transação corrente. Por outro lado, quando uma application exception é lançada, o EJB
Container não aborta a transação corrente.
Uma exceção de sistema sempre é lançada como a exceção real, e não são empacotada.
Podemos utilizar a anotação @ApplicationException ou <application-excepyion> no DD para alterar
a classificação de uma System Exception e a mesma anotação pode alterar o comportamento padrão
para rollback das Application Exceptions.
@ApplicationException(rollback = true)
public class MyException extends Exception {}
ou
<ejb-jar>
<assembly-descriptor>
<application-exception>
<exception-class>br.com.MyException</exception-class>
<rollback>false</rollback>
</application-exception>
</assembly-descriptor>
</ejb-jar>
Propagação de transações BMT
Stateless e MDBs devem iniciar e completar transação no mesmo método, mais Stateful
podem iniciar em um método e finalizar em outro.
Quando um cliente que já faz parte de uma transação invoca um método de transação BMT, a
transação do cliente é suspensa até o método retornar.
Regras de propagação
Quando um EntityManager em escopo de transação é invocado fora de transação, ele cria seu
próprio escopo de persistência e quaisquer objetos gerenciados são desacoplados.
Quando um EntityManager em escopo de transação é invocado de dentro de escopo transacional,
aproveita o contexto de persistência ou cria um novo se não existe (propagação do contexto de
persistência).
Se um EJB com um contexto de persistência de transação invoca um stateful com contexto de
persistência estendido é disparado um erro.
Se um stateful estendido invoca um EJB de escopo transacional, o escopo do contexto de
persistência é propagado.
Se um EJB invoca outro de um diferente escopo de transação, o contexto de persistência não é
propagado.
Se um stateful estendido invoca outro com escopo estendido, um erro ocorre, pois stateful injetado
em outro deve compartilhar o mesmo contexto de persistência.
javax.ejb.SessionSynchronization
A interface javax.ejb.SessionSynchronization permite estender o ciclo de vida do stateful para
receber notificações referentes a transações.
void afterBegin() throws RemoteException
void beforeCompletion() throws RemoteException
void afterCompletion(boolean committed) throws RemoteException
Ciclo de vida stateful estendido
Se um stateful está envolvido em uma transação, ele não pode ir para um diferente contexto de
transação. Essa nova transação causará um erro. @Remove também causará um erro
Contexto de persistência conversacional
Ao criar um contexto de persistência estendido fora de um contexto transacional, as alterações são
enfileiradas até que este contexto seja associado a uma transação.
INTERCEPTADORES
Interceptadores são objetos capazes de interceptar chamadas de métodos ou sobre evento no ciclo de
vida dos EJBs.
As classes Interceptadoras tem os mesmo ciclos de vidas dos EJBs que elas interceptam, considere
uma classe interceptadora como uma extensão da instanciado EJB, essas classe
são criadas justamente com as instancia dos beans, elas são destruídas , apassivadas e ativadas
justamente com suas instancias do EJB. Além disso é importante observar
que elas tem as mesma restrições dos beans ao quais ela está anexada. Por exemplo você não pode
injetar um contexto estendido em uma classe interceptadora se esse
interceptor não interceptar um Statefull.
InvocationContext
Um método interceptador recebe um Invocation Context como parâmetro. Através dos Invocation
Context, os métodos interceptadores podem acessar a instância do Session Bean que será utilizada
para atender a chamada, descobrir qual método de negócio será executado, quais parâmetros foram
passados e até mesmo trocar os parâmetros antes de chegar no método de negócio. Veja os métodos
disponíveis nessa interface.
public interface InvocationContext
public Object getTarget();//retorna uma referencia a instancia do EJB alvo.
public Method getMethod();// retorna java.lang.reflect.Method que representa o método real do EJB
sendo invocado
public Object[] getParameters();//retorna os parâmetros do método invocado
public void setParameters(Object[] args);// permite modificar os parâmetros do método invocado
public java.util.Map<String, Object> getContextData();// retorna uma Map que permanece ativo por
toda a invocação dos métodos, interceptores podem usar esse objeto para passar dados contextuais
entre si.
public Object proceed() throws Exception; // método para prosseguir com a execução, se outro
interceptor precisa ser invocado como parte da chamada do método, então proceed() chama o método
@AroundInvoke deste outro, se nenhum outro interceptor precisa ser chamado então o container EJB
chama o método real que o cliente está invocando, proceed() deve ser chamado pelo código
interceptado, ou o método do EJB real nunca será chamado.
Com interceptores você pode abortar uma invocação antes de ela alcançar o método real do EJB
chamando uma exceção.
Ordem dos Interceptadores
A ordem na qual os interceptadores são executados pode afetar o funcionamento da aplicação. A
especificação dos interceptadores define a seguinte ordem:
1. Default Interceptors
2. Class-Level Interceptors
3. Method-Level Interceptors
4. Internal Interceptors
Quando dois ou mais Default Interceptors estão associados a um método de negócio, eles serão
executados na ordem em que foram definidos no ejb-jar.xml.
Quando dois ou mais Class-Level Interceptors estão associados a um método de negócio, eles
serão executados na ordem em que foram declarados na anotação @Interceptors.
Quando dois ou mais Method-Level Interceptors estão associados a ummétodo de negócio, eles
serão executados na ordem em que foram declarados na anotação @Interceptors.
Existe dois tipos de Interceptores, interceptores de método e de eventos do ciclo de vida.
Interceptors de método
Podem ser usado em um classe interceptadora ou na própria classe do EJB
Não há restrições em relação a visibilidade desse método, ou seja, ele pode
ser público, protegido, padrão ou privado. Contudo, ele deve possuir uma assinatura compatível com
o seguinte formato:
@AroundInvoke
public Object interceptador ( InvocationContext ic) throws Exception
Interceptador interno (dentro da classe)
Um interceptador interno é criado quando um método interceptador é definido dentro de um
Session Bean. Cada Session Bean pode ter no máximo um interceptador interno. Um interceptador
interno atua em todos os métodos de negócio do seu respectivo Session Bean e o é o ultimo
interceptor a ser invocado antes do método real.
Interceptador interno(classe externa)
Os interceptadores externos são criados quando um método interceptador é definido fora de um
Session Bean em uma classe comum. Novamente, não mais do que um método interceptador pode ser
definido em uma mesma classe.
Um método @AroundInvoke empacota a chamada ao seu método de negócio e é invocado na mesma
pilha de chamadas Java e no mesmo contexto de transação e de segurança do
método do EJB que ele está interceptando.
O Parâmetro javax.interceptor.InvocationContext é uma representação genérica do método de negócio
que o cliente está invocando
Aplicando Interceptors
Um ou mais interceptadores podem ser aplicados a todos os EJBs dentro de uma implantação, a todos
os métodos de um EJB ou em um único método
@Interceptors pode ser usado na classe ou em um método individual.
@Interceptors ({ LoggingInterceptor .class , SegurancaInterceptor . class })
public double soma ( double a, double b){
return a + b;
}
Ou para o EJB
@Stateless
@Interceptors ({ LoggingInterceptor . class })
class CalculadoraBean {
Interceptores de metodo via XML
Correspondente a @Interceptors no XML DD para método especifico
<interceptors>
<interceptor>
<interceptor-class>br.IntercptMethod</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>br.EJBNam</ejb-name>
<interceptor-class>br.IntercptMethod</interceptor-class>
<method>
<method-name>salvar</method-name>
<method-params>
<method-param>br.PessoaDO</method-param>
</method-params>
</method>
</interceptor-binding>
</assembly-descriptor>
O elemento<method-params> só é necessário para métodos reutilizável, pois o Container precisar
desses parâmetros para conseguir distinguir o método correspondente
Interceptores de classe via XML
<interceptors>
<interceptor>
<interceptor-class>br.IntercptClass</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>br.SessionB</ejb-name>
<interceptor-class>br.IntercptClass</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
Interceptores padrão
Interceptadores externos também podem ser associados a métodos de negócio através de
configurações adicionadas no arquivo de configuração do EJB, o ejb-jar.xml. Esse arquivo deve ser
colocado em uma pasta chamada META-INF dentro do módulo EJB da aplicação.
Interceptores padrão só podem ser aplicados usando XML no DD. neste caso é aplicado um ou mais
interceptores em um ejb-jar em particular.
<interceptors>
<interceptor>
<interceptor-class>br.IntercptDefault</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>br.IntercptDefault</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
Desativando Interceptores
Podemos excluir osDefault Interceptors e os Class-Level Interceptors através das anotações
@ExcludeDefaultInterceptors e @ExcludeClassInterceptors respectivamente.
A anotação @ExcludeDefaultInterceptors pode ser aplicada em ummétodo de negócio ou no
Session Bean.
javax.interceptor.ExcludeDefaultInterceptors // Desativa Interceptores padrão, pode ser usado na
classe EJB ou método.
Correspondente no XML DD
<assembly-descriptor>
<interceptor-binding>
<ejb-name>br.EJBNam</ejb-name>
<interceptor-class>br.IntercptFull</interceptor-class>
<exclude-default-interceptors/>
</interceptor-binding>
</assembly-descriptor>
javax.interceptor.ExcludeClassInterceptors // Desativa Interceptors de classe, pode ser usado em
metodos.
Correspondente no XML DD
<assembly-descriptor>
<interceptor-binding>
<ejb-name>br.EJBNam</ejb-name>
<interceptor-class>br.IntercptFull</interceptor-class>
<exclude-class-interceptors/>
</interceptor-binding>
</assembly-descriptor
Interceptadores e Injeção
Interceptadores permanecem no mesmo ENC do EJBS que eles interceptam.
Como ocorrem com os EJBs, as anotações criam entradas adicionais no ENC do EJB a qual a classe
interceptadora está vinculada, por exemplo, um contexto de persistencia
na classe Interceptor como name entityManage estaria disponível no JNDI com a string
java:comp/env/com.titan.interceptors.AuditInterceptor/entityManage .
Injeção XML no interceptor
O elemento <interceptors> é um novo elemento de primeiro nivel no <ejb-jar>
Interceptores de eventos do ciclo de vida do EJBs.
Não apenas é possível interceptar invocações de um método EJB, mais também interceptar eventos do
ciclo de vida do EJB
Método de interceptação
@<callback-annotation> void <nome-metodo>(javax.interceptor.InvocationContext
invocationContext )
Este método deve ser void e não lançar exceções verificadas.
O invocationContext.getMethod() em interceptadores de ciclo de vida retorna null.
Agendamento
TimerService
O TimerService é um recurso do sistema contêiner EJB que fornece um API que podem ser usado
para agendar programaticamente timers em datas especificadas, períodos e intervalo de tempos, um
exemplo é usar o TimerService em um EJB @Singleton com @Startup e programar no
@PostConstruct o agendamento.
Para usar o Timer Service o EJB deve implementar a interface javax.ejb.TimedObject que define um
único método ejbTimeout ou usar a anotação @javax.ejb.Timer em qualquer método, ambos método
deve retorna void e receber um objeto javax.ejb.Timer como parâmetro. Quando a data/hora
agendada é alcançada ou o intervalo de tempo transcorrer, o container invoca o método de retorno.
Um EJB se registra para receber uma notificação utilizando uma referencia ao TimerService, que
pode ser obtido através da JNDI lookup , EJBContext ou injetada com a anotação Resource. Os
alarmes não podem ser criados para Stateful Session Beans. Essa funcionalidade deve ser adicionada
em versões futuras da especificação Enterprise Java Beans.
O TimerConfig é um objeto que é usado como alternativa para passar informações ao Temporizador
ao invés de um objeto serializado.
Interface javax.ejb.TimerService
O TimerService permite a criação dos seguintes tipos de timers.
Calendar timers - Dependendo das configurações o timer pode ser executado uma vez ou em
intervalos recorrentes.
• createCalendarTimer(ScheduleExpression)
• createCalendarTimer(ScheduleExpression, TimerConfig) )
Interval timers - Temporizador de intervalos executa o timer em intervalos recorrentes.
• createIntervalTimer(Date, long, TimerConfig)
• createTimer(Date, long, Serializable)
• createIntervalTimer(long, long, TimerConfig)
• createTimer(long, long, Serializable)
Single-action timers - Temporizador de ação única executa o timer uma única vez.
• createSingleActionTimer(Date, TimerConfig)
• createTimer(Date, Serializable)
• createSingleActionTimer(long, TimerConfig)
• createTimer(long, Serializable)
Obs: A diferença entre Date expiration e long duration é que long é um período em milesegundos
que será calculado a partir da data atual.
Os quatros métodos TimerService.createTimer() estabelece um temporizador com um tipo diferente
de configuração: de ação única e de intervalos. Quando um temporizador é criado , o Timer Service
torna-o persistente em algum tipo de sistema secundário, assim ele sobreviverá a falhas do sistema.
Se o servidor para, os temporizadores continuarão ativos quando o servidor voltar a operar.
Os outros métodos que usa Schedule usa uma instância de ScheduleExpression para configuração e
usa regras similares da anotação @Schedule
Atributo
second
minute
hour
dayOfMonth
Valores
Default
0
0
0
*
year
timezone
[0 . . . 59]
[0 . . . 59]
[0 . . . 23]
[1 . . . 31]
[-7 . . . -1] quantidade de dias para o término do mês.
[1st, 2nd, 3rd, 4th, 5th, Last ]
[Sun,Mon, Tue,Wed, Thu, Fri, Sat]
[1 . . . 12]
[Jan, Feb,Mar, Apr,May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
]
[0 . . . 7]
[Sun,Mon, Tue,Wed, Thu, Fri, Sat]
ano com 4 dígitos
fusiorário em que o temporizador é mantido
startDate
Date qual o agendamente é ativado
none
endDate
Date qual o agendamente é finalizado
none
month
dayOfWeek
*
*
*
"" fusiorario
atual)
Exemplo :
public void agendarTimer(int seg){
TimerService tService =sessionContx.getTimerService();
ScheduleExpression schedule = new
ScheduleExpression().hour("*").minute("*").second(seg);
TimerConfig timerConfig = new TimerConfig("Info Timer Conf", true);
Timer timer = tService.createCalendarTimer(schedule , timerConfig);
}
Note que todos os-métodos setter, que têm o mesmo nome que a propriedade sem qualquer "set"
prefixo, da classe ScheduleExpression retorna o exemplo ScheduleExpression
em que o método era invocada, observe também que cada setter método vem em duas versões, uma
que dê uma string como um parâmetro outro que tomar um número inteiro como um parâmetro.
Excecões
java.lang.IllegalArgumentException - parametros invalidos como número negativo e valor null.
java.lang.IllegalStateException - Caso EJB tente invocar um dos métodos TimerService a partir de um
método em que ela não é permitida.
javax.ejb.EJBException - Caso algum tipo de exceção de sistema ocorrer.
Método timeout.
Pode ser especificado de tres maneiras , lembrando que só podemos ter dois tipos de atributos
transacionais neste método, REQUIRED ou REQUIRES_NEW
•
A classe do EJB implementar TimedObject e implementar o método ejbTimeout(Timer)
@Stateful
public class StatefullEJB implements TimedObject {
@Override
public void ejbTimeout(Timer arg0) {..
}
}
•
Anotando o método com @Timeout
@Timeout
public void metodoDeNegocio(){..}
•
Especificado no ejb-jar.xml em DD.
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<!--Um enterprise-beans pode conter um ou mais timer -->
<timeout-method>
<method-name>scheduledMethod1</method-name>
<method-params>
<method-param>javax.ejb.Timer</method-param>
</method-params>
</timeout-method>
</session>
</enterprise-beans>
Regras para metodo de timeout
•
•
•
•
•
•
Pode ser public, protected, private or package visibility, não deve ser final ou static
Deve possuir uma das seguintes assinaturas : void someMethodName() ou void
someMethodName(Timer timer)
Não deve lançar exceções verificadas
Deve ter atributos transacionais REQUIRED ou REQUIRES_NEW quando as transações do
EJB é gerenciado pelo container.
Pode ser definidos na classe de implementação do EJB ou na subclasse.
É executado sem um contexto de segurança do client.
Timer
O Timer é um objeto que implementa a interface javax.ejb.Timer. Ele representa um evento que foi
agendado para um EJB utilizando o TimerService.
Os Timers vão do momento que são agendados até sua ultima invocação do método timeout ou
cancelado.
Objetos que implementa a interface Timer, não deve ser serializados para serializar um timer deve-se
usar o objeto TimerHandle
Situações quando o container travar e depois se recuperar:
temporizadores evento único - método timeout será chamado uma vez.
Temporizador de intervalo - método timeout será chamado ao menos uma vez , mesmo que ocorreu
varias expirações.
Temporizador Scheduled- método Scheduled será chamado ao menos uma vez , mesmo que ocorreu
varias expirações.
Interface javax.ejb.Timer
public interface Timer {
void cancel();
TimerHandle getHandle();
Serializable getInfo();
Date getNextTimeout();
long getTimeRemaining();
boolean isCalendarTimer();
boolean isPersistent();
ScheduleExpression getSchedule();
}
void cancel() - Cancela o temporizador.
TimerHandle getHandle() - O TimerHandle é recuperado usando Timer.getHandle(), ele é uma
referencia que pode ser salva em um arquivo ou em algum outro recurso e então utilizado
posteriormente para recuperar acesso ao Timer e só permanece valido caso o temporizador não tenha
expirado ou cancelado, caso contrario tentar obter o Timer usando TimerHandle.getTimer()
resultará em uma java.ejb.NoSuchObjectException. Objetos TimerHandle são locais, não podem ser
usados fora do container.
Serializable getInfo() - recupera o objeto de informação.
Date getNextTimeout() - retorna a data representada por um instancia java.util.Date em que o
temporizador expirará em seguida, se o temporizador for de ação única a data retornada é a data/hora
em que o temporizador expirará.
long getTimeRemaining() - retorna o número em milissegundos antes da próxima espiração do
temporizador.ScheduleExpression getSchedule()
ScheduleExpression getSchedule() - recupera temporizadores baseados em calendário , se não for
Calendario uma execeção é lançada.
boolean isCalendarTimer() - retorna true se o timer é um temporizador baseando em calendário,
false ao contrario.
boolean isPersistent() - retorna true se o timer é persistente e sobrevive a queda e falhas do sistema,
false ao contrario.
Excecões
java.ejb.NoSuchObjectException - É chamada se invocar algum método em um temporizador de ação
única expirado ou cancelado
javax.ejb.EJBException - Caso algum tipo de exceção de sistema ocorrer.
Schedule
Na versão 3.1 da especificação Enterprise Java Beans, os alarmes podem ser criados e
automaticamente associados a métodos de timeout através da anotação @Schedule.
Schedule pode ser usado em EJB Stateless , Singleton e MDB e um EJB pode ter qualquer numero de
métodos anotados com @Schedule para agendar mais de um @Schedule em
um EJB podemos usar a anotação @Schedules
@Schedule - usado para anotar um método de timeout criado automaticamente.
@Schedules(value = { @Schedule(second="10", info="Timer 1"),
@Schedule(second="15", info="Timer 2")
})
public void bussinessTime( Timer t) {...}
@Schedules - usado para agendar múltiplos timer que são invocado no mesmo método @Timeout usado para anotar um método de timeout criado programaticamente , como alterativa o EJB pode
implementar a interface TimedObject e o método ejbTimeout
O método anotado com @Schedule pode ter visibilidade private e não precisa necessariamente ter
como parâmetro o objeto Timer, ao usar está anotação o temporizador
não precisa ser criado pelo um client EJB pois o agendamento ocorre no deployed. O Container
controla a concorrência.
Atributo da anotação @Schedule
Atributo
second
minute
hour
dayOfMonth
month
dayOfWeek
year
Valores
[0 . . . 59]
[0 . . . 59]
[0 . . . 23]
[1 . . . 31]
[-7 . . . -1] quantidade de dias para o término do mês.
[1st, 2nd, 3rd, 4th, 5th, Last ]
[Sun,Mon, Tue,Wed, Thu, Fri, Sat]
[1 . . . 12]
[Jan, Feb,Mar, Apr,May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
]
[0 . . . 7]
[Sun,Mon, Tue,Wed, Thu, Fri, Sat]
ano com 4 dígitos
Default
0
0
0
*
*
*
*
timezone
fusiorário em que o temporizador é mantido
"" fusiorario
atual)
persistent
info
indica se o timer é persistente devido a queda do servidor
String que será usada como informação do objeto timer.
true
vazio
Ex:
@Schedule(second = "20, 45",
minute = "*",
hour = "6-22",
dayOfWeek = "Mon-Fri",
dayOfMonth = "*",
month = "*",
year = "*",
info = "MyTimer")
public void timeout() {..}
// este metodo é invocado todos o dias no 20 segundo e 45 segundo entre as 6 e 22 horas de segunda
a sexta.
@Schedule(second = "15/10", minute = "*", hour = "*")
// É invocado a cada 10 segundos dentro do minuto a partir de 15 segundos.
As funcionalidade das anotações @Schedule e @Schedules também estão disponível usando o DD
ejb-jar.xml
Ex:
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<!--Um enterprise-beans pode conter um ou mais timer -->
<timer>
<schedule>
<second>15/10</second>
<minute>*</minute>
<hour>*</hour>
</schedule>
<!--Opcionalmente inicio e fim do temporizador -->
<start>2010-12-01T00:00:00Z</start>
<end>2012-12-24T00:00:00Z</end>
<timeout-method>
<method-name>scheduledMethod1</method-name>
<method-params>
<method-param>javax.ejb.Timer</method-param>
</method-params>
</timeout-method>
</timer>
</session>
</enterprise-beans>
Transação
Transação é realizada no contexto atual, ou seja, quando um bean chama createTimer() a operação é
realizada no escopo da transação atual, se a transação for revertida
o temporizador será desfeito, ou, mais precisamente , ele não é criado,
Invocar setRollbackOnly() quando o TimerService estiver sendo criado, o timer é revertido no final
do método mesmo usando o atributo TransactionAttributeType.NEVER, uma
observação é que de acordo com a especificação 3.1 métodos setRollbackOnly e getRollbackOnly não
estão disponível no @PostConstruct
• Timers podem ser criados na transação , se a transação sofrem roolback o timer não é criado
• Timers podem ser cancelados na transação , se a transação sofrem roolback o timer não é
cancelado
• Caso a transação ter sofrido roolback na chamada do método timeout a especificação especifica que
o Container deve chamar o método ao menos uma vez.
EJB(s)
Temporizador EJB SINGLETON, pode ser agendado no @PostConstruct em conjunto com a anotação
@Startup.
Temporizador EJB STATELESS , quando disparado o container seleciona uma instancia desse tipo de
bean a partir do pool de instacia e chama seu metodo,
o ejb pode acessar o TimerService a partir do @PostConstruct, @PreDestroy ou qualquer metodo de
negocio. Quando um EJB de sessão sem informação de estado implementa interface
javax.ejb.TimedObject ou usar a anotação @javax.ejb.Timer seu ciclo de vida muda a fim de incluir o
o serviço do eventos sincronizados. Iniciar um temporizador no @PostConstruct ou cancelar no
@PreDestroy é problemáticos por varias maneiras.
Temporizador EJB MDB são de varia maneiras semelhantes ao EJB Stateless, sua principal diferença
é a maneira que eles são disparados. MDB são criados em resposta de
uma mensagem entrante ou uma solução proprietária do fornecedor, a partir de um arquivo de
configuração. Quando um EJB de sessão sem informação de estado implementa interface
javax.ejb.TimedObject ou usar a anotação @javax.ejb.Timer seu ciclo de vida muda a fim de incluir o
serviço do eventos sincronizados.
Note that an EJBContext is not available at all occasions in the life-cycle of an EJB.
SEGURANÇA
Para muitas aplicações, a segurança é um aspecto obrigatório. Da segurança podemos extrair
dois processos fundamentais: Autenticação e Autorização.
O processo de autenticação consiste na identificação dos usuários através de algum tipo de certificado
(usuário e senha). Já o processo de autorização determina o que cada usuário autenticado pode acessar
dentro da aplicação.
Na plataforma Java, esses dois processos são padronizados pela especificação JAAS (Java
Authentication and Authorization Service).
As especificações Java EE e EJB fornecem um conjunto básico de serviços de segurança que os
desenvolvedores de aplicativos podem integrar declarativamente e programaticamente. Estes incluem
Realms
Em um ambiente Java EE, para realizar o processo de autenticação, devemos criar um ou mais
Realms. Um Realm é uma base de dados na qual os usuários de uma ou mais aplicações estão
cadastrados.
Autenticação : É o processo de validar a identidade do usuário
Autorização : Depois que um usuário é Autenticado em um sistema, ele vai querer interagir com o
Aplicativo. A autorização envolve em determinar se um usuário de permissão de executar certa ação.
A confidencialidade e integridade : Impede que usuário mal-intencionados interceptem pacotes de
redes e interpretem os dados A transferência de dados pode ser mantida segura por meio de serviços
de criptográficos com SSL.
Somente os beans de sessão podem ser mantidos seguros no territórios do EJB.
Autenticação : Quando um cliente remoto se conecta a um EJB é associado a ele uma identidade de
segurança até o final dessa sessão Quando um cliente invoca o método no EJB, o servidor EJB passa
implicitamente a identidade do cliente com a invocação do método, desta forma quando o objeto EJB
recebe a invocação do método, ele verifica a identidade para assegurar que o cliente é valido e tem
permissão de invocar este método.
Infelizmente a especificação EJB não define quase nada referente a Autenticação e nem como ela
acontece, também não especifica como o cliente supostamente deve obter e associar a identidade e as
redenciais, fica para o fornecedor escolher, em geral é feita usando a API JNDI:
properties.put(Context.SECURITY_PRINCIPAL, userName);
properties.put(Context.SECURITY_CREDENTIALS, pass);
InitialContext ic = new InitialContext(properties);
A única regra que a especificação especifica é como as informações de segurança são propagados do
cliente para o servidor (usando CORBA/IIOP).
Autorização : é realizada no Java EE e EJB , definindo papeis lógicos para o usuário, os papeis no
EJB de segurança no EJB são mapeados para grupos de usuário e para usuários do dia a dia quando o
bean é implantado . Esse mapeamento permite que o bean seja portável. Diferente da autenticação, a
autorização é algo que a especificação EJB define claramente.
Segurança declarativa no EJB
@DeclareRoles : usado para declarar papeis somente em nível de classe, Se nunca declararmos
papéis, o container construirá, automaticamente, uma lista de papéis verificando a anotação
@RolesAllowes, no caso de segurança programática, o uso da @DeclareRoles é obrigatória.
Outra alternativa seria especificar papéis para toda a aplicação corporativa ou modulo EJB por meio
de descritores de implantação, quando a aplicação é implantada o administrador tem que mapear cada
papel para grupos definidos no tempo de execução do ambiente.
A @DeclareRoles possui o atributo String[] value.
@DeclareRoles({ "superuser", "plainuser" })
XML (ejb-jar.xml) necessário quando usar o isCallerInRole.
Define regras de segurança local para o componente que estão mapeadas em <assemblydescriptor>.
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>StatelessSession2Bean</ejb-name>
<local-bean />
<ejb-class>br.com..ejbs.StatelessSession</ejb-class>
<session-type>Stateless</session-type>
<security-role-ref>
<role-name>superuser</role-name>//isCallerInRole
<role-link>superuser</role-link>
</security-role-ref>
<security-role-ref>
<role-name>plainuser</role-name>//isCallerInRole
<role-link>plainuser</role-link>
</security-role-ref>
</session>
</enterprise-beans>
// Define regras de segurança usada no modulo EJB. Essas regras
são mapeadas no servidor de aplicação ou em um descritor de
aplicação especifico do fornecedor, no caso do GlassFish é o sun-ejbjar.xml.
<assembly-descriptor>
<security-role>
<role-name>superuser</role-name>
</security-role>
<security-role>
<role-name>plainuser</role-name>
</security-role>
</assembly-descriptor>
</ejb-jar>
@javax.annotation.security.RolesAllowed: é o ponto crucial do gerenciamento de segurança
declarativa, essa anotação define um ou mais papéis lógicos que tem permissão de acessar o
método/classe e pode se aplicada em método ou na classe inteira do EJB, a grande flexibilidade
oferecida por essa anotação torna-se evidente quando você considera o fato de que pode sobrepor
definições de nível de classe ao replicar a anotação no novel de método (por exemplo restringir acesso
adicional para certo métodos). Possui o atributo String[] value:
Regras:
• A class-level @RolesAllowed annotation in the superclass applies to the (inherited) methods
defined in the superclass.
• A method-level @RolesAllowed annotation in the superclass applies to the (inherited)
method which it annotates.
• Não herda regras de segurança da superclasse
• A nível de método sobrescreve o nível de classe
@javax.annotation.security.PermitAll: Para marcar uma classe ou método EJB a ser invocado por
qualquer papel, também é valor padrão se nenhum meta-dados , padrão ou explicito se segurança for
fornecido
Exemplo de configuração de autorização com XML:
<ejb-jar>
<assembly-descriptor>
<security-role>
<role-name>ADMIN</role-name>
<description>Administrador do sistema</description>
</security-role>
<security-role>
<role-name>MANAGE</role-name>
<description>Gerente do sistema</description>
</security-role>
<method-permission>
<role-name>ADMIN</role-name>
<role-name>MANAGE</role-name>
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>log</method-name>
</method>
</method-permission>
<method-permission>
<unchecked />
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>log2</method-name>
</method>
</method-permission>
</assembly-descriptor>
</ejb-jar>
<method-permission> cada elemento define um ou mais elementos <role-name> que declaram os
papéis que tem permissão de acessar um <method> em particular
<unchecked> é equivalente a @PermitAll.
<method> declara o método em particular que irá ser mantido seguro
<method-name> declara o nome do método em particular , pode receber um curinga * .
Declaração com curinga :
Esta declaração se aplica a todos métodos da interface do bean.
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>*</method-name>
</method>
Declaração com métodos genéricos :
Esta declaração se aplica a todos os métodos com um dado nome “byNameFull” em qualquer
interface de negocio
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>byNameFull</method-name>
</method>
Declaração com métodos específicos :
Utiliza o elemento <method-params> para identificar um método, que permite diferenciar entre
métodos reusáveis. Este elemento contem 0 ou mais elementos <method-param>, que corresponde em
ordem, a cada tipo de parâmetro (incluindo arrays multidimensionais) declarado no método. Para
especificar um método sem argumento, utilize o elemento <method-params> sem nenhum elemento
<method-param>, alinhado a ele.
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>byNameFull</method-name>
<method-params>
<method-param>br.com.domain.Pessoa</method-param>
<method-param>int[]</method-param>
</method-params>
</method>
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>byNameFull</method-name>
<method-params></method-params>
</method>
Diferenciação de remote/home/local :
O nome do método pode ser utilizado em diferentes interfaces, causando ambiguidade
Utilize o elemento <method-intf> para diferenciar métodos em interfaces locais e remotas. Possui os
5 valores : Remote, Home, LocalHome, Local, ServiceEndPoint.
<method>
<ejb-name>MyEJB</ejb-name>
<method-name>byNameFull</method-name>
<method-intf>Remote<method-intf>
</method>
@javax.annotation.security.DenyAll: Para marcar uma classe ou método EJB que não pode ser por
papel algum, pode ser usada quando a aplicação é distribuída por uma grande quantidade de ambiente
que você não vislumbrou e gostaria pode invalidar métodos ou classes
que sejam inapropriados para um ambiente em particular.
<ejb-jar>
<assembly-descriptor>
<exclude-list>
<method>
<ejb-name>MyEJB</ejb-name>
<method-intf>Local</method-intf>
<method-name>log2</method-name>//Opcinal
<method-params>//Opcional
<method-param>java.lang.String</method-param>
</method-params>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>
Esse exemplo desativa todo o acesso ao método MyEJB.log2, o elemento <exclude-list> pode
receber uma ou mais assinaturas de métodos.
@DenyAll , @PermitAll e @RolesAllowed não podem ser aplicadas simultaneamente à
mesma classe ou método.
quando um cliente invoca em um método EJB ao qual não tem permissão apropriada , o container
EJB chama um javax.ejb.EJBAccessException.
@javax.annotation.security.RunAs e DeclareRoles é usada somente em nível de classe
@javax.annotation.security.RunAs: Usada somente em nível de classe quando o EJB tem
necessidade de um papel diferente para acessar um método de outro EJB em tempo de
execução.Com @RunAs podemos temporariamente designar um papel "extra" ao "Principal"
corrente para acessar aquele método especifico de outro EJB, nota esse "Principal" só conseguiria
assumir outro papel neste ponto da aplicação, ou melhor, neste EJB. Possui o atributo String value
@Stateless
@RunAs("Admin")
public class MyBean {
public void do() {
// do something...
}
}
ou XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<security-identity>
<run-as>
<role-name>ADMIN</role-name>
</run-as>
</security-identity>
</session>
</enterprise-beans>
</ejb-jar>
Para garantir que o papel de segurança do chamador seja passado a outro EJB ignorando a run-as,
deve ser usada a tag <use-caller-identity />:
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<security-identity>
<use-caller-identity />
</security-identity>
</session>
</enterprise-beans>
</ejb-jar>
Segurança programática no EJB
O EJB também tem um pequena API programática para coleta das informações sobre uma sessão
mantida segura. a segurança programática prove acesso direto ao Principal e é
feita somente por dois métodos de segurança que são definidos na interface javax.ejb.EJBContext
public java.security.Principal getCallerPrincipal(); // da acesso direto ao Principal , representa o
contexto de autenticação atual, O único método interessante na interface "Principal" é o getName, que
retorna o nome do Principal (varia de acordo com fornecedor)
public boolean isCallerInRolle(String roleName); // O contexto EJB resgata o Principal associado a
thread corrente e verifica se em algum dos seus papéis encaixa o nome que você forneceu, você deve
usar a anotação @DeclareRoles ou <security-role-ref> no ejb-jar.xml em conjunto com este método,
caso contrário um exceção é lançada.
@Stateless
@DeclareRoles("Admin")
public class MyBean {
@Resource
private EJBContext ctx;
public void do() {
ctx.isCallerInRole("ADMIN);
ctx.getCallerPrincipal();
}
}
XML
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>MyBean</ejb-name>
<security-role-ref>
<role-name>ADMIN</role-name>
</security-role-ref>
</session>
</enterprise-beans>
</ejb-jar>
Segurança declarativa usando DD.
Empacotamento
Carregamento de classes
O carregamento de classe é iniciado pelo JVM quando ela inicia, eles são :
•
•
•
•
•
•
•
classloader boot (carregas todas classes da plataforma java (java.lang , java.util, etc).
classloader extension (carrega classes de JAVA_HOME/jre/lib/ext ou informada em Djava.ext.dir (bibliotecas de criptografia , classes de segurança)
classloader system (carrega classes da aplicação, existe diversos mecanismo para
especificar a posição das classes, por exemplo , especificar o Class-Path no arquivo
manifest)
classloader appserver
classloader EAR
classloader EJB
classloader WAR
Módulos Java EE são os blocos de construção básicos com que aplicações Java EE são montados,
conhecido como assembled. Módulos Java EE, por sua vez, são compostos de componentes Java EE
Aplicações Java EE são contida em arquivos EAR (Enterprise Application aRchive). Aplicações
Java EE pode conter um número de bibliotecas no qual uma ou mais módulos da aplicação
pode depender.
Módulos Java EE são:
•
•
•
•
•
Modulo de aplicação WEB (Web application modules)
Contido em um arquivo WAR (Web Application aRchive)
Modulo EJB (EJB modules)
Contido em arquivos EJB-JAR (componentes de negócios corporativos Java)
Modulo de clientes de aplicativos (Application client modules)
Modulo de adaptação de recursos (Resource adapter modules)
Bibliotecas (Libraries)
Contido em arquivos JAR
Componentes Java EE exigidos pela especificação Java EE 6 são:
•
•
•
•
EJBs
Enterprise Java Beans, normalmente contem a regra de negocio.
Servlets
Inclui paginas JSP , paginas JSF , filtro e ouvintes, tipicamente produz HTML que renderizar
no browser para criar a interface da aplicação
Clientes de aplicativos (Application clients)
Os programas clientes rodando em computadores desktop, normalmente chamados de fat
clients.
Applets
Componentes de interface de usuário em execução navegadores web.
Opcões de empacotamento
As seguinte opções de empacotamento disponível no EJB 3.1 são:
•
No arquivo EJB-JAR
•
Este é a maneira padrão para empacotamento EJB e também tem sido usado em
versões anteriores da especificação EJB, arquivos EJB-JAR podem se empacotado
com arquivos EAR
No arquivo WAR
EJBs podem agora ser empacotados em WAR, arquivos WAR podem se empacotado
com arquivos EAR
No arquivo JAR
•
Usando o container embutido disponível no EJB 3.1, aplicações standalone Java SE podem
agora tirar proveito de EJBs.
EJB-JAR
EJB-JAR são usados para empacotar modulo EJB standalone, o modulo pode ser construído separado
ou incluído em arquivo EAR,
Tudo no arquivo EJB-JAR é opcional
•
•
•
•
O diretório META-INF somente é necessário se o EJB-JAR tiver um arquivo
MANIFEST.MF ou ejb-jar.xml descritor de implantação ou algum outro arquivo que reside
neste diretório.
O arquivo MANIFEST.MF só é necessário se o EJB precisa incluir classes de arquivos JAR
externos para o classpath.
O arquivo ejb-jar.xml não é necessário se todas as configurações dos EJBs foram feitas
usando anotações
As classes de implementação dos EJBs, interface e outras classes podem ser incluídos,
incluindo outro arquivo JAR no classpath. As classes podem ser incluídos por que está no
arquivo EJB-JAR ou por estar em outro arquivo que é referenciado a partir do arquivo
MANIFEST.MF (incluído no classpath).
O arquivo EJB-JAR é um modulo com namespace próprio , isto significa que o arquivo EJB-JAR
pode ser incluído em um arquivo EAR junto com outro módulos que contem componentes com um
mesmo nome dos componentes do EJB-JAR.
Deploying EJBs em um arquivo JAR EJB
•
•
Se o arquivo EJB-JAR conter um descritor de implantação ejb-jar.xml e o descritor de
implantação é marcado como um metadata-complete, então anotações em classes no
arquivo EJB-JAR não serão processados.
Se o jar do EJB está incluído em um WAR, então os metadata-complete de seu
descritor de implementação não afeta se as anotações de classes EJB no WAR é
processado ou não.
<?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"
metadata-complete="true">
</ejb-jar>
WAR
Arquivos WAR são usado para empacotar modulo aplicações WEB, a partir do EJB 3.1, EJBs podem
ser construído em arquivos WAR.
Tudo no arquivo WAR é opcional
•
•
•
•
•
O diretório META-INF somente é necessário se o WAR contem um MANIFEST.MF ou
algum outro arquivo que reside neste diretório.
O arquivo MANIFEST.MF só é necessário se aplicação precisa incluir classes de arquivos
JAR externos para o classpath.
O arquivo ejb-jar.xml localizado em WEB-INF não é necessário se todas as configurações
dos EJBs foram feitas usando anotações
O descritor de implantação web.xml é opcional.
A especificação Servlet 3.0 afirma que o descritor de implementação web.xml é opcional se
todas as configurações relevantes possam ser feito usando anotações.
As classes de implementação dos EJBs, interface e outras classes podem ser incluídos,
incluindo outro arquivo JAR no classpath ou no diretório WEB-INF/lib. As classes podem ser
incluídos por que está no arquivo WAR ou por estar em outro arquivo que é referenciado a
partir do arquivo MANIFEST.MF (incluído no classpath).
Deploying EJBs em um arquivo WAR
•
•
•
•
•
Se incluído , o descritor de implantação ejb-jar.xml é aplicado a todos EJBs dentro do WAR
Todos os componentes em um arquivo WAR residem no interior de um mesmo módulo e
compartilhar um mesmo nome (JNDI) de ambiente.
Classes de implementação de EJBs, podem estar localizadas no diretório WEB-INF/classes
ou em arquivos JAR localizado em WEB-INF/lib
EJB-JAR localizados no diretorio WEB-INF/lib, só será reconhecido como arquivos
JAR regulares e não como módulos Java EE, qualquer descritor de implantação ebjjar.xml no arquivo EJB-JAR não será reconhecido pelo container, mais classes EJBs
anotadas e interfaces no arquivo dentro do diretorio WEB-INF/lib deve ser
encontrada e reconhecida pelo container.
A visualização no-interface e interface local de negocio de um EJB implantado em
um arquivo WAR somente serão visível para componentes dentro do WAR, se o
•
•
•
•
arquivo WAR é parte de um aplicativo e outros módulos da aplicação deseja acessar e
nenhuma visão no-interface e interface de negócios local de um EJB está disponível ,
então o EJB deve ser implantado em um arquivo EJB-JAR separado na aplicação.
Se um arquivo WAR conter um descritor de implantação ejb-jar.xml para EJB3.x no
diretório WEB-INF e o descritor de implantação for marcado com metadata-complete,
então as classes EJB anotadas no arquivo WAR não serão processadas.
Empacotamento de versões anteriores a EJB3.x em WAR não são suportados.
Empacotamento de classes de implementação JAX-RPC endpoint não são suportados
em arquivos WAR.
Anotações em classes EJB não será processado se não houver descritor de
implantação ejb-jar.xml e o descritor de implementação web.xml é marcado como
metadata-complete ou se a sua versão do WAR for anterior a 2.5
<?xml version="1.0" encoding="UTF-8"?>
<!-Deployment descriptor version is specified using the version
attribute
in the <web-app> element.
Whether the deployment descriptor is metadata-complete is specified
using
the metadata-complete attribute in the <web-app> element.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0" metadata-complete="true">
</web-app>
JAR
Usando o container EJB embutido, o qual é novo no EJB 3.1, é possível rodar EJBs, por
exemplo em aplicações Java SE ou em teste unitários.
Se todas configurações foram feitas usando anotações, então não existe a necessidade para
incluir o descritor de implantação ejb-jar.xml, se o ejb-jar.xml for usado, ele deve ser
localizado dentro do diretório META-INF no arquivo JAR a fim de que ele seja encontrado
automaticamente pelo container EJB embeddable.
Um arquivo MANIFEST.MF deve ser incluso se nos queremos especificar uma classe main e
o class-path da aplicação, ele não contém qualquer informação relacionada com EJB.
EAR - Enterprise Application aRchive
EAR, Enterprise Application Archive, são arquivos de nível superior do container de
aplicações Java EE.
Quando implantado um arquivo EAR , o JNDI global muda para ter um nome de aplicação inserida.
Inserido do Java EE 5, o descritor de implantação application.xml do arquivo EAR é opcional, se o
descritor de implantação application.xml é usado, o elemento <library-directory> pode ser usado
para especificar um diretório de bibliotecas, todos os arquivos JAR neste diretório são
disponibilizados no class-path de todos os componentes no EAR.
EJB-Client arquivos JAR
Opcionalmente, as classes que compõem visualização EJB do cliente, podem ser empacotadas em um
arquivo JAR separado , este arquivo é conhecido como EJB-Client.jar, este arquivo jar contem todos
EJB clients que o cliente precisa para interagir com o EJBs. A visualização do clientes EJBs consiste
nos seguintes fluxos:
•
•
•
•
•
Inteface(s) de negocio do EJB.
Superinterfaces(s) de negocio do EJB
Classes e interfaces usadas como parâmetros de métodos na interface de negocio dos EJBs
Classes e interfaces usadas como retornos de métodos na interface de negocio dos EJBs
Classes e interfaces usadas como exceções de métodos na interface de negocio dos EJBs
No módulo que contém a implementação EJB, a localização do arquivo JAR EJB-Client é
especificada no descritor de implantação ejb-jar.xml, relativo ao arquivo que contém o descritor
implantação. O fragmento de descritor de implementação abaixo especifica o local do arquivo JAR
EJB-Client ter o nome de "employee_service_client.jar" como sendo localizada no mesmo local no
arquivo EAR contendo como o arquivo (EJB-JAR ou WAR) que o descritor de implementação é
contido em:
<?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">
...
<!-- The optional <ejb-client-jar> element specifies the location,
relative to the EJB-JAR or WAR file in which this deployment
descriptor is contained, in the EAR of the EJB-client JAR file.
The EJB-client JAR contains all the classes and interfaces a
client needs to access the EJB(s) located in the archive in which
this deployment descriptor is located. -->
<ejb-client-jar>employee_service-client.jar</ejb-client-jar>
</ejb-jar>
O conteúdo do JAR EJB-Client pode ser incluído em uma de duas maneiras:
•
Por referencia
As classes e interfaces da visualização do cliente são contidos no EJB-Client JAR, que é
referenciado a partir de arquivos EJB-JAR ou WAR contendo as classes de implementação do
EJB incluído no EJB-Client.jar no classpath.
•
Por copia
As classes e interfaces da visualização do cliente são duplicadas tanto no EJB-Client.jar
como no EJB-JAR ou WAR no qual as classes de implementação do EJB são
localizadas.
Requisitos de empacotamentos
As seguintes coisas são obrigados a serem incluídos ou referenciados a partir de, todos os diferentes
arquivos de empacotamento no quais os EJBs podem ser distribuídos:
•
•
•
•
•
Classes de implementação dos EJBs
Interfaces de negocio do EJB, caso o EJB tenha interface
Interfaces de Web Service endpoint, caso um ou mais EJB sejam expostos como Web Service
Classes interceptadoras , se interceptores foram configurados.
Arquivos de classes para todas as classes e interfaces das quais os EJBs dependem, exceto
classes Java SE e Java EE
Módulo de visibilidade
•
Classes e interfaces implantadas no arquivo JAR dentro do diretório lib do arquivo
•
EAR ou usando o elemento <library-directory> no descritor de implantação
application.xml será disponibilizado a todos os módulos no EAR.
Componentes EJB em módulos EJB em um arquivo EAR são acessíveis por outros
componentes no EAR, sem qualquer configuração além Class-Path.
Componentes EJBs em um WAR no arquivo EAR não são acessíveis por componentes
•
externos do WAR.
Descritor de Implantação ejb-jar.xml
As duas regras que são provável para manipular informações de implementação EJB são:
•
•
Bean provider (Desenvolve EJBs).
Application assembler (Monta as aplicações em que os EJBs são usados).
As informações a seguir relacionadas com EJB e podem ser modificados quando as aplicações
EJBs são montados (assembled)
•
Entrada de valores de ambientes
•
•
•
Inscrição campos
Nomes da relação para EJB 2.x.
Seletores de mensagem para message driven beans
•
Atributos Timer Schedule
As informações a seguir relacionadas com EJB não podem ser modificados quando as
aplicações EJBs são montados (assembled)
•
•
Nome do esquema abstrato de um EJB (relacionadas com os beans de entidade e pode ser
modificada se sequências de consulta EJB-QL contendo nomes de esquema são modificados
de acordo).
Regra de relacionamento do elemento fonte (relacionada com os beans de entidade. Também
pode ser modificada se sequências de consulta EJB-QL contendo nomes de esquema são
modificados de acordo)
As informações a seguir relacionadas com o EJB pode, opcionalmente, ser especificado quando
um aplicativo que contém EJBs é montado (assembled).
•
•
•
•
•
•
•
•
•
•
•
•
Binding de referencias EJBs, usando o elemento <ejb-link>
Links de destinatário de mensagens
Regras de segurança
Permissões de métodos
Ordem de inicialização de Singleton Session Bean
Inicialização antecipada de Singleton Session Bean
Timeout de acesso concorrentes
Timeout de Stateful session bean
Link referente as regras de segurança
Regras de segurança
Atributos de transações de métodos de negocio, aplicado somente em EJB (CMT)
Interceptadores , configurações de interceptadores podem ser alteradas, sobrescritas
adicionados ou reordenadas.
Download

resumo_oceejbd - WordPress.com