DeltaSpikeの例外処理 (1)

DeltaSpikeの例外処理は、Seam3 Solderの例外処理と基本的な考え方は一緒と言っていいでしょう(開発者も同じ人です)。ただし、@HandlesExceptionsが@ExceptionHandlerに変更されていたり、CaughtExceptionがExceptionEventになっていたりするので、両者の間でのAPIの完全な互換性はありません。

DeltaSpikeの例外処理のAPIについてはドキュメントに詳しく書かれています。概要は次の通り。

  1. アプリケーションがJava例外をキャッチしてそれをCDIのイベント(ExceptionToCatchEvent)としてfireする。
  2. 例外ハンドラーのメソッド引数でExceptionEventをキャッチする。
  3. ExceptionEventのメソッドを使って例外処理を実行する。

例外ハンドラーの具体例は次のようになります(ドキュメントからの引用です)。例外ハンドラーには@ExceptionHanlderというアノテーションがついています。また、例外をキャッチするためのメソッド引数には@Handlesでマークされています。

@ExceptionHandler
public class MyHandlers
{
   void printExceptions(@Handles ExceptionEvent<Throwable> evt)
   {
      System.out.println("Something bad happened: " +
            evt.getException().getMessage());
      evt.handleAndContinue();
   }
}

次のコードは、DeltaSpikeのサンプルコードからの引用になります (org.jboss.seam.examples.booking.exceptioncontrol) 。この例のように、例外ハンドラーは複数のメソッドを持ち、それぞれのメソッドごとに別々の種類の例外をキャッチすることができます。

@ApplicationScoped
@ExceptionHandler
public class ExceptionHandledHandler
{
    private boolean exAscCalled = false;
    private boolean iaeAscCalled = false;
    private boolean npeDescCalled = false;

    public void exHandler(@Handles ExceptionEvent<Exception> event)
    {
        exAscCalled = true;
    }

    public void npeHandler(@Handles ExceptionEvent<IllegalArgumentException> event)
    {
        iaeAscCalled = true;
        event.handled();
    }

    public void npeDescHandler(@BeforeHandles ExceptionEvent<NullPointerException> event)
    {
        npeDescCalled = true;
        event.handled();
    }
// ...

以上から、DeltaSpikeの例外処理の特長は次のようになることがわかります。

  • 例外ハンドラーを定義するBeanである。つまり、アプリケーション本体とは切り離して定義でき、例外処理をそこに集約することができる。
  • 例外の宣言はタイプセーフである。つまり、Java例外のクラス名はJava Genericesの型変数として設定されるので、クラス名をタイプミスした場合はコンパイル時に検出される。
例外ハンドラーはCDI Beanです。上の例では例外ハンドラー自身にも@ApplicationScopedが宣言されています。このことは、CDIのBeanとして、さらにそれ自身を拡張をすることが可能であることを意味します。例えば、@Alternativeをつけて例外コンポーネントを切り替えたり、DeltaSpikeの@Excludeを使ってフェーズごとにコンポーネントを切り替えることもできるでしょう。
タイプセーフについては、Seam2の例外処理との違いを調べれば一目瞭然です。Seam2ではXMLファイルに例外の宣言を書いていたため、そこでクラス名をタイプミスをするとデプロイ実行時エラーになってしまいました。CDI仕様では、タイプセーフや疎結合というのがモットーとなっています。DeltaSpikeの例外処理は、それを継承しつつCDI時代の新しい例外処理フレームワークを定義しています。
DeltaSpikeの例外処理はこれですべてではありませんが、続けて書くと長くなりそうです。そこで、DeltaSpike例外処理を2回に分けて、次回は例外のチェーン処理について書くことにします。