【问题标题】:Cannot apply Dependency Injection in EJB无法在 EJB 中应用依赖注入
【发布时间】:2013-02-21 00:54:49
【问题描述】:

我是 EJB 技术的新手,我目前正在阅读 Oracle 指南,试图将我阅读的内容付诸实践。为此,我在 Eclipse 中使用 JBoss 应用程序服务器创建了一个简单的 JSF 应用程序,使用托管 Bean 作为支持 Bean。我想借助 Singleton Bean 来初始化 Managed Bean 中的数据,只是为了感受下依赖注入是如何工作的。我关注relevant instructions,但我无法初始化 Singleton Bean。应用程序在 Hello Managed Bean 的构造函数中抛出 NPE。我预计我的代码可能缺少一些东西,但我找不到它。以下 Bean 类的缺陷在哪里? :

@Startup
@Singleton
public class LaunchBean {

private List<String> custs;

public List<String> getCusts() {
    return custs;
}

public void setCusts(List<String> emps) {
    this.custs = emps;
}

@PostConstruct
void init() {       //in the guide the () after init is missed, but the code does not compile when omitting it
    custs = new ArrayList<String>();
    custs.add("Cust1");
    custs.add("Cust3");
    custs.add("Cust2");
    custs.add("Cust4"); 
}

}  


@ManagedBean
@SessionScoped
public class Hello implements Serializable{
@EJB
private LaunchBean dBean;


private static final long serialVersionUID = 1L;
private List<String> customers;
private String customersSelect;

public Hello(){
    customers = dBean.getCusts();
}

public List<String> getCustomers() {
    return customers;
}

public String getCustomersSelect() {
    return customersSelect;
}

public void setCustomersSelect(String customersSelect) {
    this.customersSelect = customersSelect;
}

}

【问题讨论】:

    标签: jakarta-ee nullpointerexception ejb


    【解决方案1】:

    您只能使用@EJB 注解将 EJB 注入到其他 EJB 中。 Hello bean 不是 EJB。 @ManagedBean@SessionScoped 注释都不能使其成为一体。为了使其成为一体,例如,您可以为其添加 @Stateless@Stateful 注释。

    或者,您可以使用 CDI 将 EJB 注入到非 EJB 中,使用 @Inject 注释。但是请注意,您将无法利用通过 CDI 注入的 EJB bean 来利用某些 EJB 功能。

    编辑 我刚刚注意到代码的另一个问题。错误的不仅仅是注射。如果您尝试在那里访问注入的成员,Hello bean 的构造函数中总会有一个 NPE。成员在对象构造之后注入,因此构造函数不可用。要在注入成员后立即使用它们,请使用带有 @PostConstruct 注释的方法。

    编辑 2 我做了一些 SO 挖掘,看起来像 EJB 注入 indeed works for ManagedBeans。因此,虽然您不能使用 EJB 注释将 EJB 注入 POJO,但在这种情况下不应将 ManagedBeans 视为 POJO :)。给您带来的不便,我深表歉意。

    【讨论】:

    • 如果我添加注释 @Stateless 或 Stateful 但是,可以将其用作 JSF 文件的支持 Bean 吗?我一般可以使用什么作为支持 Bean 到 JSF?
    • @arjacsoh 当然,EJB 可以用作支持 bean,没有任何问题。这并不总是可行的,因为 JSF 前端通常在没有 EJB 支持的 Tomcat 之类的 servlet 容器上运行。但是,如果您的前端在 Java EE 应用程序服务器上运行,那就去吧。
    • 我试过了(改成Stateless),但是不能正常工作。它显示 ListBox 为空,没有数据。单击按钮删除到下一页后,它会引发错误:="#{hello.customersSelect}": Target Unreachable, identifier 'hello' resolve to null.
    • @arjacsoh 我自己使用Stateful EJBs 作为控制器,所以这确实有效并且EL 表达式被peroperly 解析。尝试将注释更改为Stateful,也许我对Stateless 有误。顺便说一句,您的 bean 看起来不是无状态的 - 它至少有两个可以从外部设置并更改状态的字段。所以把它变成一个无状态的 EJB 是不正确的。
    • @arjacsoh - 您是否因为 EL 分辨率问题而否决了答案?我觉得没必要。就算是我的错,为什么不先问?
    【解决方案2】:

    @kostja, 托管 bean 位于 Servlet 上下文之上,因此您可以从托管 Bean 中注入 EJB。 @arjacsoh。您需要在@PostConstruct 方法中包含代码customers = dBean.getCusts();。您不能在构造函数中执行此操作,因为还没有创建 managedbean。 @PostConstruct 方法在创建 Bean 后立即发生。

    【讨论】:

    • 从 EJB 3.1 开始,您不能使用 EJB 注释 see this question 注入 EJB。但是,您可以使用 CDI 或 JNDI 注入它们。至于@PostConstruct - 我注意到这个问题太晚了,但在你发布答案之前我已经发布了建议,请参阅我的编辑。
    • @Umoh - 我并没有打算制作 ManagedBean EJB,但我仍然很好奇是否可能。 JSF 可以使用 EJB 作为支持 Bean 吗?
    • @kostja。我看着那个问题,它似乎更像是一个讨论,而不是任何结论性的东西。我赞成您选择@PostConstruct 的答案。我还在编辑我的答案,所以我没有看到它。不过,我仍然不相信注射的事情。我会做更多的研究。
    • @arjacsoh 我从来没有这样做过,所以我不确定这是否可能。不过看看这篇有趣的文章adam-bien.com/roller/abien/entry/ejb_3_1_killed_the
    • @Umoh +1,毕竟你可能是对的 :) 我刚刚找到了 this question 似乎可以工作的地方。我现在有点困惑。
    猜你喜欢
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2011-07-14
    • 2012-08-01
    • 2018-02-25
    • 1970-01-01
    相关资源
    最近更新 更多