Problema com injeção de dependências com weld

5 respostas
S

Bom dia pessoal, tenho um projeto desktop e gostaria de tirar proveito do gerenciamento de dependências do weld, só que logo de cara não conseguir injetar um java.sql.Connection com um qualificador avançado, segue os fontes, qualquer ajuda é bem vinda, obrigado desed já.

Minha anotação qualificadora:

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.PARAMETER;

import javax.inject.Qualifier;

@Qualifier
@Documented
@Target(value = { FIELD, METHOD, TYPE, PARAMETER })
@Retention(RUNTIME)
public @interface JdbcConnection {

	String url() default "";

	String user() default "";

	String password() default "";

}

Minha classe com o método produtor:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;

import br.com.newsoft.annotations.JdbcConnection;

public class JdbcConnectionProvider {

	@Produces
	@JdbcConnection
	public final Connection buildConnection(InjectionPoint ip) {
		JdbcConnection con_param = ip.getAnnotated().getAnnotation(JdbcConnection.class);

		System.out.println(con_param);
		
		Connection con = null;

		try {
			con = DriverManager.getConnection(con_param.url(), con_param.user(), con_param.password());
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return con;
	}
}

Meu teste:

import java.sql.Connection;
import java.sql.SQLException;

import javax.enterprise.event.Observes;
import javax.inject.Inject;

import org.jboss.weld.environment.se.events.ContainerInitialized;

import br.com.newsoft.annotations.JdbcConnection;

public class Main {

	@Inject
	@JdbcConnection(user = "root", password = "root", url = "jdbc:mysql://127.0.0.1/testdb")
	private Connection con;

	public void start(@Observes ContainerInitialized container) throws SQLException {
		System.out.println(con.isClosed());
		System.out.println(con.getCatalog());
	}
}

E quando executo tenho o seguinte erro:

Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Connection] with qualifiers [@JdbcConnection] at injection point [[BackedAnnotatedField] @Inject @JdbcConnection private br.com.newsoft.Main.con]
	at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:375)
	at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:307)
	at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:170)
	at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:201)
	at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:487)
	at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:74)
	at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:72)
	at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60)
	at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)

Lembrando que o projeto está configurado segundo os projetos de exemplo do weld-se, com o arquivo beans.xml em src/main/java/META-INF:

<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">
</beans>

5 Respostas

R

Vê se isso aqui te ajuda: https://community.jboss.org/thread/180049

S

Na verdade, na verdade o que eu estou fazendo é fazer na unha o que o provider me permite de certa forma tá encapsulando só não entendo o por quê dá:

Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Connection] with qualifiers [@JdbcConnection] at injection point [[BackedAnnotatedField] @Inject @JdbcConnection private br.com.newsoft.Main.con]
	at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:375)
	at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:307)
	at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:170)
	at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:201)
	at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:487)
	at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:74)
	at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:72)
	at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:60)
	at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:53)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)

vlw Rodrigo mas continuou com o msm erro.

R

Por essas e outras que acho o Guice muito mais simples :slight_smile:

S

Pois é vou ver como implementar isso com guice, vlw. :-o
É que queria ver como funciona a implementação de referência do CDI.

S

Resolvido Galera;

O problema era relativamente simples mas, devido falta conhecimento, levei um tempinho para resolver mas consegui.
O problema é que quando tenho uma anotação de qualificador com parâmetros o meu methodFactory responsavél por gerar essa dependência
responde levando em consideração a forma como ele esta no método produtor:

@Produces  
    @JdbcConnection  
    public final Connection buildConnection(InjectionPoint ip) {  
        JdbcConnection con_param = ip.getAnnotated().getAnnotation(JdbcConnection.class);  
  
        System.out.println(con_param);  
          
        Connection con = null;  
  
        try {  
            con = DriverManager.getConnection(con_param.url(), con_param.user(), con_param.password());  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
  
        return con;  
    }

O problema é que eu referencio ele usando os atributos:

@Inject  
    @JdbcConnection(user = "root", password = "root", url = "jdbc:mysql://127.0.0.1/testdb")  
    private Connection con;  
  
    public void start(@Observes ContainerInitialized container) throws SQLException {  
        System.out.println(con.isClosed());  
        System.out.println(con.getCatalog());  
    }

Eu acabei entendendo um pouco errado as coisas, no WELD customizar dependências é simples mas nesse caso os valores podem vir de zilhões de formas diferentes,
url pode vir de vários jeitos, password de outros e etc. O segredo é qualificar segundo um grupo predefinido(limitado) de possiveis instâncias(implementações de uma interface) e customizar via anotações baseando-se no ponto de injeção ao invés da minha notação ser assim:

@Qualifier  
@Documented  
@Target(value = { FIELD, METHOD, TYPE, PARAMETER })  
@Retention(RUNTIME)  
public @interface JdbcConnection {  
  
    String url() default "";  
  
    String user() default "";  
  
    String password() default "";  
  
}

ela seria assim:

@Documented  
@Target(value = { FIELD, METHOD, TYPE, PARAMETER })  
@Retention(RUNTIME)  
public @interface JdbcConnection {  
  
    String url() default "";  
  
    String user() default "";  
  
    String password() default "";  
  
}

nota que ela agora tá sem o @Qualifier de antes e no meu metódo produtor eu faria assim:

@Produces  
    public final Connection buildConnection(InjectionPoint ip) {  
        JdbcConnection con_param = ip.getAnnotated().getAnnotation(JdbcConnection.class);  
  
        System.out.println(con_param);  
          
        Connection con = null;  
  
        try {  
            con = DriverManager.getConnection(con_param.url(), con_param.user(), con_param.password());  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
  
        return con;  
    }

Sem o qualificador do objeto e pegando os valores dinâmicos via InjectionPoint.

http://blog.caelum.com.br/customizando-a-producao-de-dependencias-no-cdi/
http://blog.frankel.ch/further-into-cdi

Criado 28 de janeiro de 2013
Ultima resposta 27 de mai. de 2013
Respostas 5
Participantes 2