入力テキストといくつかの検証を含む単純なページを考えてみましょう。ページはビュー ステートとして Spring Webflow に含まれます。検証が失敗した場合、検証メッセージを含め、同じビュー ステートを再表示する必要があります。これはうまくいきます。入力とメッセージをカプセル化する複合コンポーネントを使用しても問題なく動作します。
ただし、別のコンポジット内で同じコンポジット コンポーネントを使用すると、次のエラーが発生します。
FacesException: Cannot add the same component twice
この例外は、handleAddRemoveWithAutoPruneと呼ばれるメソッドから発生します。このメソッドは、動的アクション リストにコンポーネントを追加し、コンポーネントが 2 回目に追加されることになっている場合にエラーをスローします。
動作を再現する例を次に示します。
JSFページ
<h:form id="form">
<h:inputText id="text" value="#{bean.someValue}" >
<f:validateLength maximum="3" />
</h:inputText>
<h:message for="text" />
<!-- This will work -->
<test:ccInner anything="Blubb" />
<!-- This will not work -->
<test:ccOuter id="outer" title="Outer Component">
<test:ccInner id="inner" anything="Inner Component" />
</test:ccOuter>
<h:commandButton id="button" type="submit" value="Submit"
action="#{bean.doStuff}" />
</h:form>
コンポーネント
インナー
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="anything" />
</cc:interface>
<cc:implementation>
#{cc.attrs.anything}
</cc:implementation>
</html>
アウター
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="title" />
</cc:interface>
<cc:implementation>
#{cc.attrs.title}
<cc:insertChildren />
</cc:implementation>
</html>
(ビーンとフローの定義は省略。平易な標準的なもの)
私はこれをしばらく調べました。同様の問題を抱えている他の人は通常、反復コンポーネント (dataTable など) 内でコンポジットを使用するときにこの問題に遭遇します。そのため、コンポーネントはビューの作成時およびビューの復元時に動的に追加されます。その後、同じビューへのポストバックで問題が発生します。たとえば、このチケットはこちらを参照してください。そこでは、元の投稿者のエンコード方法の欠陥が原因でエラーが発生しましたが、私のコンポーネントはプレーンでシンプルで、背後にカスタム Java がないため、これは役に立ちません...
それにもかかわらず、2 つの回避策を見つけました。Spring Webflows のドキュメントで説明されているように、同じビュー状態への遷移が発生すると、Webflow は自動的にリダイレクトを実行します。
1)追加してこの動作をオフにする場合
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-attributes>
<webflow:redirect-in-same-state value="false"/>
</webflow:flow-execution-attributes>
</webflow:flow-executor>
問題がwebflow.xml
消えます。ただし、テキストがアドバイスするように、元のリダイレクトは、F5 キーを押したり、戻る/進むを使用したときに、クロムなどの一部のブラウザーでフォームの送信と通知が二重になるのを防ぐために望ましい動作です。
2) 本文にあるように、Ajax リクエストではリダイレクトが発生しないため<f:ajax execute="@form" render="@form" />
、送信ボタンに追加することでも問題は解決します。しかし、完全なフォームの送信に本当に Ajax を使用したいのでしょうか? 私にはちょっと無意味に思えます。
これは今のところ機能しますが、1) 重大な欠点があり、2) 物事が少し複雑になり、常に望ましいとは限りません。したがって、私はむしろ元の問題を解決したいと思います(または、最初にそれを理解します)。また、これが基礎となる実装の問題である場合は、バグ レポートを提出することをお勧めします (まだレポートがない場合)。
編集: Mojarra 2.1.21、JSF 2.1、Spring Webflow 2.3.2 を使用した JBoss での実行