Você está na página 1de 4

Enterprise Java Beans (EJB) e Contexts and Dependency

Injection (CDI)
Bruno Tanhole de Lima Colodel1
1
Setor de Educação Profissional e Tecnológica – Universidade Federal do Paraná
(UFPR)
brunotanholecolodel@gmail.com

1. Conceitos Básicos de EJB e CDI


Enterprise Java Beans (EJB) é um dos mais importantes componentes da plataforma Java
Enterprise Edition. O container EJB foi desenvolvido com objetivo de tornar o
desenvolvimento rápido e simplificado através de anotações (@) permitindo que o
programador foque apenas nas lógicas de negócio da aplicação. Além de realizar um
eficaz tratamento de transações, oferece serviços de persistência de dados, controle de
concorrência, envio de mensagens, serviço de agendamento, chamadas a métodos
remotos e a web services. Portanto, o EJB é um conjunto de soluções integradas e
centralizadas para suprir os problemas de desenvolvimento. Neste artigo será considerada
a última versão disponível do EJB, 3.2.
Contexts and Dependency Injection (CDI) é uma especificação que, ao fazer uso
de anotações, visa manter o acoplamento fraco entre classes dependentes. É dividido em
contextos, para controle de ciclo de vida e interações dos componentes, e injeção de
dependências, para injeção de componentes livre de erros de tipagem. Com o CDI é
possível a configuração de quase todos os relacionamentos de maneira declarativa. Neste
artigo será considerada a última versão disponível do CDI, 2.0.

2. Histórico e Especificações (JSRs)


Java Specification Requests (JSR) são descrições de especificações propostas para a
plataforma Java. A todo momento há JSRs passando pelos processos de revisão e
aprovação. Por isso, acompanhar as JSRs é uma maneira simples de manter-se atualizado.
EJB teve sua primeira versão lançada em 1998. Ao final de 1999, o EJB 1.1 já
contava com mecanismos de segurança, acesso remoto e descritores de implantação
XML. No entanto, com a criação da Java Community Process (JCP) que reúne
desenvolvedores de todo o mundo para decidir o futuro da tecnologia Java, o EJB ganhou
força. Em sua versão 2.0 de 2001 (JSR 19) trazia grandes benefícios quanto ao tempo
complexidade de desenvolvimento. Dois anos depois, em 2003, no EJB 2.1 (JSR 153) a
grande novidade foi o acesso a Web Service. Em 2006, na JSR 220, o EBJ 3.0 trouxe a
maior revolução dentre todas as versões: o uso de anotações ao invés dos trabalhosos
XMLs. Com o EJB 3.1 de 2009 (JSR 318), houve ainda mais simplificações e novas
funcionalidades como a possibilidade de empacotar projetos web em um WAR e os beans
de sessão singleton. Finalmente, com a chegada do EJB 3.2 em 2013 (JSR 345) surgiram
os interceptadores. Além disso, os Entity beans tornaram-se opcionais, uma vez que a
API de persistência ganhou sua própria especificação e agora pode ser executada fora de
um container.
Já o CDI surgiu na JSR 299 com o objetivo de integrar as tecnologias Java EE,
apoiando-se nas JSR 330 (injeção de dependências para Java) e JSR 316 (especificação
dos managed beans).

3. Tipos de EJBs e suas subdivisões


No EJB são colocadas todas as lógicas de negócio corporativas da aplicação. Os
componentes responsáveis por isso são os Beans de Sessão e os Message-Driven Beans.
Ambos são POJOs (Plain Old Java Objects), ou seja, essas classes são desprovidas de
construtores, getters e setters. Para anotar um componente no EJB basta fazer uso da
anotação “@Inject” para injetar uma instância no código sendo dispensável sua
instanciação através da palavra reservada “new”.

3.1. Beans de Sessão


Os beans de sessão são os componentes mais utilizados no EJB, uma vez que é onde toda
lógica corporativa é desenvolvida. Podem ser acessados de duas formas: local ou remota.
Por default o bean só pode ser acessado localmente, isto é, por requisições originárias do
próprio container. Neste caso é dispensado o uso de anotação. No entanto, se o acesso for
remoto, onde o bean poderá ser acessado por qualquer cliente, de qualquer container e de
qualquer parte do mundo, é necessária a implementação de uma interface e o uso da
anotação “@Remote”. Os beans de sessão estão divididos em: stateless, stateful e
singleton.
Os beans de sessão stateless (ou sem estado) contém operações que não
necessitam durar mais do que uma chamada. Nesse caso nenhum dado é guardado entre
solicitações para o uso daquele bean. Este tipo de bean também não pode ser utilizado por
mais de um usuário ao mesmo tempo. Esta característica o torna importante para
chamadas de inserção ou busca no banco de dados. Uma classe de beans sem estado é
anotada com “@Stateless”.
Ao contrário dos beans stateless, os beans de sessão stateful (ou com estado)
necessitam durar mais de uma chamada, o que significa que os estados dos objetos
modificados devem ser mantidos. Para isso cada usuário tem a sua própria instância
exclusiva do componente, o que aumenta o consumo de memória. Como solução foi
criada a anotação “@Remove” para que quando um método anotado for invocado, a
instância em questão seja excluída automaticamente. Uma classe de beans com estado é
anotada com “@Stateful”.
E quando é necessário que um bean dure mais que uma requisição, mas não pode
haver mais de uma instância para todos os usuários? Este é o bean de sessão singleton.
Após uma única instância criada, nenhuma outra poderá ser criada. Os métodos deste
bean podem ou não permitir chamadas simultâneas. Ao anotar um método com
“@Lock(LockType.READ)” permitirá chamadas simultâneas, enquanto quando anotado
com “@Lock(LockType.WRITE)” a próxima invocação acontecerá somente após o
processamento da anterior. Opcionalmente é possível utilizar a anotação “@Startup” para
inicializar o bean singleton antes mesmo da aplicação tornar-se disponível. Além disso, é
possível definir uma ordem de inicialização dos beans singleton através da anotação
“@DependsOn(“nomeDoBeanSingletonAnterior”). Uma classe de bean singleton é
anotada com “@Singleton”.
3.1. Message-Driven Beans
Message-Driven Beans são beans sem estado e gerenciáveis, utilizados para processar
mensagens de forma assíncrona. As mensagens podem ser de qualquer tipo, mas
usualmente são JMS (Java Message Service). Esta classe de bean deve ser anotada com
“@MessageDriven(mappedName=”meuDestino”)” e implementar a interface
MessageListener. O atributo “mappedName” especifica o nome do JMS de destino para
o qual o bean consumirá a mensagem.

3.3. Métodos Callback (ou Interceptadores)


Os métodos callback do EJB permitem implementar lógicas de negócio em determinadas
fases do componente. Desta forma a utilização de recursos poderá ser otimizada.
O método que for anotado com “@PostConstruct” sempre será invocado assim
que o container criar uma instância do componente EJB. Assim se torna vantajoso realizar
nesse método a abertura de uma conexão de banco de dados. O método que for anotado
com “@PreDestroy” sempre será invocado momentos antes da destruição de uma
instância do componente EJB. Assim se torna vantajoso realizar nesse método o
fechamento de uma conexão de banco de dados. As anotações “@PostConstruct” e
“@PreDestroy” poderão ser utilizadas para todos os três tipos de beans de sessão.
Outro problema a ser otimizado diz respeito a utilização de memória, ou seja,
quando há uma grande quantidade de instâncias acumuladas no servidor. De forma
automática o container EJB retira as instâncias não utilizadas da memória e as coloca em
disco. Esse processo é chamado de passivação. É nesse âmbito que surgem as anotações
“@PrePassivate” e “@PostActivate”. O método que for anotado com “@PrePassivate”
será invocado antes do componente EJB sofrer passivação. Já o método que for anotado
com “@PostActivate” será invocado após o componente EJB voltar a memória, isto é,
após ser resgatado do disco. Como consequência do problema de utilização de memória,
somente beans de sessão stateful podem receber as anotações “@PrePassivate” e
“@PostActivate”. No entanto, é possível desativar a passivação anotando o bean de
sessão stateful com “@Stateful(passivationCapable=false)”.
Também é possível executar um método toda vez que o construtor de um bean
qualquer for invocado. Esta tarefa é responsabilidade da anotação “@AroundConstruct”.

4. CDI: Conceito e Injeção de Beans


O CDI é um mecanismo de gerenciamento de dependências entre beans. Com ele quase
todas as classes são managed beans e com isso passíveis de serem injetadas através da
anotação “@Inject”. Entre suas várias vantagens e funcionalidades estão: beans stateful
possuem ciclo de vida bem definido; a injeção de dependências typesafe; integração com
Java Server Faces (JSF); contexto de conversação para Web; integração de extensões
portáveis ao container através de uma Service Provider Interface (SPI). Para que um bean
seja gerenciável pelo CDI basta anotar a respectiva classe com “@Named”. A
implementação de referência e mais utilizada do CDI é o Weld.
Primeiramente é necessário habilitar o CDI. Para isso deve-se: baixar a última
versão do Weld (arquivo “jar”) disponível em seu site (http://weld.cdi-spec.org) para a
pasta “WEB-INF/lib”; criar um arquivo chamado context.xml (disponível em
https://gist.github.com/sergiolopes/2469299) na pasta “WEB-INF”; acrescentar as
configurações do Weld no arquivo “web.xml” (disponível em
https://gist.github.com/sergiolopes/2469303); criar um arquivo vazio chamado
“beans.xml” na pasta “WEB-INF” do projeto.
Como mencionado, toda classe com a anotação “@Named” é gerenciável pelo
CDI. Desta forma os objetos desta classe podem ser injetados em qualquer outro ponto
da aplicação através da anotação “@Inject”. Para a instanciação da classe gerenciável é
criado um método produtor com a anotação “@Produces” que será invocado toda vez que
esta for injetada. Por padrão toda dependência no CDI possui escopo “Dependant” o que
permite várias instanciações. Por isso, para trocar o escopo a anotação “@Produces” deve
ser acompanhada da anotação adequada, como por exemplo “@RequestScoped”,
“@SessionScoped” ou “@ApplicationScoped”.
O ciclo de vida bem definido no CDI permite executar ações nas fases de vida das
dependências: no descarte, por exemplo, utiliza-se a anotação “@Disposes” antes do
parâmetro do método que deverá ser executado nesta fase.
O CDI possibilita que um método interceptador seja chamado antes de outro
através da anotação “@Priority” antes do parâmetro. A versão 2.0 introduz este conceito
a observadores de um modo mais avançado. Quando há a anotação “@Observes” antes
do parâmetro, esta pode ser acompanhada da anotação “@Priority(1)”, com um “int” entre
parênteses para definir a ordem de execução dos observadores.

Referências
“CDI 2.0: Avanços no Java EE e Além”, https://www.devmedia.com.br/cdi-2-0-
avancos-no-java-ee-e-alem/39420.
“EJB: Introdução ao novo Enterprise JavaBeans 3.2”, https://www.devmedia.com.br/ejb-
introducao-ao-novo-enterprise-javabeans-3-2/30807.
“Java Specification Requests”, https://jcp.org/en/jsr/all.

Você também pode gostar