Este documento discute conceitos e modelos de programação do CDI, incluindo:
1) Tipos de beans, qualificadores, escopos, nomes EL, alternativas e estereótipos.
2) Métodos produtores, campos produtores e recursos como formas de fornecer instâncias de beans.
3) Inicializadores, beans @New e quando um bean está habilitado.
3. Bean
O que é um bean?
Qualquer classe java. No container JEE bean é um componente (classe) cujo ciclo de vida é
gerenciado pelo próprio container de acordo com o escopo (Scopes) ao qual ele pertence. No
container JEE um bean pode conter metadados sobre seu ciclo de vida e interação com outros
componentes.
Um bean possui os seguintes atributos:
● Conjunto de tipos não vazio
● Conjunto de qualificadores não vazio.
● Um escopo
● Um nome EL (Expression Language) - opcional
● Um conjunto interceptors bindings
● Uma implementação do bean
● Pode ser ou não um "alternative" (@Alternative)
4. Tipos de um Bean
O tipo do bean ou tipos, pois ele pode ter mais de um, são aqueles visíveis para clientes (client-
view)
O tipo do bean pode ser restrito pela anotação @Typed
Tipo do bean é o
@Typed(Shop.class) conjunto de tipos
visto pelo cliente!!
public class BookShop
extends Business
implements Shop<Book> {
...
}
O bean acima terá apenas dois tipos: Shop e Object e a linha seguinte causará exceção (runtime):
@Inject Shop shop;
BookShop book = (BookShop) shop;
5. Qualificadores
Podemos ter vários beans que implementam um mesmo tipo de bean. Se um bean implementa a
interface ClientAutrorizer como o cliente poderia utilizar um bean sem que o cliente fique
fortemente acoplado com a implementação da interface ?
Usa-se o qualificador que nada mais é que uma semântica associada ao tipo do bean que
implementa a interface (tipo de bean)
@LDAP @Qualifier
LDAPAuthorizer implements @Retention(RUNTIME)
@Target({METHOD,FIELD,PARAMETER,TYPE})
ClientAuthorizer {} public @interface OAuth {
}
@OAuth //assim que se declara um qualificador
OAuthAuthorizer
implements ClientAutorizer {}
Um bean pode ter múltiplos
@Inject @OAuth ClientAuthorizer authorizer; qualificadores
É possível injetar beans usando
qualificadores tb em contrutores e
métodos
6. Qualificadoes
o CDI fornece os seguintes qualificadores encontrados no pacote javax.
enterprise.inject:
● @Default - todo bean tem esse qualificador
● @Any - todo bean é @Any mesmo não explicitando qualificadores com exceção dos @New.
● @Named - qualificador usado para dar nome a um bean para ser usado na EL
● @New - .....nao sei
@Named("euSouUmBean")
public MyBean {
}
O bean acima possui os seguintes qualificadores: @Any, @Default, @Named
7. Escopo
Define o ciclo de vida e a visibilidade de um bean. Nem todos tem escopo definido como os
singletons que existem para toda aplicação. Objetos sem estado (stateless), servlets, e stateless
session beans não tem estado da perspectiva do cliente. Vc não sabe em que estado está um servlet
por exemplo. O escopo está sempre associado a um objeto context e serve para criar e destruir o
bean na hora certa e gerenciar seu ciclo de vida de forma transparente para o cliente. O escopo tb
define quais instâncias de um bean estão disponíveis para outras instâncias de outros beans.
O container JEE oferece os seguintes escopos por padrão:
@RequestScoped - servlet. O bean existe somente durante um request http.
@ApplicationScoped
@SessionScoped
@ConversationScoped
@Dependent: pseudo-escopo para objetos dependentes
8. Escopo
Declarando o escopo do bean:
O escopo de um bean é definido anotando-se a classe do bean, o método produtor (método anotado
com @Produces, responsável por fornecer a instância do bean para o container), campo com o tipo
do escopo.
@SessionScoped
public class User {
@Inject @ApplicaticationScoped Logger logger;
@Produces @SessionScoped User getCurrentUser() { ... }
}
9. Escopo
O escopo Default:
● Quando o bean não apresenta um escopo explícito em seus estereótipo, então seu escopo é
@Dependent
● Se todos os estereótipos de um bean que declaram um default scope tem o mesmo default
scope então o escopo do bean será default scope
● Se dois estereótipos de um bean declaram cada um o seu escopo e são diferentes, então no
bean deverá ser declarado qual o escopo do bean explicitamente, senão o container dará um
erro de definição.
Se o bean declara um escopo qualquer escopo default que venha a existir nos seus estereótipos será
ignorado.
10. Escopo
Scope Annotation Duration
Request @RequestScoped A user’s interaction with a web application in a single HTTP
request.
Session @SessionScoped A user’s interaction with a web application across multiple
HTTP requests.
Application @ApplicationScoped Shared state across all users’ interactions with a web
application.
Dependent @Dependent The default scope if none is specified; it means that an object
exists to serve exactly one client (bean) and has the same
lifecycle as that client (bean).
Conversation @ConversationScoped A user’s interaction with a JavaServer Faces application,
within explicit developer-controlled boundaries that extend
the scope across multiple invocations of the JavaServer
Faces lifecycle. All long-running conversations are scoped to
a particular HTTP servlet session and may not cross session
boundaries.
11. Bean EL Names
Um bean pode ter um nome EL (Expression Language name) e pode ser referenciado através desse
nome.
EL name geralmente são nomes separados por pontos "com.mydomain.myapp.beanName"
OBS: Não existe nenhuma relação entre o EL name, o session bean name e o EJB name do bean.
No jsp podemos acessar um bean pelo EL name:
<h: outputText value="#{products.total}"/>
A anotação @Named("currentOrder") permite dar um nome ao bean (anotação de classe)
@Named("currentOrder")
public class Order { .... }
12. Bean EL Names
Default EL Names:
Em algumas circustâncias o container deverá associar um nome EL default (default EL Name):
● Uma classe bean ou método producer (com a anotação @Producer) declara a anotação @Named
sem um nome específico.
● Quando o bean declara estereótipos que declaram uma anotação @Named vazia, sem especificar
nenhum nome.
Geralmente o nome do bean será o "unqualified class name" ex: ProductList -> productList
Managed Beans, Session Beans -> unqualified class name
Producer methods: nome do método suprimido o "get" e "set"
@Produces @Named
public List<Products> getProducts(){} -> o nome desse método será "products"
Producer fields:
@Named List<product> products = .... -> o nome será o próprio nome do campo: "products"
13. Alternatives
É um bean que deve declarado explicitamente no arquivo beans.xml para disponível para injeção e
lookup por EL name.
Podem ser declarados pela anotação @Alternative na classe, producer method ou campo.
@Alternative
public class MockOrder implements Order { ... }
META-INF ou WEB-INF/
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans 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://jboss.org/schema/cdi/beans_1_0.xsd
http://jboss.org/schema/weld/beans
http://jboss.org/schema/weld/beans_1_1.xsd">
<alternatives>
<class>com.mydomain.myapp.test.MockOrder</class>
<alternatives>
</beans>
14. Estereótipos - Stereotypes
Em alguns sistemas padrões de projeto são utilizados e determinados objetos realizam um
determinado papel como "controller", "view", "model", "dao". Eles realizam uma determinada
operação de acordo com o papel dentro do patter, framework ou arquitetura. Uma Dao, por
exemplo, é responsável pela persistência dos dados.
Um estereótipo (stereotype) permite o desenvolvedor identificar o papel de uma classe e declarar
alugns metadados para os beans que fazem parte desse papel.
Um estereótipo encapsula:
● um escopo default
● conjunto de interceptadores (interceptors binding)
pode especificar:
● que todos os beans com o estereótipos tenham EL names default
● que todos os beans com o estereótipo sejam alternatives
15. Estereótipos - Stereotypes
Um bean pode ter mais de um estereótipo. O estereótipo é definido como uma anotação:
@Target({TYPE, METHOD, FIELD}) ou
@Target(TYPE) ou
@Target(METHOD) ou
@Target(FIELD) ou
@Target({METHOD,FIELD}) AND
@Retention(RUNTIME)
@Alternative
@RequestScope
@Stereotype
@Target(TYPE)
@Retention(RUNTIME)
public @interface MockAction(){}
0 ResquestScope será o escopo default desse do estereótipo Action.Além disso todos os beans
desse estereótipo serão alternativas.
16. Estereótipos - Stereotypes
Algumas considerações:
O estereótipo não deve ser anotado @Typed
O estereótipo pode declarar outros estereótipos
As declarações em estereótipos são transitivas
O estereótipo pode declarar @Alternative, especificando que cada bean será uma alternativa
Estereótipos fornecidos pelo container:
@Model - beans da camada model de uma aplicação MVC.
@Interceptor - visto nos próximos slides
@Decorator - visto nos próximos slides
17. Modelo de Programação
● Managed Beans
● Session Beans
● Producer Methods
● Producer Fields
● Resources (Java EE resources, persistence contexts, persistence units,
remote EJBs and web services)
18. Modelo de Programação
Managed Beans
Managed bean é um bean implementaado por uma classe java, não podendo ser anotado por ambas:
@Interceptor E @Decorator (gera erro de definição)
Classes que são managed beans:
* não é classe interna estática
* classe concreta, ou anotada @Decorator
* não anotada como componente EJB ou declarada como uma classe EJB em ejb-jar.xml
* Não implementa javax.enterprise.inject.spi.Extension
* Possui construtor:
- default: sem parâmetros ou
- não possui construtor default mas tem um construtor anotado com @Inject
-> Todas as classes que atendam esses requisitos são managed beans sem precisar de nenhuma
definição especial.
19. Modelo de Programação
Session Beans
É um bean que implementa o tipo "session bean" de acordo com a especificação EJB, que define a
semântica e o ciclo de vida dos session beans. Esses beans não podem ser anotados como
@Interceptor e @Decorator.
Declaração:
@Singleton @Stateless
class Shop{...} @Mock
@Named("loginAction")
public MockLoginAct implements Action
@Stateless
class PaymentProcessorImpl implement PaymentProcessor {....}
20. Modelo de Programação
Producer Methods
Métodos produtores é o fornecedor de objetos que serão injetados pelo container, onde:
* os objetos a serem injetados não são necessariamente instâncias de beans
* tipo concreto dos objetos vai varia em tempo de execução
* os objetos necessitam de inicialização customizada que não pode ser realizada pelo
construtor da classe.
Um producer method deve ser:
* não-abstrato, pode ser membro de um bean ou session bean. Pode ser não-estático
ou estático
* se for parte de um session bean ele deve ser estático um método de negócio do EJB.
21. Modelo de Programação
Producers Methods:
Tipos:
* Os tipo de retorno pode ser uma interface, ou seja, uma infinidade de tipos que
implementam a interface direta ou indiretamente mais java.lang.Object
* pode ser uma primitiva ou array contendo exatamente dois tipos: o tipo de retorno e
java.lang.object
* se o tipo de retorno é uma classe o tipo de retorno engloba as superclasses e interfaces
que ela implementa direta ou indiretamente.
@Produces PaymentProcessor getPaymentProcessor(){...}
@Produces @ApplicationScoped @Catalog @Named("catalog")
List<Product> getProducts() {...}
22. Modelo de Programação
Producer Fields
É uma alternativa simples ao producer method. É um campo de um bean que pode ser estático ou
não. Se for parte de um session bean ele deve ser estático. Se em algum momento ele assumir o
valor null ele deve ter o escopo @Dependent senão ocorrerá uma IllegalProductException
Os tipos de um producer field são os mesmos de um producer method.
public class Shop {
@Produces PaymentProcessor paymentProcessor = ...;
@Produces List<Produces> products = ...;
}
Um producer field não deve ter a anotação @Inject senão ocorrerá erro de definição.
23. Modelo de Programação
Resources
Resource é um bean que representa um referência a um recurso como um persistence context,
persistent unit, EJB remoto, web service no ambiente de componentes JEE.
@Produces @WebServiceRef(lookup="java:app/service/PaymentService")
PaymentService service;
@Produces @EJB(ejbLink="../their.jar#PaymentService")
PaymentService service;
@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatabase")
@CustumerDatabase Database customerDatabase;
@Produces @PersistenceContext(unitName="CustomerDatabase")
@CustomerDatabase EntityManager customerDatabasePersistenceContext;
@Produces @PersistenceUnit(unitName="CustomerDatabase")
@CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;
24. Modelo de Programação
Initializer Methods
É um método não-abstrato, não-estático, não-genérico de uma classe bean, ou de qualquer componente JEE que
suporte injeção. Se o bean é um session bean, o initializer method não precisa ser um método de negócio.
Um bean pode ter zero ou vários initalizer methods.
Métodos interceptadores nunca são chamados qdo o container chamar um initializer method.
A aplicação pode chamar initliazer methods diretamente mas nenhum parâmetro será passado pelo container.
@ConversationScoped
public class Order {
private Product product;
private Product product;
@Inject setProduct(@Selected Product product){ ... }
@Inject setCustomer(User customer) { ... }
}
25. Modelo de Programação
@New Beans
@New é um qualificador (qualifier). Para cada bean ou session bean existe um segundo bean que:
* tem a mesma classe bean
* tem os mesmos tipos de bean
* tem o mesmo construtor, initializer methods e injected fields
* tem os mesmo interceptors bindings
Mas:
* tem escopo @Dependent
* tem exatamente um qualificador @javax.enterprise.inject.New(Order.class)
* não tem EL name
* não tem estereótipos
* não é uma alternativa
* está habilitado se e somente se algum outro bean habilitado tem um injection point com a
o qualificador @New(X.class)
26. Modelo de Programação
Quando um bean está habilitado?
Quando:
* está publicado (deployed) em um bean arquive (pacote contendo o arquivo beans.xml)
* Não producer method ou producer field de um bean desabilitado
* Não é especializado por nenhum outro bean habilitado. (@Specializes ver especificação)
* Não é uma alternativa ou é uma alternativa selecionada de pelo menos um bean archive -
seja lá o que isso quer dizer.....
27. Interceptors
Definição:
São objetos que executam regras que ocorrem em todas as camada (cross-cutting concerns), como
logging, transação, checagem de segurança, etc. Não estão associadas a um objeto do domínio do
negócio, como nos decoradores. Os interceptadores podem ser associados ao beans através de um
mecanismo denominado interceptor bindings.
Declarando um interceptor bind:
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD}) //ou @Target(TYPE)
@Retention(RUNTIME)
public @interface Transacional { }
Os intercepadotes podem ter valores membros: @Transactional(requireLog="
true")
28. Interceptors
Implementando o interceptador
Uma vez definido o interceptor binding, vamos implementar a classe que será o interceptor:
@Transactional //nome do interceptor binding
@Interceptor
public class TransactionalInterceptor {
@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception {
return ctx.proceed();
}
}
Anota-se o bean (classe ou método). Se a anotação for na classe todos os métodos serão interceptados.
@Transactional @Transactional
public class Dao { ... } public void insert(Bean b) {....}
29. Interceptors
Por último, devemos habilitar os interceptadores uma vez que por default eles estão desabilitados.
Isso é feito no arquivo beans.xml:
<beans 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/beans_1_0.xsd">
<interceptors>
<class>org.mycompany.myfwk.TransactionInterceptor</class>
<class>org.mycompany.myfwk.LoggingInterceptor</class>
</interceptors>
</beans>
Os interceptadores serão executados na ordem que aparecem nesse arquivo.
30. Decorators
Decorators (desing pattern) implementa um ou mais tipos de bean e intercepta invocações de
método de negócio dos beans que implementam esses tipos de beans. A esses beans dá-se o nome
de beans decorados (decorated beans).
São similares aos interceptadores, mas como eles implementam diretamente operações de negócio,
eles não são capazes e nem se servem para implementar regras que permeiam todas as camadas do
projeto (cross-cutting concerns), como os iterceptadores.
Os decoradores podem estar associados com qualquer managed bean que não seja ele mesmo um
decorador, um interceptador ou EJB session bean. E a classe d decorador e suas superclasses não
são tipos decorados pelo decorador.
A instância do decorator é dependente da instância do objeto que ele decora.
31. Decorator
Declarando um decorador
Usa-se o estereótipo @javax.decorator.Decorator
@Decorator
class TimestampLogger implements Logger { .... }
Todo decorador tem um delegate injection point : bean da classe decorada. E deve ter somente um
delegate injection point.
@Decorator
class TimestpLogger implements Logger {
@Inject @Delegate @Any Logger logger;
ou:
@Inject public TimestpLogger( @Delegate @Debug Logger logger)
{this.logger = logger}
}
32. Decorator
Decoradores por default não são habilitados. Deve-se ir ao aquivo beans.xml e colocar a classe do
decorador:
<?xml version="1.0"?>
<beans 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/beans_1_0.xsd">
<decorators>
<class>com.ecl.trainning.cdi.decorator.OrderDecorator</class>
<class>com.ecl.trainning.cdi.decorator.AnotherOrderDecorator</class>
</decorators>
</beans>
A ordem das classes é a ordem que eles serão executados.
33. Decorator
Exemplo completo
@Decorator
public abstract class OrderDecorator implements Order {
@Inject @Delegate @MyOrder //delegate injection point
private Order order;
public OrderDecorator() {
}
@Override
public String getNumber() {
logger.info("calling getNumber from decorator");
return order.getNumber();
}
}
34. Events
Beans podem consumir e disparar eventos. Isso torna possível desacoplar os beans completamente,
sem necessidade de nenhuma dependência em tempo de compilação. Os eventos permitem dou ou
mais bean stateful em camadas diferem da arquitetura (tier) sincronizem seus estados a medida que
mudanças em seus estados ocorrem.
Os eventos são tratados por objetos que observam esses eventos.
O evento é:
* um objeto java: event
* um conjunto vazio ou não de várias instâncias de qualificadores - event qualifiers - que
permite os observadores diferenciarem o tipo dos eventos
@Qualifier
@Retention({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Updated {}
35. Events
Observando eventos: métodos que utilizam @Observes
public void onAnyDocumentEvent( @Observes Document document)
//observando um evento com um qualificador
//o método pode ter parâmetros adicionais
public void afterUpdating( @Observes @Updated @ByAdmin Document document,
User user)
Produtores de eventos:
Os objetos que disparam eventos utilizam a interface parametrizada Event para disparar um evento.
A instância da interface é injetada da seguinte maneira:
@Inject @Any Event<Document> documentEvent;
o produtor dispara o evento passando o objeto do evento:
documentEvent.fire(document)
36. Events
Eventos podem ter valores:
@Qualifier
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Role {
String value();
}
//disparando o evento
public void login() {
final User user = ...;
loggedInEvent.fire( new LoggedInEvent(user),
new RoleQualifier() { public String value() { return
user.getRole(); } );
}
public abstract class RoleQualifier
extends AnnotationLiteral<Role>
implements Role {}
public void afterLogin(@Observes LoggedInEvent event) { ... }
public void afterAdminLogin(@Observes @Role("admin") LoggedInEvent event)
{}
37. Events
Observadores Condicionais: são métodos que são notificados de um evento somente se a instância
do bean que define o método observer já existir no contexto atual.
public void refreshOnDocumentUpdate(@Observes( receive=IF_EXISTS) @Updated
Document d){}
Bean que seja @Dependent e tenha um método observador com uma condicional ocasionará um erro
de definição que será detectado pelo container.
Métodos Observadores Transacionais: são métodos que recebem notificações antes, durante ou
depois de uma transação na qual o evento foi disparado. Se nenhuma transação está em andamento
qdo o evento é disparado esses métodos são notificados ao mesmo tempo que os outros
obsercadores. As notificações ocorrem:
* before completion
public enum TransactionPhase {
* after completion IN_PROGRESS,
* after success BEFORE_COMPLETION,
* after failure AFTER_COMPLETION,
AFTER_FAILURE,
AFTER_SUCCESS
}
void onDocumentUpdate(@Observes (during=AFTER_SUCCESS) @Updated Document
doc)