【问题标题】:JSF managed-bean EJB injectionJSF 托管 bean EJB 注入
【发布时间】:2012-01-27 10:01:32
【问题描述】:

我在企业应用程序模块中有一个 EJB(PersonManager),它注入另一个 EJB(Person):

@Stateful
public class PersonManager implements PersonManagerLocal {
    @EJB
    private PersonLocal person;

    @Override
    public void setPersonName(String name) {
        person.setName(name);
    }

    @Override
    public String getPersonName() {
        return person.getName();
    }
}

我想在 JSF Web 应用程序中使用 PersonManager EJB。我在 faces-config.xml 中定义它:

<managed-bean>
    <managed-bean-name>personManager</managed-bean-name>
    <managed-bean-class>ejb.PersonManager</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

问题在于,不会发生 PersonLocal EJB 的注入。 person 属性始终为 NULL。我做错了什么?

但是如果我像这样将 PersonManager 注入到 JSF 托管 bean 中:

@ManagedBean
@RequestScoped
public class Index {
    @EJB
    private PersonManagerLocal personManager;
    ....

它工作正常。我需要第一个场景,请帮帮我:-D

【问题讨论】:

  • 为什么不用@EJB注解代替在faces-config.xml中手动声明呢?这就像在没有发明注释时试图回到过去:P
  • 你是对的 :-D 这只是理论上的,我想知道答案。
  • @Forty 那么为什么它不起作用呢?我不清楚答案。

标签: jsf ejb managed-bean


【解决方案1】:

您正在混合 EJB 和 JSF 托管 bean 的职责。 faces-config.xml 仅注册 JSF 工件,例如托管 bean 而不是 EJB。您在faces-config.xml注册

<managed-bean>
    <managed-bean-name>personManager</managed-bean-name>
    <managed-bean-class>ejb.PersonManager</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

基本一模一样
@ManagedBean
@SessionScoped
public class PersonManager {
    // ...
}

换句话说,您正在将该类注册为一个 JSF 托管 bean,#{personManager} 可以在视图中使用它。这并不代表由 EJB 容器管理的同一实例。您可以并且应该使用faces-config.xml 注册EJB。在那里,您可以使用 javax.ejb 包中的注释,例如 @Stateless@Stateful。这就是注册 EJB 所需的全部内容。

实际上,在 faces-config.xml 中注册 JSF 托管 bean 是一种旧的 JSF 1.x 方式,在 JSF 2.x 中已被新的 @ManagedBean 注解取代。


更新正确的方法是:

查看(Facelets 文件):

<h:form>
    <h:inputText value="#{personManager.person.name}" />
    ...
    <h:commandButton value="Save" action="#{personManager.save}" />
    <h:messages />
</h:form>

控制器(JSF 托管 bean):

@ManagedBean
@ViewScoped
public class PersonManager implements Serializable {

    private Person person;

    @EJB
    private PersonService personService;

    @PostConstruct
    public void init() {
        person = new Person();
    }

    public void save() {
        personService.create(person);
        FacesContext.getCurrentInstance().addMessage(null,
            new FacesMessage("Person successfully created, new ID is " + person.getId()));
    }

    // ...
}

模型(JPA 实体):

@Entity
public class Person implements Serializable {

    @Id
    private Long id;

    private String name;

    // ...
}

服务(无状态 EJB):

@Stateless
public class PersonService {

    @PersistenceContext
    private EntityManager em;

    public void create(Person person) {
        em.persist(person);
    }

    // ...
}

【讨论】:

  • 谢谢,PersonManager 是一个业务 EJB,因此不包含 @ManagedBean 注释。它是由 JSF 引擎创建的,只是在 faces-config 场景下没有将 person EJB 注入其中。
  • 我知道 EJB 是什么以及应该如何使用它们。你?究竟是哪一部分现在还不清楚?
  • 请注意,我的答案示例中缺少@Stateful。它不是这样的 EJB。您试图将 EJB 滥用为 JSF 托管 bean。这个不对。您基本上应该有 1 个 XHTML 文件作为视图,1 个 JSF 托管 bean 作为控制器,1 个实体作为模型和 1 个 EJB 作为服务。在您的问题中,PersonManager 应该是 JSF 托管 bean,而不是 EJB。 PersonLocal 似乎是一个实体,而不是 EJB。所以我怀疑它是否真的需要成为 EJB。 EJB 旨在提供create()save() 等服务。
  • 另请参阅更新的答案以获取启动示例。请注意,您根本不需要配置 xml 文件。
  • 我在看答案的同时也很佩服作者,但是当我读到最后,看到底部有你的名字“BalacC”,我的兴奋感降低了。难怪只有你能写出这么好的答案。祝你好运
猜你喜欢
  • 1970-01-01
  • 2013-07-28
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 2015-07-13
  • 2023-03-27
  • 2015-03-11
  • 2013-01-23
相关资源
最近更新 更多