JBoss EJB 3.0と拡張機能

  アプリケーショントランザクション
はじめに

標準的なJTAのトランザクションはスレッドベースです。トランザクションはスレッドの最後にコミットかロールバックしなければなりません。スレッドの最後にトランザクションはコミットされ、データの変更はデータベースへフラッシュされ、EntityManagerの永続コンテキストは破棄されます。Webアプリケーションにとっては、これはいくつかの問題になります。Webアプリケーションでは各Webリクエストは独自のスレッドで動作しますが、複数のリクエストが論理的にひとつのトランザクションセッションに結び付けられることがあるからです。例としてショッピングカートのアプリケーションを考えましょう。ユーザは商品を選び、クレジットカード情報を入力し、発送先を入力し、最終的な価格を確認し、最後に全体のトランザクションを終了するために、複数のWebページを移動する必要があります。各ページでのサブミットはサーバ上の別々のスレッドで処理されますが、注文がデータベースへコミットされるのは最後のページの後のみであるべきです。これをJTAのトランザクションマネージャで実装するのは困難です。

EJB 3.0では、ステートフルセッションBeanでのマルチスレッドトランザクション (すなわちアプリケーショントランザクション)をサポートするためEntityManagerを「長期生存させる」オプションがあります。長期生存EntityManagerはホストとなるステートフルセッションBeanのインスタンスが破棄される (すなわち永続コンテキストが破棄される)までコミットしません。このトレイルでは、アプリケーショントランザクションの使い方を取り上げます。

サンプルアプリケーション

このトレイルのサンプルアプリケーションは、前のトレイルで見た投資計算プログラムのための「為替変換レート更新」アプリケーションの単純なバリエーションです。新しい為替変換レートをサブミットすると、アプリケーションはエンティティBeanオブジェクトのすべての計算レコードを更新しますが、まだ変更をデータベースへフラッシュしません。そしてアプリケーションは次のページを表示し、これらのレコードのタイムスタンプを更新するかどうかを尋ねます。「はい」を選択すれば、Beanオブジェクトのタイムスタンプ属性も更新され、すべての変更がひとつのバッチ処理でデータベースにフラッシュされます。

拡張EntityManager

アプリケーショントランザクションを使うには、@PersistenceContextインジェクションアノテーションのtype属性にPersistenceContextType.EXTENDEDを指定するだけです。それはコンテナに、このBeanのEntityManagerオブジェクトがスレッドまたはメソッド呼び出しの最後でその永続コンテキスト (すなわちEntityManagerが管理するBean)を維持するよう、伝えます。


@Stateful
public class ApptransCalculator implements Calculator, Serializable {

  @PersistenceContext(
      type=PersistenceContextType.EXTENDED
  )
  protected EntityManager em;
  
  // ... ...
  
}
トランザクションをコミットする

説明したように、EntityManagerはステートフルセッションBeanが破棄されたときのみデータベースを更新します。@Removeをタグ付けしたメソッドを呼べばステートフルセッションBeanを破棄できることを思い出してください。データベースが同期化されることを確実にするため、@Removeメソッド内でEntityManager.flush()メソッドを呼ぶようにもしています。


@Stateful
public class ApptransCalculator implements Calculator, Serializable {

  // ... ...
  
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void updateExchangeRate (double newrate) {
    // ... ...
  }

  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void updateTimestamp () {
    // ... ...
  }
  
  @Remove
  public void checkout() throws Exception {
    em.flush ()
  }

}
ソースコード参照

サーバ

  • Calculator.java: CalculatorBeanセッションBeanのローカルインターフェース
  • ApptransCalculator.java: 拡張したアプリケーショントランザクション対応のステートフルセッションBean

クライアント

  • calculator.jsp: 更新トランザクションの第一段階を実行するクライアントJSP
  • check.jsp: 更新トランザクションの第二段階を実行するクライアントJSP
まとめ

このトレイルでは、ショッピングカートアプリケーションのような複数ページアプリケーションのトランザクションのために、長期生存EntityManagerオブジェクトを使う方法を学びました。次のトレイルでは、管理対象オブジェクトとメソッドのための別タイプのコンテナサービスであるセキュリティサービスについて論じます。