JEE6 CDI (Injeção de dependência) de forma inderata, através de uma classe, é possível?

9 respostas
Lavieri

Gostaria de saber se é possivel fazer injeção de depencia em uma ambiente JEE de forma indireta…

algo como

1#AlgumaCoisaFace algumaCoisaFacde = container.instanceFor(AlgumaCoisaFace.class);

é possivel fazer isso? com o container CDI ?? ou a única forma é algo como

2#@Inject //ou @EJB ou @BlaBla private AlgumaCoisaFace algumaCoisaFacde

Bom gostaria de conseguir fazer da forma 1#, tem como ?? (obs.: eu sei que da pra usar essa anotação em outro lugares como métodos, e etcs, mas gostaria mesmo era de fazer da forma 1#)

Obs.: eu sei que da pra fazer com spring, mas gostaria de fazer sem saber qual é a implementação do container do JEE

9 Respostas

Thiago_Senna

Eu faço isso com o spring. Vou postar a solucao pra você pq a única área que fica específica é a classe de configuração, o resto aparentemente é indepente do seu container IoC. Mas antes de ver minha solução, vc pode ver o @Configurable do Spring e o Salve. Ambos são solucoes para este problema.

Segue código
public interface NResources
{
	<T> T locate(Class<T> type);
}
import java.util.Map;

import org.springframework.context.ApplicationContext;

import com.nnoitra.services.NResources;

public class _NResources implements NResources
{
	private ApplicationContext applicationContext;

	public void setApplicationContext(ApplicationContext applicationContext)
	{
		this.applicationContext = applicationContext;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T locate(Class<T> type)
	{
		Map<String, T> beans = applicationContext.getBeansOfType(type);
		if (beans.size() == 1)
		{
			return beans.values().iterator().next();
		}
		else if (beans.isEmpty())
		{
			return null;
		}
		else
		{
			String msg = String.format("More than one bean of type %t in the context!", type);
			throw new RuntimeException(msg);
		}
	}
}
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.nnoitra.Nnoitra;
import com.nnoitra.support._NResources;

public class NnoitraConfigurator implements ApplicationContextAware
{
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
	{
		((_NResources)Nnoitra.resources).setApplicationContext(applicationContext);
	}
}
no application context
<bean class="com.nnoitra.configurator.NnoitraConfigurator" />
exemplo de uso
public Session session()
	{
		return resources.locate(SessionFactory.class).getCurrentSession();
	}
Lavieri

ai fica a questão neste seu código… quem é ApplicationContext ??

vc só consegue pegar beans a partir dele… e ele não á parte do CDI ou é ?

não há essa interface (ou classe) no JEE

por favor posta o código com os imports ^^ preu ver meió

Thiago_Senna

Eu estou utilizando Spring. ApplicationContext é onde estão todos os beans gerenciados pelo spring.

Lavieri:
vc só consegue pegar beans a partir dele… e ele não á parte do CDI ou é ?
não há essa interface (ou classe) no JEE

ApplicationContext é especifico do spring, no entanto não é exposto em sua aplicacao. A unica classe que sua aplicacao precisa conhecer é a interface NResources. A implementacao de NResources é especifico para cada container de injecao de dependencias. Aqui no caso, vc está criando sua própria abstracao para separar seu sistema do do container ioc.

Ok, eu editarei o posto anterior

L

Aparentemente, não existe nada do gênero para se buscar “managed beans” programaticamente. Ou é via annotations ou XML, e nada mais. Também não tem um único ponto de declaração de dependências, como o applicationScope.xml do Spring ou o Module do Guice. Por causa disso, existem um monte de conceitos complicados por cima, como os decorators e observers.

Pra falar a verdade, se eu tenho a opção de escolher, coloco Spring ou Guice na frente de CDI. Justamente por oferecer um ponto único de configuração, e por ter meios de busca programática de beans.

Lavieri

é para um framework... para rodar em um ambiente JEE6 .... não posso supor que estou trabalhando com spring ou algo do genero...

EU consegui fazer, + ou - .... funciona para a parte do CDI, mas não funciona bem de dentro dos EJBs / ManagedBeans ... ainda não entendi bem o pq

/**
 *
 * @author Tomaz Lavieri
 */
@javax.enterprise.context.Dependent
public class ContainerImpl implements Container{
    @javax.inject.Inject
    private javax.enterprise.inject.Instance&lt;Object&gt; container;

    public &lt;T&gt; T instanceFor(Class&lt;T&gt; type) {
        return container.select(type).get();
    }
}

funciona bem.... quando estou fora do EJB

@Named("ha")
public class Bleu {
    @Inject
    private Container container;
    public String getBla() {
        return ""+container.instanceFor(ItemFacade.class).find("10").getName();
    }
}

neste ponto funciona... lá na view quando coloco #{ha.bla} recebo o nome do Item de id = 10

porem c tento buscar o container dentro do EJB, levo null pointer na cara....

Acredito que a solução seja essa.... e que realmente, não posso injetar algo que não é @Stateless ou @Statefull dentro do EJB... pensei que podia, mas pelo visto não pode....

mas o meu maior problema, é que o @ManageBean também não aceita a injeção... =/

na verdade eu não consegui dar @Inject em nada dentro do ManagedBean

B

Lavieri, li rapidamente sobre esta nova especificação e posso estar errado no que estou falando… Mas creio que este novo CDI não é suportado nem em EJBs nem em Entidades(@Entity), o que resulta no seu null… É suportado apenas nos “ManagedBeans” … (classes java comuns) …

Lavieri

Lavieri, li rapidamente sobre esta nova especificação e posso estar errado no que estou falando… Mas creio que este novo CDI não é suportado nem em EJBs nem em Entidades(@Entity), o que resulta no seu null… É suportado apenas nos “ManagedBeans” … (classes java comuns) …

O fato é que o contrario funciona…

realmente não consegui injetar dentro do EJB, algo que estava fora,

mas estando fora, consigo injetar qualquer coisa, inclusive EJBs

A minha vontade é conseguir integrar um Framework ao CDI, e deixar o CDI disponivel par ao framework, para tal esse container é o primeiro passo… nele eu estou conseguindo resgatar coisas do EJB… agora falta conseguir registrar de forma programatica…

Lavieri

Resolvido o container… inclusive dentro dos EJB … o @Inject funciona sim em todas as partes do container, dentro do CDI e dentro do EJB, foi só implementar Serializable que tudo passou a funcionar =x

robsonsx

Lavieri,

Tudo bem? Este teu framework tá com código disponível?
Estou tb estudando as mesmas coisas que vc citou…

Criado 13 de abril de 2010
Ultima resposta 2 de set. de 2010
Respostas 9
Participantes 5