と
の続きです。
今回はNonexistentConversationExceptionからの画面遷移を考えます。
やりたいこと(妥協もあり)
NonexistentConversationExceptionからの会話開始画面へ遷移する
NonexistentConversationExceptionは、元となるConversationScopeのインスタンスがタイムアウトしているか、何らかの理由で(URLパラメータ変更とか)対象のページに遷移できないために発生します。
BusyConversationExceptionと違って、遷移前の状態を取得することは出来ない前提で考える必要があります。
したがって、新たな会話を開始させるしかありません。
状態管理は不可
上述の通り、情報が存在しません。
メッセージはデフォルトだけでなく独自指定も
デフォルトのメッセージは、Message.propertiesにキーを
javax.enterprise.context.BusyConversationException
として記述しておきます。
基本的に「対象操作はタイムアウトしたので、始めからやり直してください」ということを伝えるだけなので、個々のユースケースで出力を変えることはないかもしれませんが、「登録」と言う表現が妥当な場合もあれば、「保存」や「処理」が必要なケースは容易に想像できます。
したがって、ユースケースに応じたメッセージも出力できるようにします。
BusyConversationと違って、遷移先は開始ページ固定なので ユースケース全体で1つ指定できることをゴールとします。
メッセージ実装はURL(フォルダパス)
正直、妥協です。
ServletFilterから使える情報は基本的にはリクエストです。
BusyConversationであれば、会話スコープのインスタンス自体は残っていたので 迂回しても色々な情報を活用できましたが、今回はそうはいきません。
リクエストに出力するメッセージに関する情報を載せてこないといけません。
ですが、NonexistentConversationExceptionはいつ発生するか分かりません。
となると常にリクエストに 当該ユースケースにおけるメッセージ情報を持ちまわらないといけません。
正直、それは内部実装の暴露ですし、URLに「対象操作は云々」というパラメータが表示されているのは良くありません。
HttpHeaderなどで保持しておくということも考えましたが、結局 毎回のレスポンスに 暴露的な情報を持たせるという設計思想は どうもしっくりきません。
結論としては、URLのパスが同一フォルダである場合を 同一会話スコープとしている設計指針から考えると当該ユースケースを現す情報として フォルダパスを使うのが良いかな?という考えに至りました。
実装
例外補足からデフォルトのメッセージ出力まで当初案を そのままなので割愛します。
(多少のパラメータ追加があっただけ)
独自メッセージに関するところだけ記します。
Message.propertiesに以下の記述をしておけば、当該パスの会話中にNonexistentConversationExceptionが発生した場合は、
デフォルトメッセージではなく 記述しているメッセージが適用されます。
/apps/taskbase/=タイムアウトしました。
Code
vermeer_etc / jsf-ddd / source / — Bitbucket
さいごに
とりあえず、ConversationScoped周りは これで一段落ついたかな?
観測範囲で ここまで変態的に ConversationScopedを使い倒している例は 見当たらないから やった意義はあったと自己満足。