レベル: 中級 小林 浩一 (koichik@improvement.jp), Seasarプロジェクト
2008年 3月 28日 本連載では,軽量コンテナ Seasar2 を IBM WebSphere Application Server や IBM DB2 と連携させる方法について紹介します.連載の第 3 回目となるこの記事では,Seasar2 の宣言的トランザクションについて紹介します.
はじめに
データベースを利用するアプリケーションで不可欠なのがトランザクション制御です.Enterprise JavaBeans (以下 EJB) のコンテナ管理トランザクション (Container Managed Transaction,以下 CMT) で広く知られることになった宣言的トランザクションは,トランザクション制御のためのコードを記述する必要がないことために手間がかからず,トランザクション制御を忘れることもないなど,メリットの大きな技術です.Seasar2 でも EJB と同じような宣言的トランザクションを提供しています.
以下では,Seasar2 が宣言的トランザクションを実現している方法や,その利用方法について説明します.
Seasar2 によるアスペクト指向プログラミング
Seasar2 は,Dependency Injection (以下 DI) と共にアスペクト指向プログラミング (Aspect-Oriented Programming,以下 AOP) をサポートした軽量コンテナです.Seasar2 が提供する AOP 機能は,S2AOP と呼ばれます.
S2AOP では,コンポーネントのサブクラスを動的に生成することにより AOP を実現しています(図 1).
図 1. S2AOPの実現方法
サブクラスの動的な生成には,Javassist を使用しています.
横断的関心事は,インターセプタとして実装します.S2AOP のインターセプタは AOP Alliance に準拠したもので,AspectJ の around advice に相当します.一つのクラスに複数のインターセプタを適用することができます.
メソッドが呼ばれると,動的に生成されたサブクラスでオーバーライドされたメソッドが呼び出されます(図1-①).オーバーライドされたメソッドは,インターセプタを呼び出します(図1-②).インターセプタは固有の処理を行った後,後続のインターセプタに制御を渡します(図1-③).インターセプタがチェーンの最後の場合は,元のクラスのメソッドに制御が渡ります(図1-④).
S2AOPは,このように動的に生成されたサブクラスとインターセプタを用いてAOPを実現しています.
S2Tx による宣言的トランザクション制御
AOP の典型的な用途の一つがトランザクション制御です.Seasar2 では,S2AOP を利用して宣言的トランザクションを実現するためのインターセプタを,S2Tx として提供しています.
S2Tx の宣言的トランザクションは,EJB の CMT と同様のトランザクション属性を提供します(表1).
表 1. S2Tx のトランザクション属性
| Required | トランザクションが開始されていなければ自動的にトランザクションを開始します.既にトランザクションが開始されていれば,そのトランザクションを引き継ぎます. |
|---|
| RequiresNew | 常に新しいトランザクションを開始させます.既存のトランザクションが開始されていれば既存のトランザクションを中断し,新しいトランザクションの終了後,中断したトランザクションを復帰させます. |
|---|
| Mandatory | トランザクションが既に開始されてなければエラーにします. |
|---|
| NotSupported | 既存のトランザクションが開始されていれば既存のトランザクションを中断します.コンポーネントのメソッドの終了後,中断したトランザクションを再開します. |
|---|
これらのインターセプタは,j2ee.dicon という Seasar2 が提供する設定ファイルにあらかじめ定義されているため,すぐに使用することができます.
EJB の CMT とは異なり,S2Tx のインターセプタは例外が発生すると,その種類にかかわらずトランザクションをロールバックします.EJB と同様に,RuntimeException や RemoteException の派生例外を除いた「アプリケーション例外」ではトランザクションをコミットするインターセプタや,EJB3.0 と同様に ApplicationException アノテーションでロールバックするかしないかを制御することのできるインターセプタも用意しています.
UOWManager 対応
バージョン 2.4.17 以前の Seasar2 では,S2Tx のインターセプタは直接的に Java Transaction API (以下 JTA) の TransactionMaanger を呼び出していました(図2-①).しかし,前回の記事で説明されているように,JTA TransactionManager はアプリケーションから呼び出すことが想定された API ではないため,WebSphere Application Server (以下 WAS)では,非公開(サポート対象外)の情報に基づいて S2Tx を使用せざるを得ませんでした.
そこで,Seasar2 バージョン 2.4.18 からは,S2Tx はアダプタを介してトランザクション制御を行う API を呼び出すようになりました(図2-②).JTA TransactionManager を呼び出すアダプタに加えて,WAS の UOWManager を呼び出すアダプタも提供されるため,WAS でも安全に S2Tx を使用することが可能です.
図.2 S2Tx の構造
S2Tx は,標準では S2JTA (Seasar2 による JTA の実装)を使用するように構成されています.そのため,WAS 上で S2Tx を使用する場合は,WAS 用の構成を使用するように設定する必要があります.
設定を変更するには,s2container.dicon という設定ファイルに以下の記述を追加します.
リスト 1. s2containre.dicon
<component
class="org.seasar.framework.container.factory.SimplePathResolver">
<initMethod name="addRealPath">
<arg>"jta.dicon</arg>
<arg>"jta-was6.dicon"</arg>
</initMethod>
</component>
|
s2container.dicon は,Seasar2 自体をカスタマイズするための設定ファイルです.上記の定義により,S2JTA を使う標準の設定の代わりに,UOWManager を使用する WAS6 用の設定が使われるようになります.
宣言的トランザクションの利用
トランザクション境界
アプリケーションで宣言的トランザクションを使用するには,トランザクション境界となるコンポーネントに S2Tx の提供するインターセプタを適用します.
トランザクション境界となるコンポーネントはアプリケーションによって異なりますが,シンプルな Web アプリケーション (図3-①) であれば,プレゼンテーション層のフレームワークから呼び出されるコンポーネント (例えば Page クラスや Action クラス),より大規模でレイヤ化されたアプリケーション (図3-②) であれば,プレゼンテーション層とドメイン層の境界となるコンポーネント (例えば Service クラス)になるでしょう.
図 3. トランザクション境界
TxAttributeCustomizer
トランザクション境界となるコンポーネントにインターセプタを適用する方法はいくつかありますが,現在最も推奨されているのは,SMART deploy で TxAttributeCustomizer を使用する方法です.
SMART deploy とは,Seasar2 バージョン 2.4 から導入されたもので,規約に基づいてコンポーネントの自動登録を行うというものです.その際,Pageクラスや Service クラスなど,コンポーネントの種類毎に様々な特性をカスタマイズすることができます.特性のカスタマイズを行うのが Customizer と呼ばれるコンポーネントで,customizer.dicon という設定ファイルに定義します.
TxAttributeCustomizer は宣言的トランザクションのための Customizer です.TxAttributeCustomizer を使用すると,トランザクション境界となるコンポーネントに S2Tx のインターセプタを適用することができます.
例えば Service クラスをトランザクション境界とする場合は,customizer.dicon に次の設定を記述します.
リスト2 customizer.dicon
<component name="serviceCustomizer"
class="org.seasar.framework.container.customizer.CustomizerChain">
<initMethod name="addCustomizer">
<arg>txAttributeCustomizer</arg>
</initMethod>
</component>
|
この設定により,Object クラスで定義されたものを除いた全ての public なメソッドに,宣言的トランザクションが適用されます.デフォルトでは,トランザクション属性は Required になります.
リスト 3 の XxxService クラスの場合,foo() メソッドにはトランザクション属性が Required の宣言的トランザクションが適用されます.private メソッドの bar() や,Object クラスから継承している toString() 等には宣言的トランザクションは適用されません.
リスト 3. XxxServiceクラス
public class XxxService {
public void foo() {
・・・
}
private void bar() {
・・・
}
}
|
クラスまたはそのメソッドに,EJB3 の TransactionAttribute アノテーションを指定することにより,トランザクション属性を変更することもできます.クラスに TransactionAttribute アノテーションを指定することにより,そのトランザクション属性がデフォルトのトランザクション属性になります.メソッドに TransactionAttribute アノテーションを指定することにより,そのメソッドだけデフォルトと異なるトランザクション属性にすることもできます.
リスト 4 の YyyService クラスの場合,クラスにトランザクション属性 NEVER が指定されているため,foo() メソッドには宣言的トランザクションは適用されません.bar() メソッドは TransactionAttribute アノテーションが指定されているため,トランザクション属性が RequiresNew の宣言的トランザクションが適用されます.
リスト 4. YyyServiceクラス
@TransactionAttribute(TransactionAttributeType.NEVER)
public class XxxService {
public void foo() {
・・・
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void bar() {
・・・
}
}
|
このように,TxAttributeCustomizer を使用すると多くの場合は何も指定する必要がなく,必要ならクラス単位でもメソッド単位でもトランザクション属性をアノテーションで指定することが可能で,柔軟に宣言的トランザクションを利用することができます.
なお,TransactionAttribute は EJB3 で導入されたアノテーションであるため,TxAttributeCustomizer を利用するには動作環境として Java5 が,WAS のバージョンは 6.1 が必要です.アプリケーションの WEB-INF/lib には Seasar2 の配布ファイルに含まれる geronimo-ejb_3.0_spec-1.0.jar を配置する必要があります.Seasar2 が提供する Jar ファイルについては本連載の第 1 回を参照してください.
最後に
Seasar2 の宣言的トランザクションについて,その実現方法から利用方法までを説明しました.
参考文献
著者について  | |  | メインフレームによるオンラインシステムから Java による Web アプリケーションまで,時代に流されて現在に至る.Seasar プロジェクトでは,S2JMS や Kuina-Dao など,分散とトランザクションに関連したプロダクトを中心にコミッタを務めている. |
記事の評価
|