この質問は、JSF2 への部分的な回答から生成されます: なぜコンポジットで panelGroup のレンダリングされた空のテストがアクションの呼び出しを妨げるのですか?
以下の Element は、名前と ID を持つ @Entity です。view.xhtml JSF ページは ID を viewParam として受け取り、 @ManagedBean @RequestScoped ElementController の setID(Long ID) を使用して、対応する Element のロードをデータベースからの ID でトリガーします (これは問題ではそれ以上の役割を果たしません)。 Element は、Element getSelected() として使用可能な「現在の」Element として設定されます (歴史的な理由により、名前が若干異なります)。
view.xhtml ページはレンダリングされた属性テスト #{not empty elementController.selected} を実行し、faces-redirect を実行するアクションを含む ah:commandButton をクエリ パラメータとしての id と共に、view.xhtml ページに戻します。
何らかの理由で完全には理解できませんが、フォームの送信時に、viewParam id が設定される前に (したがって、現在/選択された要素が設定される前に)、リクエストの適用フェーズとプロセスの検証フェーズの両方でテスト (および getSelected) が呼び出されます。モデル値の更新フェーズで検出および設定されます)。
大幅に省略された view.xhtml ページは次のとおりです。
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{elementController.id}"/>
</f:metadata>
</f:view>
<h:body>
<h:form>
<h:panelGroup rendered="#{not empty elementController.selected}">
<h:outputText value="#{elementController.selected.name}"/>
</h:panelGroup>
<h:commandButton value="Apply" action="#{elementController.action}" />
</h:form>
</h:body>
(上記ではフォーム送信の意味が失われていますが、この質問には関係ありません。)
ElementController は RequestController を拡張します。
public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
this.id = id;
T found = (T) getAbstractFacade().find(id);
if (found == null) {
String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
log_error($error);
}
setCurrent(found);
}
}
public T getSelected() {
log_debug("getSelected","current",current);
if (current == null) {
log_warn("getSelected","null current Element");
}
return current;
}
public Object action() {
String $i = "action";
log_debug($i);
if (current==null) {
log_warn($i, "can't generate action outcome for null current element");
return null;
}
return "/view?faces-redirect=true&id="+current.getId();
}
フォーム送信時に getSelected() がたまたま 2 回呼び出され、current==null の場合は、リクエスト値の適用フェーズで 1 回、プロセス検証フェーズで 1 回です。 view.xhtml の viewParam のおかげで、id の設定 (および Element エンティティの読み込み) を行うことができます。
問題は、なぜ render=#{not empty elementController.selected} がリクエストの適用フェーズとプロセスの検証フェーズで呼び出されるのかということです。
これらのフェーズでは、id パラメータを指定して view.xhtml の初期 GET ロードを実行するときに呼び出されません。フォーム送信 POST とその後のリダイレクトおよび GET の間のみです。