【问题标题】:CDI Injection in EJB from WAR doesn't retain original objectWAR 中 EJB 中的 CDI 注入不保留原始对象
【发布时间】:2016-09-11 08:37:07
【问题描述】:

一般的问题是:当通过 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 @Inject 使用 Guest 对象:

@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) 总是返回 'Hello, null!' 而不是 'Hello, white rabbit!'

这意味着在HelloService 端生成的Guest 对象在HelloBean 中不可用,并且使用了默认构造的Guest 实例。 我尝试了各种范围(例如SessionScopedApplicationScoped),尝试使用生产者方法,尝试使 bean 成为有状态甚至单例。没有任何效果。对于我的情况,CDI 似乎总是使用Dependant 范围。

是否可以将Guest 对象的实例从HelloService 传递给HelloBean

【问题讨论】:

  • 这两个guests 不需要是同一个实例。用@Inject 更改@Produces 注释,然后容器可以 为EJB 和JAX-RS 资源注入相同的实例。
  • 嗨,金。更改 @Produces -> @Inject 不是我需要的。我需要的是 JAX-RS (HelloService) 中@Produces 下的同一个 bean 在 EJB (HelloBean) 的注入点可用。通过这样做,我想将一些上下文信息从 JAX-RS 传递到 EJB。

标签: jakarta-ee jboss ejb jax-rs cdi


【解决方案1】:

我认为您的设置可能过于复杂。生产者字段被评估一次,所以你正在改变它的事实是一个问题。你的制作人应该是这样的

@Produces
@RequestScoped
@GuestMarker
private Guest guest = new Guest();

然后只需在 JAX-RS 方法中调用 setter,而不是实例化它。但这并不能解决您的问题,因为我意识到您正在使用 EAR。 CDI bean 的范围在关联的模块内。所以 EJB 是它自己的上下文,不与您的 JAX-RS 资源共享。

【讨论】:

  • John,关于上下文共享,您似乎是对的。在我将 HelloBean 移动到 war 文件(HelloService 旁边)之后,问题就消失了。无论如何,您能指出我在哪里可以阅读与我的问题相关的 CDI bean 可见性吗?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 2012-10-21
  • 1970-01-01
相关资源
最近更新 更多