CDI Producer

CDI (Context and dependency injection) é uma poderosa especificação introduzida no JEE6 e que oferece vários recursos. Um deles é o Producer methods, que é o assunto desse post.

CDI producer methods podem ser usados em alguns cenários, tais como:

  • Tornar Non-CDI beans em CDI beans que podem ser injetados em outros beans. Você pode estar usando alguma biblioteca que não expõe seus beans via CDI mas você quer ter a chance de injetá-los em seus beans CDI.
  • Você tem um bean que requer um construtor com algum argumento.

Esses são alguns casos nos quais CDI producer methods podem ser aplicados.

Você também pode assistir o vídeo abaixo, onde mostro passo a passo a criação de uma aplicação simples e explico alguns detalhes:

Simples exemplo

Vamos ver agora através de um simples exemplo como usar CDI producer methods. Imagine um cenário onde você tem uma interface e uma implementação dessa interface, mas esta implementação só provê um construtor que recebe um argumento. Nesse caso, você não pode injetar esse bean automaticamente, pois ele não provê um construtor padrão.

package com.lucianomolinari.cdiproducer.dao;

public interface SimpleDao {

	void doSomething();

}

package com.lucianomolinari.cdiproducer.dao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileSimpleDao implements SimpleDao {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	private final String baseDir;

	public FileSimpleDao(String baseDir) {
		this.baseDir = baseDir;
	}

	public void doSomething() {
		logger.info("Invoking doSomething() on FileSimpleDao with baseDir {}", baseDir);
	}

}

Como podemos ver, temos uma simples interface e uma implementação para ela. Como cliente, queremos ser capaz de injetar essa implementação como fazemos para qualquer CDI bean.

package com.lucianomolinari.cdiproducer.client;

import java.io.IOException;

import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.lucianomolinari.cdiproducer.dao.SimpleDao;

@WebServlet(urlPatterns = "/client")
public class ServletClient extends HttpServlet {
	private static final long serialVersionUID = 1316100980591892471L;

	@Inject
	private SimpleDao simpleDao;

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		simpleDao.doSomething();
	}

}

Quando executamos esse código acessando a URL http://localhost:8080/cdiproducer-0.0.1-SNAPSHOT/client, nós recebemos o seguinte erro:

WELD-001408: Unsatisfied dependencies for type SimpleDao with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private com.lucianomolinari.cdiproducer.client.ServletClient1.simpleDao
  at com.lucianomolinari.cdiproducer.client.ServletClient1.simpleDao(ServletClient1.java:0)

Isso ocorre pois não há nenhuma implementação da interface SimpleDao que seja um bean CDI. Para resolver esse problema, nós podemos criar um CDI producer, responsável por criar uma instância de FileSimpleDao que permite que ela seja injetada em qualquer bean CDI.

package com.lucianomolinari.cdiproducer.producer;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lucianomolinari.cdiproducer.dao.FileSimpleDao;
import com.lucianomolinari.cdiproducer.dao.SimpleDao;

public class SimpleDaoProducer {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Produces
	@ApplicationScoped
	public SimpleDao createFileDao() {
		logger.info("--> Creating fileDao");
		return new FileSimpleDao("/opt/");
	}

}

Nesse momento, quando injetamos uma instância de SimpleDao, o CDI vai procurar um CDI bean válido ou algum producer method que esteja criando uma instância daquele tipo.

Se o mesmo código for executado novamente, teremos o seguinte output.

22:31:02,892 INFO  [com.lucianomolinari.cdiproducer.producer.SimpleDaoProducer] (default task-1) --> Creating fileDao
22:31:02,893 INFO  [com.lucianomolinari.cdiproducer.dao.FileSimpleDao] (default task-1) Invoking doSomething() on FileSimpleDao with baseDir /opt/

Como pode ser visto, agora tudo está funcionando.

CDI Producer e escopos

Você pode estar imaginando em que momento as instâncias de SimpleDao são criadas, se uma por aplicação, por requisição..
Na verdade, você pode usar qualquer escopo CDI no seu producer. No entanto, vale notar que você deve adicionar a anotação de escopo no producer method e não na producer class. Por exemplo, se você quer garantir que somente uma instância de um determinado bean seja criada, você precisa anotar o producer method com @ApplicationScoped ao invés de aplicar essa anotação na producer class.

Então é isso. Essa foi uma breve introdução sobre CDI producer e você pode conferir o código completo aqui. Você também pode assistir o vídeo acima (inglês), onde mostro tudo funcionando.


Quer aprender muito mais? Não deixe de ver meu curso Construa uma aplicação do zero com JEE 7, Java 8 e Wildfly.

Anúncios
Esta entrada foi publicada em Java EE, JBoss com as etiquetas , . ligação permanente.

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s