【问题标题】:CDI producer not recognized with qualifiersCDI 生产商未获得资格认证
【发布时间】:2019-07-19 17:06:48
【问题描述】:

我有一个包含 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]

所以现在我不知道如何解决这种情况。如何在WEB模块中生成ServiceConnector

【问题讨论】:

  • 你试过把public Config produce(UserContext userCtx)方法设为静态吗?
  • 感谢您的回复。我完全忘记测试那个了。但不幸的是,这并不能解决问题。
  • 我不太确定您的部署/打包结构是否正常。您的 Web 模块的类路径不太可能包含您的 ejb jar。也许阅读有关从 Web 模块扫描的内容的规范会有所帮助。您可能希望将这些生产者/实现类提取到 ear/lib 中。否则,也许有一个包含 ejb jar 的类路径清单条目可能会有所帮助(尽管这可能是一个非常糟糕的主意)。
  • 我打赌注入到你的 ejb-jar 作品中的另一个类中......
  • Web 模块的类路径包含 ejb.jar,但反之则不然。注入一般适用于 ejb->web 和 ejb->ejb。如果我将生产者移动到 ear/lib,我将无法从 web 模块访问用户上下文。

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


【解决方案1】:

您很可能会观察到 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。

【讨论】:

  • 谢谢。通过扩展注册生产者使其工作:-)
猜你喜欢
  • 1970-01-01
  • 2017-08-04
  • 2013-12-09
  • 2012-07-01
  • 1970-01-01
  • 2023-03-29
  • 2015-04-08
  • 1970-01-01
  • 2022-10-12
相关资源
最近更新 更多