CDI生产者未被合格者认可

时间:2019-02-26 07:53:20

标签: java java-ee jboss cdi java-ee-7

我有一个带有2个模块的EAR应用程序。一个WEB和一个EJB模块。

EJB模块中有一些服务被注入到WEB模块的类中,效果很好。但是某些服务需要基于用户上下文的配置,该配置仅在WEB模块中可用。因此,我尝试将生产者添加到WEB模块。
结构如下:

app-ear
|
+- app-ejb
|   |
|   +- Service
|   +- ServiceConnector
|
+- app-web
    |
    +- ServiceConnectorProducer

这是该代码的简化版本:

将连接器注入到(EJB)中的服务类

public class Service {
    @Inject
    private ServiceConnector connector;
}

将处理服务连接的连接器类:(EJB)

public class ServiceConnector {
    private final Config config;

    public ServiceConnector(final Config config) {
        this.config = config;
    }
}

ServiceConnector的制作人:(WEB)

public class ServiceConnectorProducer {
    @Produces
    public ServiceConnector produce(UserContext userCtx) {
        // ... create config and set data from user context
        return new ServiceConnector(config);
    }
}

这时在注入点无法识别生产者,并且我得到了一个不满意的依赖性错误:

org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ServiceConnector with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject private Service.connector
  at Service.connector(Service.java:0)

即使生产者是由容器加载的,也会发生这种情况:

WELD-000106: Bean: Producer Method [ServiceConenctor] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public ServiceConenctorProducer.produce(UserContext)]

当我通过添加默认构造函数使ServiceConnector可以被容器发现时,却出现了模棱两可的依赖项错误:

Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type ServiceConnector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private Service.connector
at Service.connector(Service.java:0)
Possible dependencies: 
- Producer Method [ServiceConnector] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public ServiceConnector.produce(UserContext)],
- Managed Bean [class ServiceConnector] with qualifiers [@Any @Default]

之后,我尝试了以下方法来解决模棱两可的依赖关系。
-https://stackoverflow.com/a/22985035(添加限定词)
-https://stackoverflow.com/a/36056972(使用@Any
-https://stackoverflow.com/a/29449040/11117616(使用@Vetoed

但是所有这些解决方案都会导致未满足的依赖性错误。

WELD-001408: Unsatisfied dependencies for type ServiceConnector with qualifiers @SessionService
  at injection point [BackedAnnotatedField] @Inject @SessionService private Service.connector
  at Service.connector(Service.java:0)
WELD-001475: The following beans match by type, but none have matching qualifiers:
  - Managed Bean [class ServiceConnector] with qualifiers [@Any @Default]

因此,我现在不知道如何解决情况。如何获得ServiceConnector才能在WEB模块中生成?

1 个答案:

答案 0 :(得分:0)

您最有可能遵守Java EE伞规范的可见性限制。 EAR中某些档案(EAR / lib,EJB jar,WAR)可以查看和访问的内容受到限制。然后,CDI在注入时遵循相同的模式。

根据应用服务器解释规范的方式,这些规则的实现可能会略有不同。现在,如果您不想阅读规范(谁做了,嗯?;-),那么您可以at this SO answer进行总结,尽管并不详尽。

也就是说,在您的情况下,WAR文件可以访问EJB的内容,反之亦然。 用CDI术语来说,这意味着EJB jar不会“看到”您在那里的生产者方法。

对于当您使ServiceConnector一个bean时看到的模棱两可的依赖异常-我不确定100%没有复制器和一些调试是什么。这可能是在EAR中完成验证的方式的错误,也可能是有意的,因为从理论上讲,从WAR档案库中您可以看到两个ServiceConnector类型的bean。

关于如何解决此问题-我能想到的一件事是CDI扩展(按照Weld的解释)横跨整个EAR。因此,无论使用哪种存档,使用CDI扩展名来注册Bean 都可能为您工作。如果您采用这种方式,请查看AfterBeanDiscovery observer并在那里注册bean。