2016-09-30 16 views
0

Я попытался выполнить некоторые из предложений, которые я нашел в ранее опубликованных вопросах, но я не могу получить полное решение. Используя следующий код:Использование прокси для ввода с помощью CDI Producer

@Produces 
@Dependent 
@RestClientResourceConnector 
public <T> RestClientProxy<T> getStatusResource(InjectionPoint injectionPoint) throws NamingException, OAuthClientException { 
String propertiesFile = null; 
String url = null; 
AuthenticationStrategy authStrategy = null; 

Class<T> clazz = (Class<T>) ((ParameterizedType)injectionPoint.getType()).getActualTypeArguments()[0]; 

for (Annotation qualifier : injectionPoint.getQualifiers()) { 
    if (qualifier instanceof RestClientResourceConnector) { 
    RestClientResourceConnector connector = (RestClientResourceConnector) qualifier; 
    propertiesFile = connector.value(); 
    url = connector.clientUrl(); 
    LOGGER.debug("url set to: " + url); 

    authStrategy = this.createAuthStrategry(propertiesFile); 
    } 
} 

Constructor<?> constructor; 
try { 
    constructor = clazz.getConstructor(String.class, AuthenticationStrategy.class); 
} catch (NoSuchMethodException | SecurityException e1) { 
    // TODO Auto-generated catch block 
    e1.printStackTrace(); 
    return null; 
} 

try { 
    RestClientProxy rcp = new RestClientProxy(); 
    rcp.setService(constructor.newInstance(url, authStrategy)); 
    return rcp; 
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

return null; 
} 

Источником для классификатором является:

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) 
public @interface RestClientResourceConnector 
{ 
    @Nonbinding String value() default ""; 
    @Nonbinding String clientUrl() default ""; 
} 

С RestClientProxy определяется как:

public class RestClientProxy<T> { 
private T client; 

public RestClientProxy() { 
} 

public RestClientProxy(T service) { 
    this.client = service; 
} 

public void setService(T service) { 
    this.client = service; 
} 

public T get() { 
    return client; 
} 
} 

И попытки внедрить с:

@Inject 
    @RestClientResourceConnector(value="ferpa.properties", clientUrl="person.enpoint.url") 
    RestClientProxy<PersonResourceClient> personProxy; 

Я получаю th e исключение сварки:

2016-09-30 14:07:08,372 WARN [org.jboss.weld.Bootstrap] (weld-worker-1) WELD-001125: Illegal bean type javax.validation.ConstraintValidator<edu.psu.injection.validator.NotNullNotEmptyCollection, java.util.Collection<?>> ignored on [EnhancedAnnotatedTypeImpl] public class edu.psu.injection.validator.NotNullNotEmptyCollectionValidator 
2016-09-30 14:07:08,782 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC000001: Failed to start service jboss.deployment.unit."account-activation-web.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."account-activation-web.war".WeldStartService: Failed to start service 
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type RestClientProxy<AccountActivationClient> with qualifiers @RestClientResourceConnector 
at injection point [BackedAnnotatedField] @Inject @RestClientResourceConnector private edu.psu.activation.services.AccountActivationTokenService.accountActivationClientProxy 
at edu.psu.activation.services.AccountActivationTokenService.accountActivationClientProxy(AccountActivationTokenService.java:0) 

at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359) 
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281) 
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134) 
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155) 
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518) 
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:68) 
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66) 
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.run(FutureTask.java:266) 
... 3 more 

2016-09-30 14:07:08,787 ERROR [org.jboss.as.controller.management-operation] (management-handler-thread - 8) WFLYCTL0013: Operation ("full-replace-deployment") failed - address: ([]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"account-activation-web.war\".WeldStartService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"account-activation-web.war\".WeldStartService: Failed to start service 
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type RestClientProxy<AccountActivationClient> with qualifiers @RestClientResourceConnector 
at injection point [BackedAnnotatedField] @Inject @RestClientResourceConnector private edu.psu.activation.services.AccountActivationTokenService.accountActivationClientProxy 
at edu.psu.activation.services.AccountActivationTokenService.accountActivationClientProxy(AccountActivationTokenService.java:0) 
"}} 

Как всегда, любая помощь очень ценится.

ответ

1

К счастью, ответ довольно прост.

Чтобы решить вашу проблему, вы должны исключить элементы аннотации (value и clientUrl) из соображений, когда Weld сравнивает два экземпляра аннотаций. Для этого используйте аннотацию @Nonbinding.

import javax.enterprise.util.Nonbinding; 
import javax.inject.Qualifier; 

@Qualifier 
@Retention(RUNTIME) 
@Target({TYPE, METHOD, FIELD, PARAMETER}) 
public @interface RestClientResourceConnector { 

    @Nonbinding 
    String value() default "value"; 

    @Nonbinding 
    String clientUrl() default "clientUrl"; 
} 

Подробное описание:

Если внимательно прочитать трассировки стека вы можете найти STH как:

WELD-001475: The following beans match by type, but none have matching qualifiers: 
    - Managed Bean [class RestClientProxy] with qualifiers [@Any @Default], 
    - Producer Method [RestClientProxy<T>] with qualifiers [@RestClientResourceConnector @Any] declared as [[BackedAnnotatedMethod] @Produces @Dependent @RestClientResourceConnector public *your_producer_method_goes_here*... 

Это означает, что Weld найден соответствующий компонент, но у него не было необходимый определитель. Вы можете спросить: «Почему?». Поскольку ваша точка инъекции содержит классификатор с двумя параметрами:

@RestClientResourceConnector(value="ferpa.properties", clientUrl="person.enpoint.url") 

но ваш метод Производитель определяется только с

@Produces 
@Dependent 
@RestClientResourceConnector 

Вот почему вы, вероятно, следует сказать Weld игнорировать эти параметры.

UPDATE

Как пользователь @ussmith выяснилось, проблема была вызвана тем, что метод производитель не был определен внутри архива CDI боба.

Снова я нахожу CDI гораздо более запутанным, чем должно быть. При явной конфигурации таких проблем не должно быть.

+0

Спасибо и извинились, я должен был добавить вышеописанный код. Участники аннотаций уже @Nonbinding. Я был успешным с тем же кодом и не-generics, что и созданный экземпляр, так что теперь я схожу с родовой кроличьей дыры. –

+0

Хм. Код выше работает для меня отлично отлично с Weld ** 2.3.5. Final **. Какую версию Weld вы используете? BTW: пожалуйста, также обновите свой вопрос с полной трассировкой стека. Это может быть полезно. –

+0

Бег 2.2.14.Final. Я поговорю с моими опс о модернизации. Полная запись стека теперь находится в сообщении. Еще раз спасибо. –