Seasar DI Container with AOP

トランザクションの自動制御

S2Txの機能を使って、POJO(普通のJavaのクラス)に対して、Aspectでトランザクションの自動管理機能を組み込むことができます。EJBコンテナが提供するようなトランザクション管理機能をPOJOに対して透明に組み込むことができるのです。組む込むことのできるトランザクション属性は次のとおりです。

トランザクション属性

S2が標準で用意しているj2ee.diconには、次のトランザクション属性に対応したAdviceが定義されています。コンポーネント名がAdviceの名前です。

属性 コンポーネント名 説明
Required j2ee.requiredTx トランザクションが開始されていなければ、
自動的にトランザクションを開始します。
既にトランザクションが開始されていれば、
そのトランザクションを引き継ぎます。
RequiresNew j2ee.requiresNewTx 常に新しいトランザクションを開始させます。
既存のトランザクションが開始されているなら、
既存のトランザクションを中断し、
自分自身のトランザクションの終了後、
中断したトランザクションを復帰させます。
Mandatory j2ee.mandatoryTx トランザクションが既に開始されてなければエラーにします。
NotSupported j2ee.notSupportedTx 既存のトランザクションが開始されているなら、
既存のトランザクションを中断します。
コンポーネントのメソッドの終了後、
中断したトランザクションを復帰させます。

Example

Hoge.java

package examples.tx;

public interface Hoge {

    public void foo();
}

HogeImpl.java

package examples.tx;

public class HogeImpl implements Hoge {

    public void foo() {
        System.out.println("foo");
    }
}

HogeClient.dicon

<components>
<include path="j2ee.dicon"/>
<component class="examples.tx.HogeImpl">
<aspect>j2ee.requiredTx</aspect>
</component>
</components>

HogeClient.java

package examples.tx;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

public class HogeClient {

    private static final String PATH =
        "examples/tx/HogeClient.dicon";

    public static void main(String[] args) {
        S2Container container = S2ContainerFactory.create(PATH);
        Hoge hoge = (Hoge) container.getComponent(Hoge.class);
        hoge.foo();
    }
}

実行結果

DEBUG 2004-03-14 18:05:18,402 [main] Transaction.begin()
foo
DEBUG 2004-03-14 18:05:18,432 [main] Transaction.commit()

j2ee.diconはS2としてあらかじめ用意(srcの直下)されています。Adviceのコンポーネント名をaspectタグのボディに指定するだけなので簡単です。 POJOに簡単にトランザクション管理機能が組み込めることがわかってもらえたと思います。

例外発生時の動作

j2ee.diconに定義されているAdviceは、コンポーネントが例外をスローした場合はトランザクションをロールバックします.
発生した例外に応じてトランザクションをコミットするかロールバックするかを指定することもできます。

  • AdviceのaddCommitRule(Class)メソッドを使用すると、コンポーネントからスローされてもトランザクションをコミットする例外を指定することができます。
  • AdviceのaddRollbackRule(Class)メソッドを使用すると、コンポーネントからスローされてもトランザクションをロールバックする例外を指定することができます。

コンポーネントから例外がスローされると、addCommitRule()/addRollbackRule()が設定された順番にマッチするかチェックされます。スローされた例外がaddCommitRule()/addRollbackRule()で指定された例外またはその派生例外であれば、その設定に従ってトランザクションをコミットまたはロールバックします。スローされた例外がaddCommitRule()/addRollbackRule()で指定された例外とマッチしない場合、トランザクションはロールバックされます。

Example

MyTx.dicon

次の例では、実行時例外 (java.lang.RuntimeException) またはその派生型がスローされた場合はロールバック、例外 (java.lang.Exception) またはその派生型がスローされた場合はコミットするRequired のAdviceとしてmyTxを定義しています.
実行時例外 (java.lang.RuntimeException) は例外 (java.lang.Exception) の派生例外であるため、設定する順番を逆にすると実行時例外 (java.lang.RuntimeException) がスローされた場合でもコミットされてしまうので注意してください (Java言語のcatch節と似ています)。

<components>
<include path="j2ee.dicon"/>
<component name="myTx" class="org.seasar.extension.tx.RequiredInterceptor"> <initMethod name="addRollbackRule"> <arg>@java.lang.RuntimeException@class</arg> </initMethod> <initMethod name="addCommitRule"> <arg>@java.lang.Exception@class</arg> </initMethod> </component> </components>

EJB互換のAdvice

S2が標準で用意しているejbtx.diconには、EJBのコンテナ管理トランザクション (CMT) と同じように実行時例外 (java.lang.RuntimeException)・リモート例外 (java.rmi.RemoteException) とその派生例外が発生した場合はロールバックし、その他の例外 (java.lang.Exception) が発生した場合はコミットするAdviceが定義されています。コンポーネント名がAdviceの名前です。

属性 コンポーネント名
Required ejbtx.requiredTx
RequiresNew ejbtx.requiresNewTx
Mandatory ejbtx.mandatoryTx
NotSupported ejbtx.notSupportedTx