アプリケーションで例外が発生した場合の処理を制御するには、例外ハンドラの機構を使用します。
例外ハンドラはorg.seasar.ymir.handler.ExceptionHandlerインタフェースを継承したクラスです。例外ハンドラインスタンスについては、Pageインスタンスと同様S2Containerによる暗黙的なDIは行なわれません。 S2ContainerによるDIを行ないたい場合は、@Bindingアノテーションを使って明示的に指定するか、Ymirの@Injectアノテーションを使用して下さい。
例外ハンドラの登録
アプリケーションのルートパッケージの下のhandlerパッケージの下に「対応する例外クラス名(パッケージ部分なし)+「Handler」という名前で作成しておけば、例外ハンドラとして自動的にコンポーネント登録されます(例:IllegalArgumentException → IllegalArgumentExceptionHandler)。
例外ハンドラの探索
リクエストの処理中に例外Eが発生した場合、Ymirは以下の順序で例外ハンドラを探します。
- SeasarからEに対応する例外ハンドラを探します。
- 見つからなくてかつEのスーパークラスがExceptionまたはExceptionのサブクラスならば、Eのスーパークラスに対応する例外ハンドラを探します。
- 2.の処理を再帰的に繰り返します。
デフォルトの例外ハンドラ
例外ハンドラが見つからなかった場合はデフォルトの例外ハンドラが使用されます。デフォルトの例外ハンドラとその処理は以下のとおりです。
例外 | 処理 |
---|---|
PageNotFoundRuntimeException | HTTPレスポンスにステータス404(Not Found)をセット |
ActionNotFoundRuntimeException | HTTPレスポンスにステータス405(Method Not Allowed)をセット |
PermissionDeniedException | HTTPレスポンスにステータス403(Forbidden)をセット |
その他 | 例外を再スロー |
例外ハンドラの呼び出し
例外ハンドラの呼び出しに先立って、Pageオブジェクトの場合と同じようにオブジェクトスコープからのオブジェクトのインジェクション処理が行なわれます。すなわち、@Inアノテーションが付与されているSetterメソッドがあれば、アノテーションに従ったオブジェクトスコープからオブジェクトが取り出されてSetterメソッドを使ってオブジェクトがセットされます。
次に例外ハンドラのhandleメソッドが呼び出されます。handleメソッドの引数にはスローされた例外オブジェクトが渡されます。
最後にオブジェクトスコープへのオブジェクトのアウトジェクション処理が行なわれます。すなわち、@Outアノテーションが付与されているGetterメソッドがあれば、アノテーションに従ったオブジェクトスコープにGetterメソッドの返り値が格納されます。
例外ハンドラの呼び出し後の遷移
リクエストの処理の流れが例外ハンドラに切り替えられると、パススルー先が/WEB-INF/template/exception/例外クラス名.htmlという画面に切り替えられます。ここでの例外クラス名はスローされた元々の例外クラスの名前ではなく、例外の処理を行なった例外ハンドラに対応する例外クラスの名前です。
handleメソッドの返り値はPageクラスのアクションメソッドと同じようにレスポンスを表すものとみなされますので、返り値として"passthrough:"という文字列を指定してパススルーさせた場合、/WEB-INF/template/exception/例外クラス名.htmlにフォワードすることになります。
また、例えばエラーページ/error.htmlにフォワードしたい場合はhandleメソッドの返り値を"/error.html"とすれば良いことになります。
テンプレートから例外ハンドラオブジェクトを参照する
例外ハンドラオブジェクトに持たせたエラーメッセージなどをフォワード先の画面で表示できるよう、例外の処理を行なった例外ハンドラオブジェクトをrequestスコープにhandlerという名前でバインドしています。