SeamFramework.orgCommunity Documentation
Java EE 5 já tinha introduzido um suporte limitado a injeção de dependências, na forma de injeção de componentes do ambiente. Um recurso do ambiente de componentes é um componente Java EE, por exemplo um datasource JDBC, uma fila ou um tópico JMS, um contexto de persistência JPA, um EJB remoto ou um web service.
Naturalmente, agora existe uma leve incompatibilidade com o novo estilo de injeção de dependência em CDI. Mais notadamente, a injeção de componentes no ambiente se baseia em nomes para qualificar tipos ambíguos, e não há real consistência quanto à natureza dos nomes (algumas vezes um nome JNDI, outras vezes um nome de unidade de persistência, às vezes um link EJB, e por vezes um "nome mapeado" não-portável). Os campos produtores acabou se tornando um adaptador elegante para reduzir toda esta complexidade a um modelo comum e obter recursos do ambiente de componentes para participarem do sistema CDI como qualquer outra categoria de bean.
Os campos possuem uma dualidade em que eles podem tanto ser o alvo de uma injeção de componente do ambiente Java EE quanto ser declarado como um campo produtor da CDI. Por esse motivo, eles podem definir um mapeamento a partir de nomes textuais no ambiente de componentes, até uma combinação de tipo e qualificadores usados no mundo da injeção typesafe. Nós chamamos um campo produtor que representa uma referência a um objeto no ambiente de componentes Java EE de recurso.
A especificação CDI utiliza o termo recurso para referir, genericamente, a qualquer das seguintes categorias de objeto que podem estar disponíveis no ambiente de componentes Java EE:
Datasource
s do JDBC, Queue
s, Topic
s e ConnectionFactory
s do JMS, Session
s do JavaMail e outros recursos transacionais incluindo os conectores JCA,
EntityManager
s e EntityManagerFactory
s do JPA,
EJBs remotos, e
web services
Declaramos um recurso ao anotar um campo produtor com uma anotação de injeção de componentes de ambiente: @Resource
, @EJB
, @PersistenceContext
, @PersistenceUnit
ou @WebServiceRef
.
@Produces @WebServiceRef(lookup="java:app/service/Catalog")
Catalog catalog;
@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatasource")
@CustomerDatabase Datasource customerDatabase;
@Produces @PersistenceContext(unitName="CustomerDatabase")
@CustomerDatabase EntityManager customerDatabasePersistenceContext;
@Produces @PersistenceUnit(unitName="CustomerDatabase")
@CustomerDatabase EntityManagerFactory customerDatabasePersistenceUnit;
@Produces @EJB(ejbLink="../their.jar#PaymentService")
PaymentService paymentService;
O campo pode ser estático (mas não final).
Uma declaração de recurso contém duas peças de informação:
o nome JNDI, link EJB, nome de unidade de persistência, ou outro metadado necessário para obter uma referência ao recurso a partir do ambiente de componentes, e
o tipo e os qualificadores que usaremos para injetar a referência dentro de nossos beans.
Pode parecer estranho declarar recursos no código Java. Não podem ser coisas específicas da implantação? Certamente, e é por isso que faz sentido declarar seus recursos em uma classe anotada com @Alternative
.
Este recursos agora podem ser injetados na maneira habitual.
@Inject Catalog catalog;
@Inject @CustomerDatabase Datasource customerDatabase;
@Inject @CustomerDatabase EntityManager customerDatabaseEntityManager;
@Inject @CustomerDatabase EntityManagerFactory customerDatabaseEntityManagerFactory;
@Inject PaymentService paymentService;
O tipo do bean e os qualificadores do recurso são determinados pela declaração do campo produtor.
Pode parecer trabalhoso ter que escrever estas declarações de campos produtores extras, apenas para ganhar um nível adicional de indireção. Você poderia muito bem usar uma injeção de componente do ambiente diretamente, certo? Mas lembre-se que você vai usar recursos como o EntityManager
em vários beans diferentes. Não é mais agradável e mais typesafe escrever
@Inject @CustomerDatabase EntityManager
em vez de
@PersistenceContext(unitName="CustomerDatabase") EntityManager
em todos os lugares?