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

原因ejbBeanは、管理対象Beanが開始された後にのみ注入する必要があります

@PostConstructコンストラクターの後に実行され(その後、マネージドBean自体がJSFによって作成された後)、EJBがBeanに注入され、アクセスできるようになります...

于 2012-09-25T05:46:55.030 に答える
0

あなたの考えは正しいですが、修正される可能性のあることがいくつかあります。

  • @LocalBeanEJBがインターフェースを直接実装していない場合は、アノテーションは必要ありません。この場合、@LocalBean注釈の有無にかかわらず、同じ効果があります。ただし、明示的にしたい場合は、そのままにしておくことができます。これを参照してください。

  • 両方を確認し@ManagedBean、パッケージ@SessionScopedからインポートしてください。javax.faces.bean

この作業サンプルをご覧ください。

EJB

import javax.ejb.Stateless;

@Stateless
public class PersonService { 

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

マネージドBean

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の構築時など、値を1回だけロードする必要がある場合は@PostConstruct、コンストラクターではなく、常にアノテーション付きのメソッドを使用してください。

f:eventまた、ビューをレンダリングする前にBeanメソッドを呼び出すには、次のようなタグを使用できます。

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

お役に立てば幸いです。

于 2012-09-25T08:10:40.363 に答える