web-dev-qa-db-ja.com

非リクエストスコープBeanの@ManagedProperty(value = "#{param.id}")

@managedBeanにパラメーター(POST)を渡す必要があります。次のような管理プロパティを使用しました:

@ManagedProperty(value = "#{param.id}")
private int id;

そして、BeanのスコープはViewScopeです。

私はこのエラーで終わります:

管理対象のBeanレシートを作成できません。次の問題が見つかりました。-式#{param.id}、requestによって参照されるオブジェクトのスコープが、参照する管理対象Beanのビューのスコープよりも短い

私に何ができる?

arjanを見てください:

マイページ:フェイスレットタイトル

<form method="post" action="faces/index.xhtml">
  <input name="id" value="4" />
  <input type="submit" value="submit" />
</form>

<h:form>
  <h:commandLink value="click" action="index">
    <f:param id="id" name="id" value="20"/>
  </h:commandLink>
</h:form>
17
ehsun7b

二つの方法:

  1. Beanリクエストのスコープを設定し、スコープのあるビューを別の@ManagedPropertyとして注入します。

    @ManagedBean
    @RequestScoped
    public class RequestBean {
    
        @ManagedProperty(value="#{param.id}")
        private Integer id;
    
        @ManagedProperty(value="#{viewBean}")
        private ViewBean viewBean;
    }
    

    ビュースコープのBeanは、@PostConstructおよびリクエストスコープのBeanのアクションメソッドで使用できます。パラメータなしで同じビューにポストバックすると、idが失われる可能性があることに注意する必要があります。

  2. または、Beanの初期化中にリクエストパラメータマップから手動で取得します。

    @ManagedBean
    @ViewScoped
    public class ViewBean {
    
        private Integer id;
    
        @PostConstruct
        public void init() {
            id = Integer.valueOf(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id"));       
        }
    }
    

    このようにして、最初のidはビュースコープ全体で使用できます。

38
BalusC

Beanのリクエストから直接パラメータを取得する代わりに、view parametersを使用できます。

これらは、マネージドBeanを使用するFaceletで次のように宣言する必要があります。

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://Java.Sun.com/jsf/html"
    xmlns:f="http://Java.Sun.com/jsf/core"
>
    <h:body>

    <f:metadata>
        <f:viewParam id="id" name="id" value="#{myBean.id}" />        
    </f:metadata>

    <!-- Rest of Facelet here -->   

    </h:body>
</html>

このページをリクエストすると、idパラメータに指定されたリクエスト値を使用してバッキングBeanのセッターが呼び出されます。これは、GETリクエストと(顔以外の)POSTリクエストの両方で機能します。

利点は、ここで標準のJSFコンバーターとバリデーターを使用できることです。もちろん、マネージドBeanが特定のビューに関連付けられていない場合、このソリューションはあまり理想的ではありません。

注意すべき小さな特殊な点は、ビューパラメータを指定した最初のリクエストの後に通常のフェイスポストバックを実行すると、Beanがビュースコープ内にあり、新しい値が明示的にない場合でも、Beanのセッターが再度呼び出されることです。提供されます。

これが機能することをテストするために、次のマネージドBeanを使用しました。

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;

@ManagedBean
@ViewScoped
public class MyBean {

    Long id;

    @PostConstruct
    public void test() {
        System.out.println("post construct called");
    }

    public void actionMethod(ActionEvent event) {       
        System.out.println("action called");        
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

}

そして、次のフェイスレット:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://Java.Sun.com/jsf/html"
    xmlns:f="http://Java.Sun.com/jsf/core"
>
    <h:body>

        <f:metadata>
            <f:viewParam id="id" name="id" value="#{myBean.id}" />        
        </f:metadata>

        <h:outputText value="#{myBean.id}"/>

        <h:form>
            <h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
        </h:form>

        <form method="post">
            <input name="id" value="4" />
            <input type="submit" value="submit" />
        </form>

    </h:body>
</html>

入力フィールドに番号を入力し、送信ボタンをクリックします。番号が画面に印刷されている場合、テストは成功しています。 2番目のフォームは通常のフォームであり、JSF状態を投稿しないことに注意してください。これをJBossAS 6でテストしたところ、機能しました。 idパラメーターをGETパラメーターとして証明することもできます。

6
Arjan Tijms