Beanが@ViewScopedであるにもかかわらず、@PostConstruct CallBack Fireはなぜですか? JSF
-
04-10-2019 - |
質問
ページでデータテーブルを使用しており、バインディング属性を使用してバッキングビーンにバインドしています。これは私のコードです: -
<?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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
これは私の豆です: -
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
@PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
ボタンをクリックするたびに、 @postconstructがそれぞれ発射するのはなぜですか?私が同じページにいる限り、私の豆が@viewScopedになっているので、それは一度だけ発射する必要があります。さらに、バインディング属性を削除すると、すべてが正常に動作し、@PostConstructコールバックが1回だけ動作します。では、なぜバインディング属性を使用するたびに?バインディング属性が必要であり、WebServiceなどからデータを取得するなどの初期化タスクを1回だけ実行したいと考えています。私は何をすべきか?初期化タスクをどこに書くべきですか?
解決
興味深いことに、ビュースコープビーンでコンポーネントバインディングを使用している場合、ビュースコープが壊れます。
それがJSF2のバグかどうかはわかりませんが、最初にJSF2仕様全体を読む必要があります。今の限りの最善の策は、今のところコンポーネントバインディングをドロップし、新しいEL 2.2メソッド引数構文を介して選択したアイテムを渡すことです。
<h:dataTable var="item" value="#{testBean.stringCollection}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
</h:column>
</h:dataTable>
参照:
- 選択した行を渡すにはどうすればdatAtable内にCommandLinkがありますか?
- ELの引数 /変数 /パラメーターを使用して直接的な方法または方法を呼び出す
- の利点と落とし穴
@ViewScoped
アップデート (2012年12月):これは確かにJSF2のバグです。それは鶏卵の問題です。ビュースコープ豆は、JSFビュー状態に保存されます。したがって、ビュースコープされた豆は、復元ビューフェーズ後にのみ利用できます。しかし binding
属性は復元ビューフェーズ中に実行されますが、ビュースコープされた豆はまだ利用できません。これにより、まったく新しいビュースコープビーンインスタンスが作成され、その後、復元されたJSFビュー状態に保存された実際のビュースコープ豆に置き換えられます。
これはとして報告されています JSF問題1492 と JSF仕様ISSSUE 787 JSF 2.2に対して修正されます。それまでは、あなたの最善の策は使用することです binding
リクエストに応じて、豆のみをスコープしたり、特定の機能要件の代替方法を探します。
アップデート (2015年3月):JSF 2.2の修正は、Mojarra 2.1.18にバックポートされました。したがって、JSF 2.0/2.1をまだ使用している場合は、少なくともそのバージョンにアップグレードするのが最適です。 AOも参照してください JSFのコンポーネント結合とは何ですか?使用することが好ましいときは? と JSF2フェイスラットのJSTL ...理にかなっていますか?
他のヒント
他の人が言ったように、私はしなければならない最善のことはコンポーネントバインディングを落とすことです(ここでは必要ありません)。
しかし、このようなアクションパラメーターを使用して、よりオブジェクト指向のファッションでやろうとしているのと同じことを達成できると付け加えます。
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
...そしてあなたのJavaコードで:
public void action(Item item){
System.out.println("Clicked!!" + item);
}
ビュースコープ付きBeanがあり、フォームに入力された値を保持したい場合、またはPostconstructの発射を望まない場合は、アクションメソッドからnullを返す必要があります。
結果を返し(例:無効)、Faces-config.xmlを使用して無効な結果を同じページに向けると、ビュースコープされたビーンが再作成され、ポストコンストラクトが再び発生します。
その他の解決策:
- リクエストスコープビーンでHTMLDATATABLEをバインドします。
- ビュースコープビーンにこのリクエストスコープビーンを注入します。
JBoss Seamこのソリューションを使用して、JSFコンポーネントを会話スコープコンポーネントに結合します。
Baluscの答えは私を大いに助けてくれました。Mojarraバージョン2.1.7でそのバグがあったと言いたいです。現在、2015年1月にリリースされた2.1.29-01を使用しています。このバグは修正されました。ビュースコープ付きの豆へのtabview。このバージョンでは、私はそのバグとバインディングを持っていません。私はJBoss 5.2を使用しており、Mojarra 2.1.xを使用する必要があるので、この答えが同じ状況にある他の人々に役立つことを願っています。
http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01 http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01