2

我创建了一个ejb

@Stateless
@LocalBean   
public class BasitBean {

    public String helloBasit() {

        return "Basit";

    } //end of helloBasit()

} //end of class BasitBean

我是从 JSF 调用它的

<h:body>

    <h:outputLabel value="#{helloBasit.callBasit()}" />

</h:body>

@ManagedBean
@SessionScoped
public class HelloBasit {

    @EJB
    private BasitBean basitBean;

    /** Creates a new instance of HelloBasit */
    public HelloBasit() {         

    }

    public String callBasit() {

        return basitBean.helloBasit();

    } //end of callBasit()

} //end of class HelloBasit

这段代码工作正常。但是当我像这样更改代码时

<h:body>
    <h:outputLabel value="#{helloBasit.label}" />        
</h:body>

@ManagedBean
@SessionScoped
public class HelloBasit {

    @EJB
    private BasitBean basitBean;
    String label;

    /** Creates a new instance of HelloBasit */
    public HelloBasit() {

        System.out.println();
        String label = basitBean.helloBasit();
        System.out.println(label);

    }

    public BasitBean getBasitBean() {
        return basitBean;
    }

    public void setBasitBean(BasitBean basitBean) {
        this.basitBean = basitBean;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

} //end of class HelloBasit

然后我得到了例外

SEVERE: Error Rendering View[/index.xhtml]
com.sun.faces.mgbean.ManagedBeanCreationException: Cant instantiate class: pk.mazars.basitMahmood.HelloBasit.
 at com.sun.faces.mgbean.BeanBuilder.newBeanInstance(BeanBuilder.java:193)
 at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:102)
 ......

为什么我得到这个例外?我理解的流程应该是当我的页面遇到#{helloBasit.label}然后我的构造函数被调用,实例变量被初始化,将bean实例注入basitBean,然后bean方法应该调用。但是在这种情况下,我在 bean 实例中得到了 null,为什么?为什么以前的代码可以工作,但不能?如何从构造函数调用 bean?

谢谢你。

4

2 回答 2

7

尝试将构造函数的内容移动到后构造函数中...

像这样

@PostConstruct
private void init() {
    System.out.println();
    String label = basitBean.helloBasit();
    System.out.println(label);
}

因为只有在托管 bean 启动后才应该注入 ejb bean

@PostConstruct构造函数之后运行(在托管 bean 本身由 JSF 创建之后),然后才将 EJB 注入到 bean 中并且可以访问......

于 2012-09-25T05:46:55.030 回答
0

您的想法是正确的,但我看到一些可能会解决的问题。

  • @LocalBean如果您的 EJB 不直接实现接口,则不需要注释。在这种情况下,无论有没有@LocalBean注释,您都具有相同的效果。如果你想让它明确,你可以离开它。看到这个

  • 确保两者都从包中@ManagedBean导入@SessionScopedjavax.faces.bean

请参阅此工作示例:

EJB

import javax.ejb.Stateless;

@Stateless
public class PersonService { 

    public String getName() {
        return "Cloud Strife";
    }
}

托管豆

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class PersonBean {

    @EJB
    private PersonService ps;

    private String name;

    @PostConstruct
    public void init() {
        name = ps.getName();
    }

    public String getName() {    
        return name;
    }
}

XHTML 页面

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">

    <f:view contentType="text/html">
        <h:head>
            <title>Test</title>
        </h:head>
        <h:body>
            <h1>Welcome, #{personBean.name}</h1>
        </h:body>
    </f:view>

</html>

如果你的值应该只加载一次,比如在你的 bean 构造中,总是更喜欢带有@PostConstruct注释的方法而不是构造函数。

此外,为了在渲染视图之前调用 bean 方法,您可以使用f:event标签,例如:

<f:event type="preRenderView" listener="#{personBean.init}" />

我希望它有帮助!

于 2012-09-25T08:10:40.363 回答