我有一个带有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
?
您很可能会观察Java EE伞规范可见性限制。 EAR中的某些归档(EAR / lib,EJB jar,WAR)可以查看和访问的内容存在限制。然后CDI遵循相同的注射模式。
根据应用程序服务器如何解释规范,这些规则的实现可能略有不同。现在,如果你不想阅读规范(谁做,呃?;-)),那么你可以看看at this SO answer那种总结它虽然不是详尽的。
即在您的情况下,WAR文件可以访问EJB的内容,但反之亦然。在CDI术语中,这意味着EJB jar不会“看到”您在那里的生产者方法。
至于你在使ServiceConnector
成为bean时看到的模糊依赖异常 - 我不是百分之百确定没有重现器和一些调试的东西。它可能是如何在EAR中进行验证的错误,或者它可能是有意的,因为理论上从WAR存档中你可以看到两个类型为ServiceConnector
的bean。
至于如何解决这个问题 - 我能想到的一件事是CDI扩展(在Weld的解释中)跨越整个EAR。使用CDI扩展来注册bean可能对你有用,无论存档是什么。如果你这样做,看看AfterBeanDiscovery
observer并在那里注册豆子。