S2JSFでダーティリード対応 しょにょ2(谷岡先生風)

ピンポェ〜ン。例外はLogicクラスで投げようキャンペーンが開始された訳ですが、そこへ踏み込む前に、まずはどんな動きするか確認したいので安易な方法でダーティリード対策してみました。

Logicクラスは処理モードを知るべきか

どんな方法かと云うと、ActionThrowsInterceptor#handleThrowableをオーバーロードしちゃってみたりなんかしたりしたのです。早くMr.Booボックス来ないかな。

で、ダーティリード時にseasarから投げられるUpdateFailureRuntimeExceptionをキャッチしてまうのです。

●ActionThrowsInterceptor

    public String handleThrowable(AppRuntimeException ex, MethodInvocation invocation) 
        throws Throwable {
		
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, MessageUtil.getErrorMessage(ex.getMessageId(), ex.getArgs()));
        return null;
    }
    
    public String handleThrowable(UpdateFailureRuntimeException ex, MethodInvocation invocation) 
        throws Throwable {
		
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, MessageUtil.getErrorMessage("example.jsf.UpdateFailure", null));
        return null;
    }

もちろんappMessages_ja.propertiesに上で指定してるメッセージを追加します。あくまでも動作確認のための応急処置ですよ。ちゃんとアプリケーション固有の例外クラス(サンプルではAppRuntimeException)を継承した専用の例外を作り、UpdateFailure・・・をそっちに振り替えて、元々のhandleThrowableで一括管理させるのが筋です。

ブラウザ2つ立ち上げて、同じデータに時間差攻撃で更新、どりゃっ!見事メッセージ表示されました。イェー。

と思ったが。

サンプルは編集画面 → 確認画面 と遷移して登録、となってますが、この確認画面にエラー表示されるんですけど、登録ボタンが出っ放しなのです。当然です。処理モードが更新モードのままですから。

で、エラーが出たまま登録ボタンを押すとなんと!エラー表示されてる画面の内容でちゃんと更新が出来ちゃうのです。バージョンNoが最新に置き替わってるのかな?うーん、従業員情報、再取得してないんだけど。謎だ。

てな訳で、登録エラーなのに登録ボタンが生きてるのは随分と不健全なUI設計です。

て事はですな、更新エラー時には処理モードを登録ボタンが非表示となる何かに変更しなけりゃいけないのです。つまり、UpdateFaulureRuntimeExceptionが発生した時、処理モードを保持しているProcessModeDtoを知っていなけりゃならんのです。

サンプルを見ると、LogicクラスではProcessModeDtoは一切見てません。見てるのはActionクラスのみで、つまりは処理モードはプレゼンテーション層内で閉じられた関心事だと云う位置付けの様です。そしてその方針に反論するのはなかなかに面倒そうなので頷いておくのが吉っぽいです(ああ情けない判断基準だ)。

それにLogicクラスはステートレスにしてSingletonが基本ですから、そこへsessionオブジェクトであるProcessModeDtoをインジェクションするのは、もう何がなんだかわけわかめになってしまいます(ちゃんとした判断も出来るのだ)。

ProcessModeDto#setProcessModeを書き換えるのはActionクラスで、て事になりましょう。そうすると結局Action側でもキャッチせにゃならん事に。

で、それは各画面共通の関心事ですから、ActionThowsInterceptorかそれに準じた専用のInterceptorでアスペクトでやりたいのが人情。そうなると、そのInterceptorはProcessModeDtoを知ってなきゃならん事に。

これも無理だよなー。InterceptorもLogicと同じくsessionオブジェクトを持てないでしょう。何か良い手はないか。Actionクラスのメソッド一個一個の中でやらなきゃいかんかなあ・・・。

むーん、根本的に間違ってるのかなあ。