Webサービス・トランザクション

ある実践者のアプローチ

トランザクション対応アプリケーションとWebサービスの構築方法を学びます。Manish Vermaが、Webサービス・トランザクションと通常のトランザクションの違いを解説し、トランザクションに参加するためのWebサービスの作成方法の例を示します。

Manish Verma (mverma@secf.com), Principal Architect, Second Foundation

Manish Vermaは、インドにある、Second Foundationによるソフトウェア開発センターのセンター長です。ソフトウェア開発サイクルのすべての面に関して13年間の経験があり、本質的に異なるシステムを実行するクライアント組織のために、統合戦略を設計してきました。統合に関する彼の実力は、様々なレガシー・システムや.NET、Java技術、最新のミドルウェアまで、広範な技術を深く理解していることからもうかがうことができます。Second Foundationの前には、Quark Inc.やHewlett Packard、Endura Software、The Williams Companyなどの会社でソフトウェア・アーキテクトおよび技術リーダーとして働いてきました。連絡先はmverma@secf.comです。



2005年 9月 30日

トランザクション対応アプリケーションとWebサービスの構築方法を学びます。Manish Vermaが、Webサービス・トランザクションと通常のトランザクションの違いを解説し、トランザクションに参加するためのWebサービスの作成方法の例を示します。

時間のかかるトランザクションの問題

トランザクションは、あらゆる重要なビジネス・アプリケーションの重要なビルディング・ブロックです。トランザクションは、1つ以上のリソースを必要とする作業単位であり、完全に実行されるか、まったく実行されないかのいずれかです。参加するリソースは、トランザクションの間、ロックされます。参加リソースすべての準備が整っているかどうかによって、リソースに加えられた変更がコミットまたはロールバックされ、ロックが解除されます。

トランザクションの概念をさらに詳しく説明するために、eコマース・サイトで書籍を買うシナリオを考えてみましょう。このシナリオでの主要タスクは、次の2つです。

  1. 本を注文する。
  2. クレジットカードに請求される。

これらのタスクは両方とも行われるか、まったく行われないかのいずれかでなければなりません。本を注文していないのにクレジットカードに請求されるという状況は避けなければなりません。逆に、小売店にとっては、本の注文を処理したのにクレジットカードから拒否されるという状況を避けなければなりません。正しいトランザクションとは、望ましくない状況が発生しないトランザクションです。両方のアクションが正常に行われるか、どちらのアクションも行われないかのいずれかです。

Webサービスはビジネス・アプリケーションとサードパーティの統合にとって、ますます重要な付加機能となりつつあります。複数のWebサービスにアクセスする複雑なビジネス・プロセスには、さまざまなWebサービスを結び付ける信頼できるメカニズムが必要です。これによって、ビジネス・プロセスの一部分が他の部分と一致しないということがないようにします。

よく用いられる旅行代理店の例から始めましょう。ある顧客が、オンライン旅行代理店で旅行プランを作成しようとしています。このために、オンライン旅行アプリケーションは次の3つのWebサービスを呼び出します。

  • 航空券の予約
  • ホテルの予約
  • タクシーの予約

ACID特性

ACID特性は、次のもので構成されます。

  • Atomicity(原子性) -- トランザクションに参加するすべてのプロセス(ここから「パーティシパント」(参加者)と呼びます)が確定されるかキャンセルされなければならない。
  • Consistency(一貫性) -- 一貫性のある結果が得られる。
  • Isolation(分離性 -- すべてのパーティシパントが確定されるかキャンセルされるまで、効果は目に見えない。各パーティシパントの中間状態は、外からは見えない。
  • Durability(持続性) -- トランザクションの効果は保管される。

この3つのサービスは、3つの異なるベンダーが提供しています。この3つのうちの1つのサービスが失敗した場合、顧客はトランザクションを進めようとは思いません(3つのサービスのすべてが成功するか、3つとも成功しないかのいずれかでなければなりません)。開発者がこれを保証するための唯一の方法は、この3つのプロセスのすべてを単一のトランザクションに含めることです。

ここまではOKです。これで、トランザクションのニーズが確立されました。次に、上記の例で必要なトランザクションと通常のトランザクションがどう違うのかを説明します。「通常のトランザクション」とは、ACID特性に一致するトランザクションです。

これらのWebサービスをACIDベースの従来のトランザクションに結び付けた場合、次のようなシナリオになります。

  • Webサービスによって使用されるリソースは、すべての参加サービスが実行されない限り、無限にロックされたままになります。
  • 中央の1つのトランザクション・マネージャがすべてのサービスを制御して、アクションを調整します。結果として、サービスはリソースの制御を失います。

DoS攻撃

DoS攻撃は、ユーザーによるサービスへの正当なアクセスを妨げることを目的としています。たとえば、ACIDベースのトランザクションが各種のWebサービスの機能を調整するとき、不当なプロセスが各種のWebサービスに関わるトランザクションを開始すると、各サービスはタスクの終了を待ちますが、タスクはいつまでたっても終了しません。結果として、他のプロセスはこれらのWebサービスを使用できません。

このようなシナリオは、WebサービスをDoS攻撃にさらすことになります。参加組織の重要なリソースが使用不能になり、経済的および財務的に重大な損失をもたらす恐れがあります。従来のトランザクションの欠点を克服するために、開発者はWebサービスの世界でトランザクションを管理する新しい方法を生み出しました。このソリューションでは、リソースはロックされず、コーディネーターと相殺タスクが外部マネージャに取って代わります。これをもう少し詳しく説明しましょう。


ソリューション案:相殺ベースのトランザクション

相殺ベースのトランザクションというソリューション案には、次のような顕著な特長があります。

  • リソースをロックせずに、アプリケーション間のデータの一貫性を管理できる。
  • 中央のトランザクション・マネージャに完全な権限を与えずに、さまざまなトランザクション・パーティシパントを調整する。
  • パーティシパントの可用性や応答が保証されないシナリオで有効。

上記の特長は、Webサービス調整/Webサービス・トランザクション(Web Services-Coordination/Web Services-Transaction:WS-C/T)仕様に基づくソリューションで使用可能です。IBM、Microsoft、およびBEAが共同でこれらの仕様を開発しました。以下のセクションでは、これらの仕様を説明した後、トランザクション対応Webサービスを作成するための手順を示します。


WS-C/Tの概要

このソリューションには、Webサービス調整(WS-C)Webサービス・トランザクション(WS-T)という2つの部分があります。

WS-Cは、必要な基本的トランザクション・インフラストラクチャー・サポートのすべてを規定しています。これには、次のものが含まれます。

  • 特定の調整プロトコルのコーディネーターの作成:コーディネーターの責任は、パーティシパント間でメッセージをやり取りすることです。調整プロトコルは、パーティシパントとコーディネーターが交換するメッセージのタイプと順序、特に状態遷移を定義します。
  • コーディネーターへのパーティシパントの登録:パーティシパントはメッセージを受信するために、コーディネーターに登録します。
  • コンテキストの伝播:コーディネーターは、トランザクション関連のコンテキスト情報をパーティシパント間で受け渡す責任を負います。

WS-Tは、2つのトランザクション・モデルを定義しています。

  • アトミック・トランザクション(AT):ATは、ACID特性を持つ従来のトランザクションと同様です。このモデルは、短時間のトランザクションをサポートします。(「時間のかかるトランザクションの問題」のeコマース・サイトで本を買う例を参照してください。)
  • ビジネス・アクティビティー(BA):ここで最も関連が深いのは、BAトランザクション・モデルです。このモデルは、特に時間のかかるインタラクションを目的としています。パーティシパントはリソースをロックせずにトランザクションに参加することができます。このモデルは、トランザクションの結果がパーティシパントが求めているアクションのタイプと異なる場合に、パーティシパントに適切なアクションをとるように知らせるメカニズムを備えています。(「時間のかかるトランザクションの問題」セクションの旅行プランの例を参照。この例は、この後でも使用します。)

次のセクションでは、トランザクションWebサービスとそれらにアクセスするクライアント・アプリケーションを作成する方法を紹介します。


前線で: トランザクション対応Webサービスの作成

Arjuna XML Transaction Service

Arjuna XML Transaction Serviceは、分散コンピューティング環境でアプリケーションの処理をサポートするミドルウェア・ソリューションです。このソフトウェアを使用すると、ビジネス・プロセスの正確さと完全性を確保できます。WS-AtomicTransactionおよびWS-BusinessActivity仕様をサポートしています。

まず、このプロセスに必要なソフトウェアのリストを示します。

  • Arjuna XML Transaction Service 1.0.(評価版)
  • JBoss 3.2.5
  • Ant 1.6.2

まず、Arjunaソフトウェアに付属の説明書に従って、JBossアプリケーション・サーバーにArjunaを導入します。デモ・アプリケーションを実行して、正常に導入されたことを確認することもできます。

トランザクションWebサービスの作成例を示すために、以下のステップについて説明します。

  1. Arjuna XML Transaction Serviceを使用して、2つのWebサービスを作成します。
  2. トランザクションでこれらのWebサービスの両方を呼び出すクライアント・アプリケーションを作成します。
  3. JBossアプリケーション・サーバーにWebサービスとクライアント・アプリケーションを導入します。クライアント・アプリケーションにアクセスして、2つのWebサービスのトランザクション動作を確認します。

ステップ1. Arjuna XML Transaction Serviceを使用して、2つのWebサービスを作成する

Arjuna XML Transaction Serviceで作成するWebサービスは、次の2つの部分に分かれています。

  1. トランザクション対応サービスは、ビジネス・ロジックを扱います。
  2. パーティシパントは、トランザクション・プロトコルを扱います。

ここで作成するWebサービスは非常に単純です。ビジネス・ロジックは、JBossコンソールにメッセージを表示するだけです。

リスト1と2に、Webサービスの1つのサービスのコードとパーティシパントのコードをそれぞれ示します。

リスト1. トランザクション対応サービス
public class PersistDataOne {
  public boolean writeToFileOne(boolean passFail) {

    PersistDataOneMgr dataManager = 
                    PersistDataOneMgr.getSingletonInstance();
    BusinessActivityManager activityManager = 
    BusinessActivityManagerFactory.businessActivityManager();

    // get the transaction context of this thread:
    String transactionId = null;
    try {
      transactionId = activityManager.currentTransaction().toString();
    } catch (com.arjuna.wst.SystemException e1) {
      e1.printStackTrace();
    }
    System.out.println("PersistDataOne transaction id ="
    + transactionId);

    // invoke the back-end business logic:
    dataManager.writeToFileOne(transactionId, passFail);
    PersistDataOneParticipant persistDataOneParticipant =
    new PersistDataOneParticipant(
    transactionId, 
    passFail);
      // enlist the Participant for this service:
      BAParticipantManager participantManager = null;
      try {
            participantManager =
              activityManager.
                enlistForBusinessAgreementWithParticipantCompletion
                  (persistDataOneParticipant,
                    new Uid().toString());
      } catch (Exception e) {
            System.err
              .println("writetoFileOne: Participant enlistment failed");
            e.printStackTrace(System.err);
            return false;
      }
      try {
            participantManager.completed();
      } catch (Exception e2) {
            e2.printStackTrace();
      }
    return passFail;
  }
}

リスト1では、サービスはさらに、PersistDataOneMgrという名前の別のクラスからビジネス・ロジックを呼び出します。このクラスは、付属のソース・バンドルに含まれています。

サービス・クラスをよく見てください。3つの重要なことが行われています。

  • BusinessActivityManagerがインスタンス化されます。これはトランザクション・コーディネーターであり、これによってパーティシパントの登録が可能になります。
  • ビジネス・メソッドwriteToFileOneがサービス・クラスPersistDataOneMgrに対して呼び出されます。
  • サービスPersistDataOneMgrの対応するパーティシパントPersistDataOneParticipantがトランザクション・コーディネーターに登録されます。これは、トランザクション失敗の場合にタスクを相殺するために使用されます。

リスト2はパーティシパントのコードであり、トランザクション・プロトコルを管理するライフサイクル・メソッドのすべてを実装します。リスト2は、トランザクション・プロトコルのメソッドBusinessAgreementWithParticipantCompletionParticipantを実装します。(トランザクション・プロトコルの詳細については、「ビジネス活動 ? トランザクション・プロトコル」を参照してください。)

ライフサイクル・メソッドの1つは、compensateです。このメソッドは、トランザクションが失敗したときにトランザクション・コーディネーターによって呼び出されます。実際には成功したサービスのパーティシパントに対して呼び出されます。トランザクション全体としては失敗したので、成功したパーティシパントを元の状態に戻すのが目的です。成功したパーティシパントの作業を元に戻すのは、アプリケーション固有です。(さまざまなプロトコルの詳細については、「ビジネス活動 ? トランザクション・プロトコル」を参照してください。)

リスト2. パーティシパント
public class PersistDataOneParticipant
    implements
      BusinessAgreementWithParticipantCompletionParticipant {
  public PersistDataOneParticipant(String txID, boolean passFail) {
    dataManager = PersistDataOneMgr.getSingletonInstance();
    TransactionID = txID;
    PASS_FAIL = passFail;
  }

  public void close() throws WrongStateException, SystemException {
    System.out.println("PersistDataOneParticipant.close");
  }

  public void cancel() throws WrongStateException, SystemException {
    System.out.println("PersistDataOneParticipant.cancel");
  }

  public void compensate() throws WrongStateException, SystemException{
    System.out.println("PersistDataOneParticipant.compensate");
  }
  public String status() {
    return Status.STATUS_ACTIVE;
  }
  public void unknown() throws SystemException {
  }
  public void error() throws SystemException {
  }

  private static String TransactionID;
  private static boolean PASS_FAIL;
  private static PersistDataOneMgr dataManager;
}

ステップ2. トランザクションでこれらのWebサービスの両方を呼び出すクライアント・アプリケーションを作成する

ビジネス活動 ? トランザクション・プロトコル

パーティシパントは、ビジネス活動トランザクションに関する2つのトランザクション・プロトコルに準拠します。

  • BusinessAgreementWithParticipantCompletionParticipant
    --このプロトコルでは、パーティシパントはトランザクションの終了を一方的に選ぶことができます。ただし、パーティシパントがトランザクションを続行したい場合は、行った作業を相殺できなければなりません。このような場合、パーティシパントはコーディネーターにCompleteメッセージを送信して、Closeメッセージ(正常完了を示す)またはCompensateメッセージ(トランザクションが失敗したことを示す)のいずれかを待ちます。
  • BusinessAgreementWithCoordinatorCompletion
    --このプロトコルは、BusinessAgreementWithParticipantCompletionParticipantと同様ですが、パーティシパントが自由にトランザクションを終了できない点が違います。パーティシパントはコーディネーターからCompleteメッセージを受信しなければ、さらにアクションを取ることができません。

このデモンストレーションを単純にするために、2番目のWebサービスも基本的には最初のものと同じにします。メソッドの名前と表示するメッセージが違うだけです。2番目のサービスについては、コード・リストを省略しました。このアプリケーションのサンプル・コード全体は、ダウンロード・ファイルx-transws_wstransaction.zipに含まれています。

クライアント・アプリケーションを作成するときには、以下の2つのことを実行する必要があります。

  • トランザクションの境界を定めます。一般的には、開始、コミット、またはロールバックを使用します。
  • トランザクションの境界内でWebサービス・ビジネス・ロジックを呼び出します。

最初の項目は、Arjuna XML TransactionクライアントAPIが処理します。このAPIは、トランザクションの境界を定義するメカニズムを備えています。クラスUserBusinessActivityのbeginメソッドは、トランザクションの開始を定義するために使用されます。同じクラスのcloseメソッドは、トランザクションの完了を定義します。同じクラスのcancelメソッドは、トランザクションのキャンセルを知らせます。

Webサービス・ビジネス・ロジックの呼び出しに関して、アプリケーションは任意のメカニズムを採用して、トランザクションの境界内からWebサービスを呼び出すことができます。すなわち、Webサービスに話しかけるには、任意のベンダーが提供しているWebサービス・クライアント・サイドAPIを使用することができます。ただし、クライアント・アプリケーションがWebサービスに送信するメッセージに、トランザクション・コンテキストが埋め込まれていなければなりません。また、クライアント・アプリケーションは応答メッセージからトランザクション・コンテキストを抽出できなければなりません。

サンプル・アプリケーションは、クライアント・アプリケーションのメッセージ内のトランザクション・コンテキストの操作に関しては何もせず、今のところは気にする必要はありません。その理由は、Arjuna XML Transaction Serviceには、クライアント・ライブラリーがApache AXISの場合、クライアント・メッセージからのトランザクション・コンテキストの挿入と抽出を処理するフィルターが含まれているからです。

Arjuna XML Transaction APIのバージョン1.0の制約の1つは、クライアントが、サーブレットをホストできるコンテナに入っていなければならないことです。

ここからが肝心なところです。ApacheのWSDL2Javaユーティリティーを使用して、Webサービスのクライアント・サイド・スタブを作成します。このユーティリティーを使用するには、2つのWebサービスのWSDLが必要です。このWSDLは、WebサービスをJBossに導入することによって入手できます。

Webサービスのクライアント・サイド・スタブができたら、リスト3に示されているように、クライアント・アプリケーションを組み立てます。

メソッドrunBusinessActivityで、トランザクションの境界を定義するために、Arjuna XML TransactionクライアントAPIのクラスUserBusinessActivityが使用されていることに注目してください。これらの境界内で、2つのWebサービスのそれぞれについて1つのメソッドpersistOne.writeToFileOne(onePassFail)およびpersistTwo.writeToFileTwo(twoPassFail)が呼び出されます

クライアント・アプリケーションは、まだ終わりではありません。Webサービスのトランザクション動作を見るためには、2つのシナリオを作成する必要があります。

  1. Webサービスは両方とも、ビジネス・ロジックを正常に完了します。
  2. 2番目のWebサービスは失敗し、最初のWebサービスが行った作業を実際に相殺したかどうかを確認できます。

これらのシナリオを作成するには、クライアント・アプリケーションPersistDataClientの2つのパラメーターの値を変更するだけです。

最初のシナリオについては、変数onePassFailとtwoPassFailの両方をtrueに設定する必要があります。ソリューション全体を導入して、クライアント・アプリケーションを実行します。トランザクションが正常に完了したことがわかります。これは、JBossコンソールのログ・メッセージで確認できます。

2番目のシナリオを作成するには、変数onePassFailをtrueに、twoPassFailをfalseに設定します。このようにすると、最初のWebサービスは正常に実行されますが、2番目のWebサービスは失敗します。次のセクションでの説明に従って、アプリケーションを導入し、クライアントを実行します。最初のWebサービスが正常に完了し、2番目のWebサービスが失敗し、最初のWebサービスの相殺メソッドが呼び出されることに注目してください。

ステップ3. Webサービスを導入し、クライアント・アプリケーションにアクセスする

ここで、Webサービスとクライアント・アプリケーションをJBossアプリケーション・サーバーに導入して、クライアント・アプリケーションにアクセスし、2つのWebサービスのトランザクション動作を見る必要があります。

アプリケーションの実験を容易にするために、アプリケーションをビルドして、JBossサーバーに導入するAntスクリプトを作成しました。ビルド・ファイルは、ダウンロード・パッケージx-transws_wstransaction.zipに含まれています。ただし、ビルド・ファイルのパス設定をインストール環境に合わせて変更する必要があります。


実験のアイデア

次のような実験をして、この記事のデモをさらに発展させ、理解を深めてください。

  • ステップ3で述べたパラメーターをいろいろ変えてみて、トランザクションの動作の変化を見ます。
  • さらに複雑なビジネス・ロジックを含むように、サンプル・アプリケーションを拡張します。
  • JBossの複数のインスタンスを導入して、異なるJBossインスタンスに複数のWebサービスを導入し、それらを1つのトランザクションにまとめ上げます。

まとめ

多くの開発者はACIDベースのトランザクションに安心感を抱いてきましたが、ビジネス・ソフトウェアが複雑になるにつれて、このようなトランザクションではすべてのシナリオに対応できなくなってきました。したがって、次のようなシナリオでは、別の種類のトランザクションが必要になるかもしれません。

  • トランザクションに時間がかかる。
  • トランザクション・パーティシパントが単一の権限の管理下にない。
  • トランザクションの結果が個々のパーティシパントの結果と異なる場合がある。

この記事では、代わりのトランザクション・タイプとして、相殺ベースのトランザクションを試してみました。この記事で紹介したデモ・アプリケーションを試した皆さんは、現在と将来のビジネス・アプリケーションで相殺ベースのトランザクションを使い始める準備ができたことになります。


ダウンロード

内容ファイル名サイズ
Web services transactions source codex-transws_wstransaction.zip20KB

参考文献

学ぶために

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

  • この記事で使用しているソースコードをダウンロードしてください。
  • この記事で使用しているArjuna XML transaction middlewareを入手してください。
  • JBossソフトウェアと、その関連情報を入手してください。
  • Antソフトウェアと、その関連情報を入手してください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML, SOA and web services
ArticleID=242734
ArticleTitle=Webサービス・トランザクション
publish-date=09302005