7.7. ナビゲーション
Seam アプリケーションの
faces-config.xml で定義された標準の JSF ナビゲーションルールを使用することができます。ただし、このルールには制限がいくつかあります。
- リダイレクト時に要求パラメータの使用は指定できません。
- 規則から対話を開始または終了することはできません。
- 規則はアクションメソッドの戻り値を評価することにより動作するため、 任意の EL 式を評価することはできません。
pages.xml と faces-config.xml の間に、「オーケストレーション」ロジックが分散するという別の問題があります。pages.xml でこのロジックを統合した方が適切です。
この JSF ナビゲーションルールは
<navigation-rule>
<from-view-id>/editDocument.xhtml</from-view-id>
<navigation-case>
<from-action>#{documentEditor.update}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/viewDocument.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/editDocument.xhtml</from-view-id>
<navigation-case>
<from-action>#{documentEditor.update}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/viewDocument.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
次のように書き直すことができます。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if-outcome="success">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if-outcome="success">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
しかし、このメソッドは
DocumentEditor を文字列の戻り値 (JSF の結果) で汚してしまいます。 代わりに Seam では次のように記述することができます。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}"
evaluate="#{documentEditor.errors.size}">
<rule if-outcome="0">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}"
evaluate="#{documentEditor.errors.size}">
<rule if-outcome="0">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
または、次のように記述することもできます。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
最初の形式は値バインディングを評価して後続のルールにより使用される結果の値を決定します。2 番目の方法は結果を無視してそれぞれ可能なルールに対して値バインディングを評価します。
更新が成功したら、 現在の対話を以下のように終了させることができます。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<end-conversation/>
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<end-conversation/>
<redirect view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
対話が終了しているため、 後続の要求は関心があるドキュメントを認識しなくなります。要求パラメータとしてドキュメント ID を渡すことができ、これによりビューをブックマーク可能にします。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<end-conversation/>
<redirect view-id="/viewDocument.xhtml">
<param name="documentId" value="#{documentEditor.documentId}"/>
</redirect>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule if="#{documentEditor.errors.empty}">
<end-conversation/>
<redirect view-id="/viewDocument.xhtml">
<param name="documentId" value="#{documentEditor.documentId}"/>
</redirect>
</rule>
</navigation>
</page>
結果が null となるのは JSF では特別なケースであり、「そのページを再表示する」という意味に解釈されます。 次のナビゲーションルールは null 以外ならいずれの結果とも一致しますが、 null の結果には 一致しません。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule>
<render view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<rule>
<render view-id="/viewDocument.xhtml"/>
</rule>
</navigation>
</page>
結果が null の場合にナビゲーションを実行するには次の形式を使います。
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<render view-id="/viewDocument.xhtml"/>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation from-action="#{documentEditor.update}">
<render view-id="/viewDocument.xhtml"/>
</navigation>
</page>
ビュー ID は JSF EL 式となることができます。
<page view-id="/editDocument.xhtml">
<navigation>
<rule if-outcome="success">
<redirect view-id="/#{userAgent}/displayDocument.xhtml"/>
</rule>
</navigation>
</page>
<page view-id="/editDocument.xhtml">
<navigation>
<rule if-outcome="success">
<redirect view-id="/#{userAgent}/displayDocument.xhtml"/>
</rule>
</navigation>
</page>