@Singleton 的 @Inject 字段上的 NPE class
NPE on a @Inject field for a @Singleton class
我遇到了一个奇怪的场景,无论我尝试过什么解决方案,任何使用 CDI 管理单例的尝试都会导致失败,我现在甚至不确定这是否是什么 feasable/that 可以完成,因此我在这里发帖的原因。
我会尽力解释当前的情况,我想知道我的意图是否可以实现,如果可以,通过什么方式,如果不能,是否有其他选择 "upgrading" 那个 jar 中的单例实例。如果我遗漏了 details/parts 代码,请告诉我,因为这有点不寻常,如果我提供了所需的一切,我不会这样做。
背景:
- JBoss 7.2 EAP作为服务器使用;
- 一个大的Maven项目,父pom文件只作为一个pom在maven中为所有其他子项目提供dependencies/configurations,类型为ejb/ear/war主要是.
- JBoss 中使用的自定义模块为某些项目提供了许多依赖项,因此它只是一个充满 jar 文件的文件夹,包括在其他项目中使用的自定义 jar。
- testing-purposes-ear.ear 被部署到服务器,其中包含一个 testing-ejb 和 测试-war 个项目。
- war 项目提供 依赖自定义模块中的一个 jar 文件(该 jar 实际上只是主项目的另一个子项目),并且在编译和运行时它解决得很好并且没有任何问题(在我看来与使用 maven 依赖项完全相同);
- 到目前为止,war 项目通过 getInstance() 方法从那个 jar 中调用单例实例(纯粹作为业务逻辑),一切正常。
意向:
- 从单例 classes 的 jar 中删除所有私有 constructors/getInstance() 并用 @Singleton 注释它们以期改变所有通过使用 @Inject,而不是使用 getInstance() 方法,将 war 项目中的调用改为另一种方式。
已走步数:
对于单个 class,删除了私有构造函数 getInstance(),为 class 创建了一个新接口以仅公开某些方法,并且单例 class 正在实现新接口,并标有来自 javax.inject 的 @Singleton 注释。
在war项目中,去掉了getInstance()调用,将@Inject变量设置为class 正在使用它,像这样:
@Inject
private Management managementInterface;
...
void someMethod(){
managementInterface.performBusinessLogic();
}
这导致在调用 performSomeBusinessLogic() 时抛出 NPE,为此我找到了几个答案,所以我添加了一个 beans.xml使用 discovery-mode=all 到那个罐子,尝试了 @Singleton
来自 javax.ejb,但没有任何方法可以注入该单例。
我已经搜索了很长时间以了解如何做到这一点,但是所描述的大多数场景 here/on google 都是关于部署在中的应用程序之间的 ejb 间通信同一个容器,但这不一样:我们正在尝试使用 CDI 从一个不是 ejb/war 项目的 jar 文件中注入一个单例,而是一个简单的 java 库。
需要考虑的事情:
那个单例 class 以前在多个 ejb/war 项目中使用没有问题,所以它作为自定义模块放在 JBoss 中的事实和一个独立的 jar 意味着对于所有调用 ejb/war 的项目,确实只有一个 class 的实例,我们避免了这些东西带来的整个 context/class-loading 典型问题。
那个singleton暴露了很多方法,有些方法其实不暴露更好,所以我想在它前面放一个接口,这样调用客户端只能访问一些方法,但不是全部。
由于项目的结构和管理依赖关系的方式,jar文件可以访问很多libraries/dependencies,所以打算放弃旧的创建方式并使用单例并将其迁移到更现代的东西。
IDE (Intellij) 能够毫无问题地解决依赖关系,如下面的附件所示,单击蓝色标记图标会导致 class 标记为 @Singleton 并且正在实现该接口。
问题:
- 是否可以将该 jar 项目中的单例从 classic 方式更改为使用服务器 CDI 的方式?在这方面,使用注释的东西是最好的,但如果有任何其他可用的解决方案,我愿意接受。
如果Managementclass是一个jar依赖(由JBoss提供或打包在ear里面)不被视为CDI bean。
它必须是一个 EJB/CDI 模块,与 testing-ejb.
打包在同一级别
另一种方法是使用@Remote EJB 注释并将 jar 部署为库,而不是简单的依赖项。
(对我而言)不清楚这种重构的目的,但如果是为了避免在每个需要它的 bean 上手动实例化 class,您可以编写一个简单的生产者:
@Singleton
public class ManagementProvider() {
@Produces
public Management getInstance() {
return Management.getInstance();
}
}
然后你可以随时使用@Inject!
我遇到了一个奇怪的场景,无论我尝试过什么解决方案,任何使用 CDI 管理单例的尝试都会导致失败,我现在甚至不确定这是否是什么 feasable/that 可以完成,因此我在这里发帖的原因。
我会尽力解释当前的情况,我想知道我的意图是否可以实现,如果可以,通过什么方式,如果不能,是否有其他选择 "upgrading" 那个 jar 中的单例实例。如果我遗漏了 details/parts 代码,请告诉我,因为这有点不寻常,如果我提供了所需的一切,我不会这样做。
背景:
- JBoss 7.2 EAP作为服务器使用;
- 一个大的Maven项目,父pom文件只作为一个pom在maven中为所有其他子项目提供dependencies/configurations,类型为ejb/ear/war主要是.
- JBoss 中使用的自定义模块为某些项目提供了许多依赖项,因此它只是一个充满 jar 文件的文件夹,包括在其他项目中使用的自定义 jar。
- testing-purposes-ear.ear 被部署到服务器,其中包含一个 testing-ejb 和 测试-war 个项目。
- war 项目提供 依赖自定义模块中的一个 jar 文件(该 jar 实际上只是主项目的另一个子项目),并且在编译和运行时它解决得很好并且没有任何问题(在我看来与使用 maven 依赖项完全相同);
- 到目前为止,war 项目通过 getInstance() 方法从那个 jar 中调用单例实例(纯粹作为业务逻辑),一切正常。
意向:
- 从单例 classes 的 jar 中删除所有私有 constructors/getInstance() 并用 @Singleton 注释它们以期改变所有通过使用 @Inject,而不是使用 getInstance() 方法,将 war 项目中的调用改为另一种方式。
已走步数:
对于单个 class,删除了私有构造函数 getInstance(),为 class 创建了一个新接口以仅公开某些方法,并且单例 class 正在实现新接口,并标有来自 javax.inject 的 @Singleton 注释。
在war项目中,去掉了getInstance()调用,将@Inject变量设置为class 正在使用它,像这样:
@Inject private Management managementInterface; ... void someMethod(){ managementInterface.performBusinessLogic(); }
这导致在调用 performSomeBusinessLogic() 时抛出 NPE,为此我找到了几个答案,所以我添加了一个 beans.xml使用 discovery-mode=all 到那个罐子,尝试了 @Singleton 来自 javax.ejb,但没有任何方法可以注入该单例。
我已经搜索了很长时间以了解如何做到这一点,但是所描述的大多数场景 here/on google 都是关于部署在中的应用程序之间的 ejb 间通信同一个容器,但这不一样:我们正在尝试使用 CDI 从一个不是 ejb/war 项目的 jar 文件中注入一个单例,而是一个简单的 java 库。
需要考虑的事情:
那个单例 class 以前在多个 ejb/war 项目中使用没有问题,所以它作为自定义模块放在 JBoss 中的事实和一个独立的 jar 意味着对于所有调用 ejb/war 的项目,确实只有一个 class 的实例,我们避免了这些东西带来的整个 context/class-loading 典型问题。
那个singleton暴露了很多方法,有些方法其实不暴露更好,所以我想在它前面放一个接口,这样调用客户端只能访问一些方法,但不是全部。
由于项目的结构和管理依赖关系的方式,jar文件可以访问很多libraries/dependencies,所以打算放弃旧的创建方式并使用单例并将其迁移到更现代的东西。
IDE (Intellij) 能够毫无问题地解决依赖关系,如下面的附件所示,单击蓝色标记图标会导致 class 标记为 @Singleton 并且正在实现该接口。
问题:
- 是否可以将该 jar 项目中的单例从 classic 方式更改为使用服务器 CDI 的方式?在这方面,使用注释的东西是最好的,但如果有任何其他可用的解决方案,我愿意接受。
如果Managementclass是一个jar依赖(由JBoss提供或打包在ear里面)不被视为CDI bean。 它必须是一个 EJB/CDI 模块,与 testing-ejb.
打包在同一级别另一种方法是使用@Remote EJB 注释并将 jar 部署为库,而不是简单的依赖项。
(对我而言)不清楚这种重构的目的,但如果是为了避免在每个需要它的 bean 上手动实例化 class,您可以编写一个简单的生产者:
@Singleton
public class ManagementProvider() {
@Produces
public Management getInstance() {
return Management.getInstance();
}
}
然后你可以随时使用@Inject!