IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Open source | Java technology  >

Apache Geronimo EJB トランザクションのオプションを比較検討する、第 1 回: コンテナー管理トランザクション

Geronimo と OpenEJB によって実現できることを学ぶ

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

原文はこちら

原文はこちら


レベル: 初級

Jonathan Sagorin (jonathan@javoncall.com), Freelance Software Developer

2006年 7月 25日

全 3 回のこのシリーズで、Apache Geronimo での EJB (Enterprise Java™Beans)コンテナー管理トランザクションと Bean 管理トランザクションの両方について学んでください。第1 回では、この 2 つのタイプのトランザクションの違い、そしてコンテナー管理トランザクションでは、どのようにしてトランザクション・ロジックと管理の複雑さをなくし、エンタープライズBean のビジネス・ロジックに専念できるようにしているかがわかります。また、コンテナー管理トランザクションをGeronimo アプリケーション・サーバーに実装する方法、さらに Geronimo、OpenEJB、XDocletを使って、やっかいな EJB コーディングから逃れる方法についても学びます。

はじめに

OpenEJB は、Apache Geronimo に選ばれた EJB コンテナー実装です。EJB 3.0も現在使用可能ですが、Geronimo が Java 1.5 認証を受けるバージョン 2.0 まではサポートされません。

全 3 回で構成されたこのシリーズでは、Geronimo と OpenEJB によって実現できる内容、そしてEJB 2.1 で今すぐ実装でき、EJB 3.0 にも適用される EJB トランザクションのコンセプトについて説明します。

EJB フレームワークには、トランザクション API プログラミングに四苦八苦することなくトランザクションを使うことができるという利点があります。EJBトランザクションを実装する際には、次の 2 つの選択肢があります。

  • EJB コンテナーに、やっかいなすべてのトランザクション作業を行うように指示する(コンテナー管理トランザクション)
  • エンタープライズ Bean に、トランザクション作業の一部を行わせる (Bean 管理トランザクション)

シリーズ第 1 回では、まずトランザクションの概要を紹介し、EJB 2.1 に説明されているEJB コンテナー管理トランザクションについて検討します。最後に、いくつかのコード・スニペットによりn、コンテナー管理トランザクションをGeronimo アプリケーション・サーバーに実装する方法を示します。

第 2 回では、EJB 2.1 での Bean 管理トランザクションの概要を紹介し、サンプル・コードの実装例をいくつか記載します。

第 3 回では、2 つのオプションを同時に取り上げ、コンテナー管理トランザクションとBean 管理トランザクション両方に関する特徴的な機能および追加機能について説明します。

トランザクションの概要

そもそも、トランザクションとは何でしょうか? なぜトランザクションがそんなに重要なのでしょうか?その点について、極端に単純化した銀行取引の例、当座預金から普通預金に 100ドルを送金するという場合を検討してみましょう。よく調べてみると、これには次の2 つの操作が関わっています。

  • 銀行によって、当座預金から 100 ドルが差し引かれる。
  • その 100 ドルが、銀行によって普通口座に追加される。

当座預金の残高が 100 ドル減ったのに、銀行の落ち度で普通預金の残高が 100ドル増えていなかったとしたら、腹が立ちませんか? 個人的に私は、この 2 つの操作を1 つの操作として考えます。つまり、普通預金に 100 ドルが加算されることがなければ、当座預金から100 ドルが差し引かれることも決してないという考え方です。

アプリケーションでも同様に、このようなオール・オア・ナッシング方式を使用するビジネス事例があります。一部の大規模な操作は、1つ以上の小さなステップで構成されています。操作が完了するためには、その操作に含まれるすべてのステップが完了する必要があります。そうでなければ、ステップは1 つも完了しません。この動作は、「原子性」として知られています。

原子性は、トランザクションが保証しなければならない 4 つの特性 (つまりプロパティー)のうちの 1 つです。他の 3 つのプロパティーは、次のとおりです。

  • 一貫性
  • 独立性
  • 耐久性

この 4 つのプロパティーをまとめて、ACID プロパティーと呼びます。

ACID プロパティー

トランザクションには、以下のよく知られた ACID プロパティーがあります。

  • トランザクションの原子性: すべての操作は単一の作業単位としてみなされます。これは、前述のオール・オア・ナッシング方式です。
  • トランザクションの一貫性: トランザクションは実行後に、システムを一貫した(正しい) 状態に維持します。この正しい状態を定義するものは、システムによって異なります。前述の例に従うと、銀行は、預金引き出しの後に預金者の当座預金残高が黒字に維持されることを要件としています。
  • トランザクションの独立性: 同じリソースで実行する複数のトランザクションは互いに独立して動作します。これは、データのロック同期によって実現します。
  • トランザクションの耐久性: リソースに対する更新は、ハードウェア障害やネットワーク障害などのシステム障害に持ちこたえなければなりません。分散システムでは、ネットワーク障害やデータベースの破壊が発生した場合、リカバリー・プロセスが必要となります。

トランザクション・モデル

有名なトランザクション・モデルには、フラット・トランザクション・モデルとネスト・トランザクション・モデルの2 つがあります。EJB ではフラット・トランザクション・モデルをサポートします。

フラット・トランザクションとは、単一の作業単位として実行される一連の操作のことです。この作業単位による結果は2 つだけで、成功または失敗のいずれかです。トランザクションに含まれるすべてのステップが正常に完了すると、トランザクションがコミットされ、操作によって行われたすべての永続データ変更が恒久的なものになります。トランザクションに含まれるいずれかのステップが失敗すると、トランザクションがロールバックし、トランザクションのステップによるデータへの影響が取り消されます。

ネスト・トランザクションでは、トランザクション (または作業単位) を他のトランザクションのなかにネストできます。他のトランザクションにネストされたトランザクションでは、親トランザクションに影響することなくロールバックできます。失敗したネスト・トランザクションは再試行を続けることが可能ですが、繰り返し失敗すると、親トランザクションがロールバックする場合があります。




上に戻る


EJB トランザクション

EJB は、コンポーネント開発用のフレームワークです。EJB コンテナー内で実行するEJB を開発してください。そうすると、何よりもEJB コンテナーのトランザクション管理機能を利用することができます。Geronimoがトランザクション管理のために使用する EJB コンテナーは、OpenEJB です。

EJB アーキテクチャーは、分散トランザクションをサポートします。分散トランザクションが必要となるようなシナリオの例には、次のものがあります。

  • 単一トランザクションで複数のデータベースを更新するアプリケーション
  • 単一トランザクションで、JMS (Java Message Service) 宛先との間でメッセージの送受信を行い、1つ以上のデータベースを更新するアプリケーション
  • 複数の EJB サーバーを介して、単一トランザクションで複数のデータベースを更新するアプリケーション
  • トランザクション境界を明示的に区分してから複数の EJB サーバー上の複数のデータベースを更新するJava クライアント

トランザクション境界

EJB トランザクションを実装する際には、トランザクション境界を区分することになります。つまり、トランザクションを開始する者、トランザクションをコミットまたはアボートする者、そしてトランザクションを使用する条件です。これは、トランザクション管理を行うEJB コンテナーとサーバー・プロバイダー、そして下位トランザクション通信プロトコルに依存します。

区分オプションには、次の 2 つがあります。

  • 宣言型オプション。EJB コンテナーにトランザクションの実装をデリゲートできます。(このオプションについては、この記事の残りの部分で取り上げます。)
  • プログラム型オプション。エンタープライズ Bean が自身のコードにコミットまたはアボート情報を組み込みます。(このオプションについては、シリーズ第2 回で説明します。)

宣言型トランザクション区分では、アプリケーション開発者が EJB デプロイメント記述子に宣言した命令に基づき、EJBコンテナーがエンタープライズ Bean のメソッドにおけるトランザクション境界を適用します。これは、コンテナー管理トランザクションと呼ばれます。

プログラム型区分のトランザクションを実装する場合は、アプリケーション開発者がトランザクション・ロジックおよび境界をエンタープライズBean コードにプログラムします。これは、Bean 管理トランザクションと呼ばれます。

どちらのトランザクションを使うべきか

コンテナー管理トランザクションのほうが簡単で、トランザクション・ロジックをコードに実装する必要もありません。エンタープライズBean メソッドをトランザクション内で実行する必要があるか、あるいはその必要がまったくないかのどちらかです。また、トランザクションは常に開始して終了するため、Beanを呼び出す Java クライアントがエンタープライズ Bean を悪用することも不可能です。

一方、トランザクション境界を完全に制御したい場合は、Bean 管理トランザクションを使用してください。この方法を使用すれば、コード内のどこでコミットまたはロールバック・ロジックを発生させるかを直接制御できます。

セッション Bean とメッセージ駆動型 Bean (MDB) は、Bean 管理トランザクションまたはコンテナー管理トランザクションを使用できますが、エンティティーBean では常にコンテナー管理トランザクションを使用する必要があります。エンティティーBean が Bean 管理パーシスタンスを使用することはできません。




上に戻る


コンテナー管理トランザクション

トランザクション区分による境界は、命令またはトランザクション属性によって提供されます。トランザクション属性は、エンタープライズBean のトランザクションへの参加方法を記述します。Bean の数にかかわらず、Beanごとに異なるトランザクション属性を指定できます。属性は、Bean 全体あるいはBean の個々のメソッドに対して指定できます。ただし、個々のメソッドの属性がBean 全体の属性よりも優先されます。




上に戻る


セッション Bean とエンティティー Bean のトランザクション属性

セッション Bean とエンティティー Bean に使用できる属性値は、次のとおりです。

  • Required -- トランザクション内で常に Bean を実行します。クライアントがすでにトランザクションを開始している場合、Beanはそのトランザクションに参加します。クライアントがトランザクションを開始していない場合は、EJBコンテナーが新しいトランザクションを開始します。この属性は、トランザクション内でBean を常に実行したい場合に使用します。
  • RequiresNew -- Bean が常に新しいトランザクションを開始します。クライアントがすでにトランザクションを開始している場合、そのトランザクションは新しいトランザクションがコミットまたはアボートするまで中断されます。新しいトランザクションが完了すると、既存のトランザクションが再開します。この属性は、Beanを単一の作業単位として実行し、ACID プロパティーをすべて提示したい場合に使用します。
  • Supports -- クライアントがすでにトランザクションを開始している場合、Bean がそのトランザクションに参加します。ただし、トランザクションが存在しない場合は、EJBコンテナーは新しいトランザクションを開始しません。この属性は、エンタープライズBean でのミッション・クリティカルでない操作に使用します。
  • Mandatory -- Bean が呼び出された場合に、クライアントはトランザクションを開始しなければなりません。新しいトランザクションは作成できません。Beanが呼び出されたときに、すでに開始されているトランザクションがなければ、例外がスローされます。この属性は、Beanが大規模なシステムの一部である場合に使用します。通常、トランザクションを開始するのは、サードパーティーの役目です。この属性はBean がトランザクションに参加することを保証するため、安全なオプションです。
  • NotSupported -- トランザクションに Bean を関与させません。クライアントがすでにトランザクションを開始している場合、その既存のトランザクションは、Beanのメソッドが完了するまで中断されます。メソッドが完了すると、トランザクションが再開されます。クライアントがトランザクションを開始していない場合は、新しいトランザクションは作成されません。この属性は、Beanにその ACID プロパティーも提示させる必要がない場合に使用します。例えば、レポート作成など、システムに重要な操作ではない場合です。
  • Never -- クライアントがトランザクションを開始済みの場合、Bean が例外をスローします。Beanをトランザクションに参加させたくない場合があります。そのような場合には、この属性を使用します。



上に戻る


メッセージ駆動型 Bean のトランザクション属性

メッセージ駆動型 Bean のメッセージ・リスナー・メソッドで使用するトランザクション属性は、次の2 つだけです。

  • NotSupported -- トランザクションに Bean を関与させません。クライアントがすでにトランザクションを開始している場合、その既存のトランザクションは、Beanのメソッドが完了するまで中断されます。メソッドが完了すると、トランザクションが再開されます。クライアントがトランザクションを開始していない場合は、新しいトランザクションは作成されません。
  • Required -- トランザクション内で常に Bean を実行します。クライアントがすでにトランザクションを開始している場合、Beanはそのトランザクションに参加します。クライアントがトランザクションを開始していない場合は、EJBコンテナーが新しいトランザクションを開始します。

ご使用のエンタープライズ Bean メソッドに適切なトランザクション属性を決定したら、次はEJB デプロイメント記述子の構成に取り掛かります。




上に戻る


EJB デプロイメント記述子の構成

それぞれのエンタープライズ Bean について、デプロイメント記述子に次の 2つのトランザクションを構成します。

  • EJB デプロイメント記述子の <transaction-type> 要素を使って、Beanがコンテナー管理トランザクションと Bean 管理トランザクションのどちらを使用するかを指定します。使用できる値は、containerまたは bean です。エンティティー Bean ではコンテナー管理トランザクションを使用しなければならいため、この設定はセッションBean とメッセージ駆動型 Bean にのみ必要です。
  • コンテナー管理トランザクションの場合、オプションでエンタープライズ Beanのメソッドにトランザクション属性を指定します。この属性は、EJB デプロイメント記述子の<container-transaction> に指定します。リスト 1 に、各メソッドの一般形式を示します。

リスト 1. 各メソッドの一般形式
                
<method>
            <ejb-name>EJBNAME</ejb-name>
            <method-name>METHODNAME</method-name>
            <trans-attribute>TRANSATTRIBUTE</trans-attribute>
</method>


TRANSATTRIBUTE に使用できる値は、以下のとおりです。

  • NotSupported
  • Required
  • Supports
  • RequiresNew
  • Mandatory
  • Never

エンタープライズ Bean のすべてのメソッドを対象としたトランザクション属性を指定することもできます。その場合は、<method-name> 属性に * を使用します。

リスト 2 は、コンテナー管理エンタープライズ Bean にトランザクション属性を指定する方法の一例です。この例では、ClaimRecordエンタープライズ Bean が、updateClaimNumber メソッドを除くすべてのメソッドにRequired 属性を割り当てています。updateClaimNumber メソッドには Mandatory属性が割り当てられています。Coverage Bean は、すべてのメソッドに RequiresNew属性を割り当てています。


リスト 2. ejb デプロイメント記述子ファイル内のトランザクション属性
                
<ejb-jar>
...
<assembly-descriptor>
...
<container-transaction>
      <method>
            <ejb-name>ClaimRecord</ejb-name>
            <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
      <method>
             <ejb-name>ClaimRecord</ejb-name>
      <method-name>updateClaimNumber</methodname>
      </method>
     <trans-attribute>Mandatory</trans-attribute>
</container-transaction>
<container-transaction>
        <method>
                <ejb-name>Coverage</ejb-name>
                <method-name>*</method-name>
        </method>
        <trans-attribute>RequiresNew</trans-attribute>
</container-transaction>
...
</assembly-descriptor>
...
</ejb-jar>




上に戻る


Geronimo の構成

EJB デプロイメント記述子にトランザクション属性を指定するための一般形式が理解できたところで、今度は、OpenEJBを使った Geronimo でトランザクション属性を指定する方法を見てみましょう。EJBで Geronimo を開発する場合、XDoclet を使って面倒な多くの必須 EJB プログラミング成果物を生成すると、時間を節約できます。XDocletはこれらの成果物の一部として、EJB デプロイメント記述子を生成します。

標準開発プロセスの一環として、エンタープライズ Bean に JavaDoc スタイルのマークアップ・タグを指定します。エンタープライズBean 内にマークアップ・タグを宣言することによって、XDoclet は ejbjar.xmlを生成します。これには、定義されたトランザクション属性も組み込まれます。つまり、デプロイメント記述子(ejb-jar.xml) を直接編集する必要はありません。

トランザクション属性は、@ejb.transaction マークアップによって XDoclet 内に指定されます。これを使用するには、エンタープライズBean のメソッドの上に宣言します。

XDoclet 構成と ejbjar.xml 生成の例

以下に記載するコード・スニペットはそれぞれ、単純化したセッション Bean とエンティティーBean のサンプル、そして XDoclet によって生成された ejbjar.xml ファイルです。まず、リスト 3 に、SampleSession というステートレス・セッション Bean を示しますトランザクションに関連する部分(太字で表示) に注目してください。


リスト 3. セッション Bean
                
package org.my.package.ejb;
/**
 * Sample session bean. 
 * Declare all my XDoclet tags here
 * ...
 * ... 
 * @ejb.bean name="SampleSession"
 *   type="Stateless"
 *   local-jndi-name="java:comp/env/ejb/SampleSessionLocal"
 *   jndi-name="org.my.package.ejb/SampleSessionLocal/Home"
 *   view-type="both"
 *
 * @ejb.permission unchecked="true"
 *
 * @ejb.interface generate="local,remote"
 *   remote-class="org.my.package.ejb.SampleSession"
 *   local-class=" org.my.package.ejb. SampleSession Local"
 * @ejb.home generate="local, remote"
 *      remote-class="org.my.package.ejb.SampleSession Home"
 *    local-class="org.my.package.SampleSession LocalHome"
 * @ejb.util generate="physical"
 * ...
 * ...
 */
public abstract class SampleSessionBean implements javax.ejb.SessionBean {

   /**
    * Perform a business operation. Add something
    * @param someParam the value
    * @ejb.interface-method view-type="both"
    * @ejb.transaction      type="Required"
    */
   public void doSomething(java.lang.String someParam)) {
        ...
   }

   /*
    * Perform another business operation. Add something
    * @param someParam the value
    * @ejb.interface-method view-type="both"
    * @ejb.transaction      type="RequiresNew"
    */
   public void doSomethingElse(java.lang.String someParam)) {
        ...
   }
   /**
    * @ejb.create-method
    * @ejb.transaction type="Required"
    */
   public void ejbCreate ()
           throws javax.ejb.CreateException
   {
   }

   public void ejbPostCreate ()
           throws javax.ejb.CreateException
   {
   }

   protected javax.ejb.SessionContext _ctx = null;

   public void setSessionContext( javax.ejb.SessionContext      ctx )
   {
        _ctx = ctx;
   }

   protected javax.ejb.SessionContext getSessionContext()
   {
        return _ctx;
   }
}

エンティティー Bean のトランザクション属性を指定する場合も、上記と同じマークアップ@ejb.transaction が使用されます。リスト 4 に、エンティティー Bean の場合のトランザクション指定方法を示します。ここでも同じく、太字で示したマークアップに注目してください。


リスト 4. エンティティー Bean
                
/**
 *
 * @ejb.bean 
 *    type="CMP" 
 *    cmp-version="2.x"
 *    name="ClaimEntry" 
 *    local-jndi-name="org.my.package.ejb/ClaimLocalHome"
 *    view-type="local"
 *    primkey-field="name"
 *    
 *
 * @xx-ejb.data-object
 *    container="true"
 *    setdata="true"
 *    generate="true"
 *    
 * @ejb.value-object
 *
 * @ejb.transaction type="Required"
 * @ejb.permission unchecked="true"
 * @struts.form include-all="true"
 *
 * @web.ejb-local-ref
 *    name="ejb/ClaimLocal"
 *    type="Entity"
 *    home="org.my.package.ejb.ClaimLocalHome"
 *    local="org.my.package.ejb.ClaimLocal"
 *    link="PhoneBookEntry"
 *
 * @ejb.persistence table-name="Claim"
 *
 */
public abstract class ClaimBean 
       implements javax.ejb.EntityBean
{

 * ... EJB entity bean implementation here   
}

ビルド・プロセスで XDoclet が実行されると、ejb-jar.xml が生成されます。リスト 5 に、このファイルのトランザクションに関連する部分を示します。太字で示した<transaction-type> および <trans-attribute> 要素に注目してください。


リスト 5. 生成された ejb-jar.xml のスニペット
                
<ejb-jar >

   <description><![CDATA[No Description.]]></description>
   <display-name>Generated by XDoclet</display-name>

   <enterprise-beans>

      <!-- Session Beans -->
      <session >
         <description><![CDATA[Sample session
 bean.]]></description>

         <ejb-name>SampleSession</ejb-name>

         <home>org.my.package.ejb.SampleSessionHome</home>
         <remote>org.my.package.ejb.SampleSession</remote>
<local-home>org.my.package.ejb.SampleSessionLocalHome
</local-home>
         <local>org.my.package.ejb.SampleSessionLocal</local>
        
 <ejb-class>org.my.package.ejb.SampleSessionSessionSession
</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
      </session>
...

      <!-- Entity Beans -->
      <entity >
         <description><![CDATA[]]></description>
         <ejb-name>Claim</ejb-name>
         <local-home>
 org.my.package.ejb.ClaimLocalHome</local-home>
         <local>org.my.package.ejb.ClaimLocal</local>
         <ejb-class>org.my.package.ejb.ClaimCMP</ejb-class>
         <persistence-type>Container</persistence-type>
         <prim-key-class>java.lang.String</prim-key-class>
         <reentrant>False</reentrant>
         <cmp-version>2.x</cmp-version>
         <abstract-schema-name>Claim</abstract-schema-name>
...
      </entity>
...
   <container-transaction >
      <method >
         <ejb-name>Claim</ejb-name>
          <method-name>*</method-name>
       </method>
       <trans-attribute>Required</trans-attribute>
    </container-transaction>
   <container-transaction >
      <method >
         <ejb-name>SampleSession</ejb-name>
         <method-intf>Local</method-intf>
         <method-name>doSomething</method-name>
         <method-params>
            <method-param>java.lang.String</method-param>
         </method-params>
      </method>
      <trans-attribute>RequiresNew</trans-attribute>
   </container-transaction>
   <container-transaction >
      <method >
         <ejb-name>SampleSession</ejb-name>
         <method-intf>Remote</method-intf>
         <method-name>doSomething</method-name>
         <method-params>
            <method-param>java.lang.String</method-param>
         </method-params>
      </method>
      <trans-attribute>RequiresNew</trans-attribute>
   </container-transaction>
   <container-transaction >
      <method >
         <ejb-name>SampleSession</ejb-name>
         <method-intf>Local</method-intf>
         <method-name>doSomethingElse</method-name>
         <method-params>
            <method-param>java.lang.String</method-param>
         </method-params>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>
   <container-transaction >
      <method >
         <ejb-name>SampleSession</ejb-name>
         <method-intf>Remote</method-intf>
         <method-name>doSomethingElse</method-name>
         <method-params>
            <method-param>java.lang.String</method-param>
         </method-params>
      </method>
      <trans-attribute>Required</trans-attribute>
   </container-transaction>
...

</ejb-jar>

トランザクション同期化

コンテナー管理トランザクションでは、EJB コンテナーによってトランザクション境界が指定されるので、作業が単純になります。ただし、トランザクションのアボート時には、Bean状態のリカバリーを実行しなければならない場合があります。ステートレス・セッションBean の場合は、単純な例外がスローされます。一方、ステートフル・セッションBean は会話型状態 (またはビジネス・プロセス) を表し、これが複数の Beanメソッド呼び出しに発展する可能性があります。

ステートフル・セッション Bean がトランザクション境界のステータス・イベントの通知を受けるようにするには、エンタープライズBean をコーディングして、オプションの javax.ejb.SessionSynchronizationインターフェースを実装します。この場合、以下のメソッドをインターフェースに定義し、実装する必要があります。

  • afterBegin() -- 新規トランザクションが開始されると、ビジネス・メソッドが呼び出される前にセッションBean に通知します。Bean インスタンスは、トランザクションがコミットされる前に、必要になる可能性のあるすべてのデータベース読み出しを行うことができます。これは、トランザクションに必要なデータをキャッシュするときに役立ちます。
  • beforeCompletion() -- ビジネス・メソッドが完了すると、トランザクションがコミットされる前にセッションBean に通知します。キャッシュされたデータがある場合は、そのデータをデータベースに更新できます。Beanはそのセッション・コンテキストで setRollBackOnly() を呼び出すことによって、トランザクションの手動ロールバックを実行することもできます。
  • afterCompletion(boolean committed) -- トランザクションがコミットされた後、セッション Bean に通知します。ブール値committed は、コミットとアボートのどちらが発生したかを示します。true の場合、トランザクションが正常に完了したことを意味します。falseの場合は、トランザクションがアボートされたことを意味します。この時点で、Beanの会話型状態/インスタンス変数がリストア/リセットされます。

使用すべきでないメソッド

EJB コンテナーはトランザクション境界を制御するため、コンテナーによる境界区分に干渉するおそれのあるメソッドを呼び出してはなりません。コンテナー管理トランザクションを実装する場合は、エンタープライズBean メソッドが以下を呼び出さないようにしてください。

  • java.sql.ConnectioncommitsetAutoCommit、および rollback メソッド
  • javax.ejb.EJBContextgetUserTransaction メソッド
  • javax.transaction.UserTransaction のすべてのメソッド

ロールバック

場合によっては、トランザクションを明示的にアボートしたいことがあります。コンテナー管理トランザクションのロールバック方法には、次の2 つがあります。

  • コンテナーにトランザクションを自動的にロールバックさせます。これは、エンタープライズBean のいずれかのメソッドによってランタイム例外がスローされた場合に行われます。
  • EJBContext インターフェースの setRollBackOnly() メソッドを呼び出します。これによって、ロールバックを発生させるタイミングを制御できます。妥当性検査が失敗した場合や、データ保全性に問題がある場合には、トランザクション全体をロールバックして、アプリケーション例外をスローすることをお奨めします。アプリケーション例外によって、コンテナーが自動的に例外をロールバックすることはありません。



上に戻る


まとめ

このシリーズ第 1 回では、トランザクションの概要を説明し、EJB トランザクションのオプションを紹介しました。コンテナー管理トランザクションを使用すると、複雑なトランザクション・ロジックと管理をEJB コンテナーに任せて、エンタープライズ Bean のビジネス・ロジックに専念することが可能になります。

コンテナー管理トランザクションで考慮が必要となるのは、エンタープライズBean のトランザクションへの参加方法だけで、これは EJB デプロイメント記述子での簡単な構成によって指定できます。Geronimoアプリケーション・サーバー、OpenEJB、そして XDoclet を使えば、コンテナー管理トランザクションの設定方法が簡単になり、EJB成果物をコーディングするやっかいなタスクから解放されます。

Bean 管理トランザクションについて学習するシリーズ第 2 回、そして両方のオプションをまとめた第3 回もお見逃しなく。




参考文献

学ぶために

製品や技術を入手するために

議論するために


著者について

Jonathan Sagorin はフリーランスの開発者です。その10年にわたる経歴の大半をコンサルタントとして過ごし、カスタム Java ソリューションを実現してきました。余暇にはソフトボールとアドリブ・プレー (彼のソフトボール・チームの仲間は反論することでしょうが、必ずしもアドリブではありません) を楽しんでいます。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



 


 


不充分・不完全である大変素晴らしい
 


この記事を共有する

del.icio.us del.icio.us newsing newsing FC2ブックマーク FC2ブックマーク
Choix! Choix! ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
MM/memo MM/memo CZブックマーク CZブックマーク livedoorクリップ livedoorクリップ
はてなブックマーク はてなブックマーク Buzzurl(バザール) Buzzurl(バザール)




上に戻る


    日本IBMについて プライバシー お問い合わせ