2011-12-24 98 views
16

我在企业应用MODUL的EJB(的PersonManager)中注入另一个EJB(人):JSF托管bean EJB注入

@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(); 
    } 
} 

我想使用的PersonManager EJB在JSF的Web应用程序。我在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

+0

你为什么不使用@EJB注解,而不是手动faces-config.xml中声明它?这就像在注释未被发明时试图回到过去:P – 2011-12-24 19:36:48

+0

你是对的: - 它只是理论上的,我想知道答案。 – Forty 2011-12-24 20:45:50

+0

@Forty那么为什么它不工作?答案并不清楚。 – 2013-06-19 17:35:56

回答

37

您正在混合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); 
    } 

    // ... 
} 
+0

谢谢,PersonManager是一个商业EJB,因此不包含@ManagedBean注释。它由JSF引擎创建,只是在faces-config场景下不会将EJB注入到它中。 – Forty 2011-12-25 07:23:12

+0

我知道EJB是什么以及它们应该如何使用。你做?究竟哪一部分现在还不清楚? – BalusC 2011-12-25 12:42:43

+4

请注意,我的答案示例中缺少'@ Stateful'。这不是**这样的EJB。您试图将EJB作为JSF受管bean进行滥用。这个不对。基本上你应该有1个XHTML文件作为View,1个JSF托管bean作为Controller,1个实体作为Model,1个EJB作为服务。在你的问题中,PersonManager应该是一个JSF托管bean,而不是EJB。 PersonLocal似乎太多实体,而不是EJB。所以我怀疑它是否真的需要成为一个EJB。 EJB可以提供诸如'create()','save()'等服务。 – BalusC 2011-12-25 16:29:08