2011-03-07 5 views
2

EJB 3.1セッションBean:Session BeansでカスタムExceptionを使用するには?

import javax.ejb.*; 
public class FooException extends EJBException { 
} 
@Stateless @Local 
public class Foo { 
    public void bar() throws FooException { 
    if (/* something wrong */) { 
     throw new FooException(); 
    } 
    } 
} 

今すぐテスト:

import org.junit.*; 
public class FooTest { 
    @Test(expected = FooException.class) 
    public void testException() { 
    new InitialContext().lookup("Foo").bar(); 
    } 
} 

問題がEJBExceptionがテスト、ないFooExceptionに巻き込まれていることです。 EJBコンテナが私のカスタム例外型についての情報を失い、基本型(EJBException)を投げるように見えます。ここで何が間違っていますか? (OpenEJB 3.1)

答えて

6

まず、@Localアノテーションをここで使用する必要はありません。これは、ローカルインタフェースとしてのインタフェースを指定します。あるいは、(あなたの場合の)Beanで使用される場合、(value属性を介して)ローカルインタフェースを指すために使用できます。いずれの場合もここでは適用できません。指定されたコードもコンパイルされません。 lookup( "Foo")は、キャストする必要があるObjectを返します。

とにかく問題については、EJBコンテナは情報を失いませんが、例外をEJBExceptionにラップします。これは、FooExceptionが最終的にRuntimeExceptionから継承するためです。そのような例外はコンテナによってnonapplication exceptionとして処理され、EJB仕様ではそれらをラップする必要があると定義されています。

あなたの状況では既にEJBExceptionから拡張されているので、これはコーナーケースのようです。例えば、JBoss AS 6はこのような状況では余分なラッピングをしませんが、明らかにOpenEJBはそうしています。

この問題は、FooExceptionがEJBExceptionから継承されないようにするか、テストで例外をキャッチし、アンラップしてラップ解除された例外を再利用することで解決できます。

barメソッドがFooExceptionをスローすると宣言しているので、私は、EJBExceptionがRuntimeExceptionであり、アプリケーション以外の例外であることを認識していないと考えています。なぜあなたはEJBExceptionからFooException inherritを許可しましたか?あなたはこれが何とか必要と思ったのですか、あるいはこれが何らかの特別な目的を果たす必要がありますか?

(余分なヒントとして、あなたが任意のトランザクションをロールバックし、プールされた豆を破壊に関しては、アプリケーションとnonapplicaton例外の違いを理解させる)

+1

'ApplicationException' @は、成功への鍵である、あなたに感謝コメント。 – yegor256

関連する問題