来自 WAR 的 EJB 中的 CDI 注入不保留原始对象
CDI Injection in EJB from WAR doesn't retain original object
一般的问题是:当通过 JAX-RS 服务(WAR 文件)中的生产者字段创建 CDI bean 而在 EJB bean(EJB 文件)中使用它时,CDI 注入是否有效)?
基于这个问题 Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? 这种情况应该可行,但我无法实现。
这里有一些细节。我有一个非常简单的 JavaEE 应用程序 (https://github.com/kocherovms/develorium.com/tree/master/cdi_problem),其结构如下:
hello-ear:
|
+- hello-ejb
| |
| +- HelloBean
|
+- hello-war
|
+- HelloService
在此应用程序中,我试图通过 CDI 注入在 JAX-RS 服务 (hello-war) 和 EJB bean (hello-ejb) 之间传递一个 Guest
对象。这是生成 Guest
对象实例的 JAX-RS 服务:
@Path("/hello")
public class HelloService {
@EJB
private Hello hello;
@Produces
@RequestScoped
@GuestMarker
private Guest guest;
@GET
public Response perform() {
guest = new Guest();
guest.setName("white rabbit");
String text = hello.getHelloText();
return Response.ok().type(MediaType.TEXT_PLAIN).entity(text).build();
}
}
hello-ejb 中 Hello
的实现尝试通过 CDI 使用 Guest
对象 @Inject
:
@Stateless
public class HelloBean implements Hello {
@Inject
@GuestMarker
Guest guest;
@Override
public String getHelloText() {
return String.format("Hello, %s!\n", guest.getName());
}
}
我正在将此应用程序部署到 WildFly 10 服务器中。部署本身工作正常,我的服务工作正常。但是调用服务 (curl http://localhost:8080/hello
) 总是 returns 'Hello, null!' 而不是 'Hello, white rabbit!' .
这意味着在 HelloService
端生成的 Guest
对象在 HelloBean
中不可用,并且使用默认构造的 Guest
实例。
我尝试了各种范围(例如 SessionScoped
、ApplicationScoped
),尝试使用生产者方法,尝试使 bean 成为有状态的甚至是单例的。什么都不管用。似乎 CDI 总是在我的案例中使用 Dependant
范围。
是否可以将 Guest
对象的实例从 HelloService
传递到 HelloBean
?
我认为您的设置可能过于复杂了。生产者字段被评估一次,所以你正在改变它的事实是一个问题。你的制作人应该看起来像
@Produces
@RequestScoped
@GuestMarker
private Guest guest = new Guest();
然后只需在 JAX-RS 方法中调用 setter,而不是实例化它。但这不会解决您的问题,现在我意识到您正在使用 EAR。 CDI bean 的范围在关联的模块内。所以 EJB 是它自己的上下文,不与您的 JAX-RS 资源共享。
一般的问题是:当通过 JAX-RS 服务(WAR 文件)中的生产者字段创建 CDI bean 而在 EJB bean(EJB 文件)中使用它时,CDI 注入是否有效)?
基于这个问题 Is it possible to @Inject a @RequestScoped bean into a @Stateless EJB? 这种情况应该可行,但我无法实现。
这里有一些细节。我有一个非常简单的 JavaEE 应用程序 (https://github.com/kocherovms/develorium.com/tree/master/cdi_problem),其结构如下:
hello-ear:
|
+- hello-ejb
| |
| +- HelloBean
|
+- hello-war
|
+- HelloService
在此应用程序中,我试图通过 CDI 注入在 JAX-RS 服务 (hello-war) 和 EJB bean (hello-ejb) 之间传递一个 Guest
对象。这是生成 Guest
对象实例的 JAX-RS 服务:
@Path("/hello")
public class HelloService {
@EJB
private Hello hello;
@Produces
@RequestScoped
@GuestMarker
private Guest guest;
@GET
public Response perform() {
guest = new Guest();
guest.setName("white rabbit");
String text = hello.getHelloText();
return Response.ok().type(MediaType.TEXT_PLAIN).entity(text).build();
}
}
hello-ejb 中 Hello
的实现尝试通过 CDI 使用 Guest
对象 @Inject
:
@Stateless
public class HelloBean implements Hello {
@Inject
@GuestMarker
Guest guest;
@Override
public String getHelloText() {
return String.format("Hello, %s!\n", guest.getName());
}
}
我正在将此应用程序部署到 WildFly 10 服务器中。部署本身工作正常,我的服务工作正常。但是调用服务 (curl http://localhost:8080/hello
) 总是 returns 'Hello, null!' 而不是 'Hello, white rabbit!' .
这意味着在 HelloService
端生成的 Guest
对象在 HelloBean
中不可用,并且使用默认构造的 Guest
实例。
我尝试了各种范围(例如 SessionScoped
、ApplicationScoped
),尝试使用生产者方法,尝试使 bean 成为有状态的甚至是单例的。什么都不管用。似乎 CDI 总是在我的案例中使用 Dependant
范围。
是否可以将 Guest
对象的实例从 HelloService
传递到 HelloBean
?
我认为您的设置可能过于复杂了。生产者字段被评估一次,所以你正在改变它的事实是一个问题。你的制作人应该看起来像
@Produces
@RequestScoped
@GuestMarker
private Guest guest = new Guest();
然后只需在 JAX-RS 方法中调用 setter,而不是实例化它。但这不会解决您的问题,现在我意识到您正在使用 EAR。 CDI bean 的范围在关联的模块内。所以 EJB 是它自己的上下文,不与您的 JAX-RS 资源共享。