Spring Web Flow
Spring Web Flow概要
本家サイト
多分、昔からのSpring MVC(Grails)使いなら、経験もあるだろうProject。
ターゲットとなるアプリは
- 開始と終了のある一連の業務フローを実行する。
- ユーザーは定義された順序で複数画面を経由して操作を行う。
- 最終的なフローが終了されるまで、変更は反映されない。
- フローが終了すると、そのフローは繰り返されない。
上位のような場合、従来はHTTPセッションにキャッシュしておいて、フロー終了時にコミットする、というのが一般的だと思います。(要件によってはDBに一時情報を入れる場合もあり。)
ただ、戻るボタン、複数タブ、セッションクリアのタイミング等々、色々とバグの温床になります。
そういった課題に対して解決策を提示してくれているのがSpring Web Flowです。
よさそう、よさそうと思っていたけど、試していなかったので、やってみます。
JSFとも連携できますが、この記事ではSpring MVCを前提にします。
フロー定義
Spring Web Flow では、Spring MVCのようなコントローラは記述しません。フロー定義と呼ばれるxmlに画面(View)と処理(Action)の遷移を記述します。フロー定義に基づいて、フレームワークが提供するコントローラが画面遷移と処理を実行します。
フロー定義の例
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<!-- フォームオブジェクトの初期化 -->
<var name="sampleForm" class="sample.SampleForm"/>
<!-- 初期画面「start」ステート。 event1が発行された場合、「action」ステートに遷移する。
イベント発生時には、modelで指定されたオブジェクトにパラメータをバインドさせる。
-->
<view-state id="start" view="start" model="sampleForm">
<transition on="event1" to="action"/>
</view-state>
<!-- 「action」ステート 処理を実行し、実行結果に基づいてステートを遷移させる。 -->
<action-state id="action">
<!-- アクションの実行 -->
<evaluate expression="sampleAction.execute(sampleForm,messageContext)"/>
<transition on="success" to="end">
<!-- アクションの結果を「actionResult」の名前でフロースコープに保存。 -->
<set name="flowScope.actionResult" value="currentEvent.attributes.result"></set>
</transition>
<transition on="error" to="start" />
</action-state>
<!-- 「end」ステート。フローの終了 -->
<end-state id="end" view="end"></end-state>
</flow>
アクセスするURLはフロー定義が配置されたパスによって決まります。
フロー定義配置の例
- ルートフォルダ(設定可能)
|
|-flow-sample-「sample-flow.xml」
上記の例では「/flow/sample」が当該フローを示すURLとなります。初期画面はフロー定義の先頭に記述されたステートです。フロー内部の遷移はリクエストパラメータに応じて行われます。URLは常に「/flow/sample」です。
画面
画面は「view-state」によって定義します。view属性に指定したパスに存在するJSP,もしくはTemplateが「view-state」に紐づく画面になります。
処理
フロー内部での処理は、ステート内部の「evaluate」要素に記述します。Java言語と同じように、インスタンス名.メソッド名で処理を呼び出します。インスタンスはSpringのコンテナに管理されているBeanを利用できます。
Spring Web Flowのメリット
HTTPは基本的にはステートレスで、一回の通信で終わりであるため、HTTPにフィットしたコントローラの処理は、1リクエスト毎に記述するしかありません。
Spring Web FlowはそうしたHTTPの特徴を隠して、複数リクエストにまたがるフローを一つの処理であるかのようにフロー定義上に表現できます。
Spring Web Flowのデメリット
昨今のWeb開発の潮流はコントローラ部分はクライアントサイドで行い、サーバ側は可能な限り、ステートレスであろうとしているようです。これは大量アクセス、画像や動画、音声などのコストの高いデータのやり取りをするようになったことや、よりリッチなUIが求められるようになったことによるものでしょう。
そうした潮流からみると、サーバ上で状態を管理するSpring Web Flowは時代遅れなのかもしれません。
Jsonフォーマットを使った軽量なWebサービスにおいて、複数リクエストにまたがるフローを表現する方法として、HETEOASなどが提案されています。
Spring HETEOAS