Java CDI: Criando beans com o CDI Producer
Veja neste artigo como usar o CDI Producer para criar beans em seus projetos Java.
Motivação
Em contextos em que se está empregando o padrão injeção de dependência em Java, na maioria das vezes o CDI sabe exatamente como criar um objeto a partir da anotação @Inject. No entanto, há casos em que é necessário “ensiná-lo” como criar determinado objeto que demanda certas peculiaridades. Neste artigo veremos como proceder nessas situações utilizando a anotação @Produces, capaz de auxiliar o CDI na construção de um bean.
Saiba mais: como utilizar o CDI em seus projetos.
Como funciona o @Produces
Em casos nos quais a criação de um bean requer a execução de procedimentos adicionais, além da chamada padrão ao seu construtor, para que o CDI consiga criá-lo de maneira correta, ele procura no classpath do projeto todos os métodos e propriedades que possuem a anotação @Produces e que retornem o tipo de objeto que ele precisa. Para compreender seu funcionamento, tomemos como exemplo um bean chamado Person, cujo código é apresentado a seguir:
package br.com.devmedia;
public class Person {}
Podemos injetar esse bean em uma classe Service, que está sendo gerenciada pelo CDI. Para isso, utilizamos a anotação @Inject, como mostrado na Listagem 1.
package br.com.devmedia;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
@Named
@RequestScoped
public class Service {
@Inject
private Person person;
}
Nesse caso, quando o objeto do tipo Person for injetado, o CDI saberá que deve chamar o construtor dessa classe. Porém, podem haver situações em que se torna necessário criar esse bean de uma forma diferente, por exemplo, a partir da chamada a um web service. Em situações como essa, precisamos criar um produtor (Producer) capaz de criar um objeto Person conforme desejamos, como mostra a Listagem 2.
package br.com.devmedia;
import javax.enterprise.inject.Produces;
public class PersonProducer {
@Produces
public Person createPerson(){
return callWebService();
}
}
Nesse exemplo, a classe PersonProducer abstrai a lógica de criação do objeto Person, que aqui simula a chamada a um web service. Perceba que o método createPerson(), independentemente da sua lógica, sempre deverá retornar um objeto do tipo Person e também possuir a anotação @Produces. Essas duas características são suficientes para o CDI entender qual método ele deve chamar a fim de criar um objeto do tipo Person.
Criando um Producer para um EntityManager
Agora que já compreendemos como o CDI trabalha para criar instâncias de objetos injetados dinamicamente, veremos um novo exemplo que ilustra um caso muito comum em projetos Java: a criação de um EntityManager proveniente do JPA através de um CDI Producer. O CDI, por si só, não sabe como criar um EntityManager, o que significa que usar apenas o @Inject não resolveria, pois ele sempre retornaria um objeto
Para simular essa situação, temos na Listagem 3 um exemplo de injeção do EntityManager em uma classe DAO, responsável por realizar as operações direto na base de dados.
package br.com.devmedia;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
@Named
@RequestScoped
public class DAO {
@Inject
private EntityManager em;
public void save(Object o){
em.persist(o);
}
}
Ao chamar o método save(), teremos uma NullPointerException, pois o objeto em terá valor nulo, uma vez que o CDI não sabe como criar uma instância de EntityManager. Para solucionar esse problema, precisaremos criar um Producer, semelhante ao que fizemos na Listagem 2. Na Listagem 4 podemos ver o código da classe EntityManagerProducer, solução para o nosso problema.
package br.com.devmedia;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.io.Serializable;
public class EntityManagerProducer implements Serializable {
private static final long serialVersionUID = 1L;
private static EntityManagerFactory emf =
Persistence.createEntityManagerFactory("persistenceUnit");
@Produces
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
public void close(@Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
public EntityManagerFactory getEmf() {
return emf;
}
public void setEmf(EntityManagerFactory emf) {
this.emf = emf;
}
}
A partir dessa implementação, quando o CDI precisar criar um EntityManager, ele irá produzi-lo e destruí-lo de acordo com a lógica implementada na classe EntityManagerProducer.
Saber como o CDI funciona é fundamental para que se obtenha os resultados esperados quando for necessário utilizar a injeção de dependências, garantindo que os objetos sejam criados corretamente pelo framework.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Vídeo