プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle WebLogic Server JAX-WS Webサービスの開発
12c (12.2.1.2.0)
E82857-02
目次へ移動
目次

前
次

15 Webサービス原子性トランザクションの使用

この章では、Java API for XML Web Services (JAX-WS)を使用したWebLogic Webサービスで、Webサービス原子性トランザクションを使用して他の外部トランザクション処理システムとの相互運用性を実現する方法について説明します。

この章の内容は次のとおりです:

Webサービス原子性トランザクションの概要

WebLogic Webサービスでは、次の仕様をサポートすることで、Websphere、Microsoft .NETといった他の外部トランザクション処理システムとの相互運用性を実現しています。

これらの仕様は、一連の参加者の間で分散されたアクティビティを調整するための拡張フレームワークを定義するものです。次の図に示されているコーディネータは中心的なコンポーネントで、トランザクションの状態(調整コンテキスト)を管理し、Webサービスおよびクライアントを参加者として登録することを可能にします。

図15-1 Webサービス原子性トランザクションのフレームワーク

図15-1の説明が続きます
「図15-1 Webサービス原子性トランザクションのフレームワーク」の説明

次の表では、この図に示されているWebサービス原子性トランザクションのコンポーネントについて説明します。

表15-1 Webサービス原子性トランザクションのコンポーネント

コンポーネント 説明

コーディネータ

トランザクションの状態(調整コンテキスト)を管理し、Webサービスおよびクライアントを参加者として登録することを可能にします。

アクティブ化サービス

アプリケーションによるトランザクションのアクティブ化、およびアクティビティの調整コンテキストの作成を可能にします。作成された調整コンテキストは、トランザクション・フローとともに渡されます。

登録サービス

アプリケーションを参加者として登録することを可能にします。

アプリケーション・プロトコルX、Y

サポートされている調整プロトコル(WS-AtomicTransactionなど)。

次の図は、Webサービス原子性トランザクションのコンテキスト内で相互に作用する2つのWebLogic Serverインスタンスを示しています。わかりやすくするために、2つのWebLogic Webサービス・アプリケーションを示しています。

図15-2 WebLogic Server環境内のWebサービス原子性トランザクション

図15-2の説明が続きます
「図15-2 WebLogic Server環境内のWebサービス原子性トランザクション」の説明

次の点に注意してください。

  • ローカルJTAトランザクション・マネージャを使用すると、すべてWebサービス・リクエストのコンテキスト内で、トランザクションを下位トランザクションとしてローカルなJTA環境との間でインポートおよびエクスポートできます。

  • 調整コンテキストの作成と管理は、ローカルJTAトランザクション・マネージャによって行われます。

  • トランザクションの整合性管理とリカバリ処理はすべて、ローカルJTAトランザクション・マネージャによって行われます。

JTAの詳細は、『Oracle WebLogic Server JTAアプリケーションの開発』を参照してください

次に、図15-2に示されているエンドツーエンドのWebサービス原子性トランザクションの相互作用の例について説明します。

  1. アプリケーションAが、サーバーAでJTAトランザクション・マネージャを使用して、コントロールの現行スレッドに対するトランザクションを開始します。

  2. アプリケーションAが、サーバーBのアプリケーションBでWebサービス・メソッドをコールします。

  3. サーバーAがトランザクション情報を更新し、調整コンテキストを含むSOAPヘッダーを作成して、トランザクションおよびローカル・コーディネータを指定します。

  4. サーバーBがアプリケーションBのリクエストを受信して、ヘッダーにトランザクション調整コンテキストが含まれていることを検出し、アプリケーションBがこのトランザクションの参加者としてすでに登録されているかどうかを判断します。すでに登録されていれば、そのトランザクションは再開され、登録されていない場合は、新しいトランザクションが開始されます。

    アプリケーションBがインポート済トランザクションのコンテキスト内で実行されます。アプリケーションの対話に使用されるすべてのトランザクション・リソースは、このインポート済トランザクションに登録されます。

  5. サーバーBが、トランザクション調整コンテキスト内で指定されている登録サービスを使用して、WS-AtomicTransactionトランザクションの参加者として自身を登録します。

  6. サーバーAがトランザクションを再開します。

  7. アプリケーションAが処理を再開し、トランザクションをコミットします。

Webサービスの高度な機能に必要なドメイン・リソースの構成

ドメインの作成または拡張を行う際に、Webサービス原子性トランザクションに加えて、Webサービスのその他の高度な機能を使用する予定の場合は(すぐに使用するのか、将来使用するのかを問わず)、WebLogic Advanced Web Services for JAX-WS拡張テンプレート(wls_webservice_jaxws.jar)を適用すると、Webサービスの高度な機能をサポートするのに必要なリソースを自動的に構成できます。この拡張テンプレートの使用は必須ではありませんが、使用すると必要なリソースの構成が格段に容易になります。あるいは、Oracle WebLogic Server管理コンソールまたはWLSTを使用して、これらの高度な機能に必要なリソースを構成できます。詳細は、「高度なWebサービス機能のためのドメインの構成」を参照してください

注意:

Webサービスのその他の高度な機能をWebサービス原子性トランザクションとともに使用する予定がない場合、この拡張テンプレートを適用する必要はなく、起動時間とメモリー・フットプリントが最小限に抑えられます。

Webサービスに対するWebサービス原子性トランザクションの有効化

Webサービスに対してWebサービス原子性トランザクションを有効にするには:

次の表は、Webサービス原子性トランザクションを有効にする際に設定可能な構成オプションをまとめたものです。

表15-2 Webサービス原子性トランザクションの構成オプション

属性 説明

Version

Webサービスおよびクライアントに対して使用されるWebサービス原子性トランザクション調整コンテキストのバージョン。クライアントの場合、アウトバウンド・メッセージに使用されるバージョンのみを指定します。指定した値は、トランザクション全体で整合性が取れている必要があります。

有効な値は、WSAT10WSAT11WSAT12、およびDEFAULTです。WebサービスのDEFAULT値は、3つのバージョンすべて(インバウンド・リクエストによって駆動される)であり、Webサービス・クライアントのDEFAULT値はWSAT10です。

Flow type

Webサービス原子性トランザクション調整コンテキストがトランザクション・フローとともに渡されるかどうか。有効な値は、表15-3を参照してください。

次の表は、フロー・タイプの有効な値と、Webサービスおよびクライアントでのそれらの意味をまとめたものです。この表では、@TransactionAttributeアノテーションを使用するEJB型のWebサービスに対してWebサービス原子性トランザクションを構成する際の有効な値の組合せも示しています。

表15-3 フロー・タイプの値

Webサービス・クライアント Webサービス EJB @TransactionAttributeの有効な値

NEVER

JTAトランザクションがある場合: トランザクションの調整コンテキストをエクスポートしません。

JTAトランザクションがない場合: トランザクションの調整コンテキストをエクスポートしません。

トランザクション・フローが存在する場合: トランザクションの調整コンテキストをインポートしません。CoordinationContextヘッダーにmustunderstand="true"が含まれている場合は、SOAPフォルトがスローされます。

トランザクション・フローがない場合: トランザクションの調整コンテキストをインポートしません。

NEVERNOT_SUPPORTEDREQUIREDREQUIRES_NEWSUPPORTS

SUPPORTS (デフォルト)

JTAトランザクションがある場合: トランザクションの調整コンテキストをエクスポートします。

JTAトランザクションがない場合: トランザクションの調整コンテキストをエクスポートしません。

トランザクション・フローが存在する場合: トランザクション・コンテキストをインポートします。

トランザクション・フローがない場合: トランザクションの調整コンテキストをインポートしません。

REQUIREDSUPPORTS

MANDATORY

JTAトランザクションがある場合: トランザクションの調整コンテキストをエクスポートします。

JTAトランザクションがない場合: 例外がスローされます。

トランザクション・フローが存在する場合: トランザクション・コンテキストをインポートします。

トランザクション・フローがない場合: サービス側の例外がスローされます。

MANDATORYREQUIREDSUPPORTS

JWSファイルでの@Transactionalアノテーションの使用

Webサービス原子性トランザクションを有効にするには、Webサービス・エンドポイントの実装クラスまたは実装メソッドに@weblogic.wsee.wstx.wsat.Transactionalアノテーションを指定します。

注意:

weblogic.jws.Transactionalもアノテーション付きのクラスまたは操作をトランザクション内で確実に実行するためのものですが、この場合のトランザクションは原子性トランザクションではありませんので、このアノテーションと混同しないでください。

次の点に注意してください。

  • Webサービス・クラス・レベルで@Transactionalアノテーションを指定すると、サービス・エンドポイント・インタフェースで定義された双方向メソッドのすべてに設定が適用されます。フロー・タイプの値はメソッド・レベルでオーバーライドできますが、バージョンはトランザクション全体で一致している必要があります。

  • @Onewayアノテーションも追加されているWebメソッドに対して、@Transactionalアノテーションを明示的に指定することはできません。

  • Webサービス原子性トランザクションは、クライアント側の非同期プログラミング・モデルでは使用できません。

@Transactionalアノテーションを指定する際の形式は次のとおりです。

@Transactional(
     version=Transactional.Version.[WSAT10|WSAT11|WSAT12|DEFAULT],
     value=Transactional.TransactionFowType.[MANDATORY|SUPPORTS|NEVER]
)

バージョンおよびフロー・タイプの構成オプションの詳細は、表15-2を参照してください。

次の項では、@TransactionalアノテーションをWebサービスの実装クラス・レベルと実装メソッド・レベルで使用する例、およびEJB @TransactionAttributeアノテーションとともに使用する例を示します。

例: Webサービス・クラスでの@Transactionalアノテーションの使用

次の例は、@TransactionalアノテーションをWebサービス・クラスに追加する方法を示しています。関連するコードは太字で示されています。例に示すように、アクティブなJTAトランザクションがあります。

注意:

次のコードは、WebLogic Serverサンプル・サーバー付属のWebサービス原子性トランザクションの例から抜粋したものです。詳細は、「Webサービス原子性トランザクションのその他の使用例」を参照してください。

package examples.webservices.jaxws.wsat.simple.service;
. . . 
import weblogic.jws.Policy;
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.Version;
import weblogic.wsee.wstx.wsat.Transactional.TransactionFlowType;
 
/**
 * This JWS file forms the basis of a WebLogic WS-Atomic Transaction Web Service with the 
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
 
@WebService(serviceName = "WsatBankTransferService", targetNamespace = "http://tempuri.org/",
            portName = "WSHttpBindingIService")
@Transactional(value=Transactional.TransactionFlowType.MANDATORY,
               version=weblogic.wsee.wstx.wsat.Transactional.Version.WSAT10)
public class WsatBankTransferService {
 
    public String createAccount(String acctNo, String amount) throws java.lang.Exception{
        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
            try {
                DataSource dataSource = (DataSource)ctx.lookup("examples-demoXA-2");
                String sql = "insert into wsat_acct_remote (acctno, amount) values (" + acctNo +
                           ", " + amount + ")";
                int insCount = dataSource.getConnection().prepareStatement(sql).executeUpdate();
                if (insCount != 1)
            throw new java.lang.Exception("insert fail at remote.");
                return ":acctno=" + acctNo + " amount=" + amount + " creating. ";
            } catch (SQLException e) {
              System.out.println("**** Exception caught *****");
               e.printStackTrace();
               throw new SQLException("SQL Exception during createAccount() at remote.");
        }
        } catch (java.lang.Exception e) {
          System.out.println("**** Exception caught *****");
          e.printStackTrace();
          throw new java.lang.Exception(e);
        }
    }
    public String deleteAccount(String acctNo) throws java.lang.Exception{
      ...
    }
    public String transferMoney(String acctNo, String amount, String direction) throws
       java.lang.Exception{
      ...
    }
    public String listAccount() throws java.lang.Exception{
      ...
    }
}
package jaxws.interop.rsp;
...
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.TransactionalFlowType;
import weblogic.wsee.wstx.wsat.Transactional.Version;
...
@WebService(
     portName = "FlightServiceBindings_Basic", 
     serviceName = "FlightService", 
     targetNamespace = "http://wsinterop.org/samples", 
     wsdlLocation = "/wsdls/FlightService.wsdl", 
     endpointInterface = "jaxws.interop.rsp.IFlightService"
)
@BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
@javax.xml.ws.soap.Addressing
@Transactional(value = Transactional.TransactionFlowType.SUPPORTS, 
   version = Transactional.Version.WSAT12)
public class FlightServiceImpl implements IFlightService {
   ...
}

例: Webサービス・メソッドでの@Transactionalアノテーションの使用

次の例は、@TransactionalアノテーションをWebサービス実装メソッドに追加する方法を示しています。関連するコードは太字で示されています。

package jaxws.interop.rsp;
...
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.TransactionalFlowType;
import weblogic.wsee.wstx.wsat.Transactional.Version;
...
@WebService(
     portName = "FlightServiceBindings_Basic", 
     serviceName = "FlightService", 
     targetNamespace = "http://wsinterop.org/samples", 
     wsdlLocation = "/wsdls/FlightService.wsdl", 
     endpointInterface = "jaxws.interop.rsp.IFlightService"
)
@BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
@javax.xml.ws.soap.Addressing
public class FlightServiceImpl implements IFlightService {
...
    @Transactional(value = Transactional.TransactionFlowType.SUPPORTS, 
                  version = Transactional.Version.WSAT12)
    public FlightReservationResponse reserveFlight(FlightReservationRequest request) {
        //replace with your impl here
        FlightReserverationEnitity entity = new FlightReserverationEnitity();
        entity.setAirlineID(request.getAirlineID());
        entity.setFlightNumber(request.getFlightNumber());
        entity.setFlightType(request.getFlightType());
        boolean successful = saveRequest(entity);
        FlightReservationResponse response = new FlightReservationResponse();
        if (!successful) {
           response.setConfirmationNumber("OF" +  CONF_NUMBER++ + "-" + request.getAirlineID() + 
                   String.valueOf(entity.getId()));
        } else if (request.getFlightNumber() == null ||
                   request.getFlightNumber().trim().endsWith("LAS"))   {
           successful = false;
           response.setConfirmationNumber("OF" + "- No flight available for " +
                   request.getAirlineID());
        } else {
           response.setConfirmationNumber("OF" +  CONF_NUMBER++ + "-" + request.getAirlineID() +
                  String.valueOf(entity.getId()));
        }
        response.setSuccess(successful);
        return response;
    }
package examples.webservices.jaxws.wsat.simple.service;
. . . 
import weblogic.jws.Policy;
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.Version;
import weblogic.wsee.wstx.wsat.Transactional.TransactionFlowType;
 
/**
 * This JWS file forms the basis of a WebLogic WS-Atomic Transaction Web Service with the 
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
 
@WebService(serviceName = "WsatBankTransferService", targetNamespace = "http://tempuri.org/",
            portName = "WSHttpBindingIService")
public class WsatBankTransferService {
 
@Transactional(value=Transactional.TransactionFlowType.MANDATORY,
               version=weblogic.wsee.wstx.wsat.Transactional.Version.WSAT10)
    public String createAccount(String acctNo, String amount) throws java.lang.Exception{
        Context ctx = null;
        UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
            try {
                DataSource dataSource = (DataSource)ctx.lookup("examples-demoXA-2");
                String sql = "insert into wsat_acct_remote (acctno, amount) values (" + acctNo +
                           ", " + amount + ")";
                int insCount = dataSource.getConnection().prepareStatement(sql).executeUpdate();
                if (insCount != 1)
            throw new java.lang.Exception("insert fail at remote.");
                return ":acctno=" + acctNo + " amount=" + amount + " creating. ";
            } catch (SQLException e) {
              System.out.println("**** Exception caught *****");
               e.printStackTrace();
               throw new SQLException("SQL Exception during createAccount() at remote.");
        }
        } catch (java.lang.Exception e) {
          System.out.println("**** Exception caught *****");
          e.printStackTrace();
          throw new java.lang.Exception(e);
        }
    }
    public String deleteAccount(String acctNo) throws java.lang.Exception{
      ...
    }
    public String transferMoney(String acctNo, String amount, String direction) throws
       java.lang.Exception{
      ...
    }
    public String listAccount() throws java.lang.Exception{
      ...
    }
}

例: @TransactionalアノテーションとEJB @TransactionAttributeアノテーションの併用

次の例は、@TransactionalアノテーションとEJB @TransactionAttributeアノテーションを併用する方法を示しています。この場合、フロー・タイプの値に互換性があることが必要です(表15-3を参照)。関連するコードは太字で示されています。

package examples.webservices.jaxws.wsat.simple.service;
. . . 
import weblogic.jws.Policy;
import javax.transaction.UserTransaction;
. . .
import javax.jws.WebService;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.Version;
import weblogic.wsee.wstx.wsat.Transactional.TransactionFlowType;
 
/**
 * This JWS file forms the basis of a WebLogic WS-Atomic Transaction Web Service with the 
 * operations: createAccount, deleteAccount, transferMonet, listAccount
 *
 */
 
@WebService(serviceName = "WsatBankTransferService", targetNamespace = "http://tempuri.org/",
            portName = "WSHttpBindingIService")
@Transactional(value=Transactional.TransactionFlowType.MANDATORY,
               version=weblogic.wsee.wstx.wsat.Transactional.Version.WSAT10)
@TransactionAttribute(TransactionAttributeType.REQUIRED
public class WsatBankTransferService {
. . .
}

WSDLから開始するWebサービス原子性トランザクションの有効化

Webサービス原子性トランザクションは、有効にすると、ポリシー・アサーションを使用してWSDLファイルで通知されます。

表15-4は、Webサービス原子性トランザクションのフロー・タイプとEJBトランザクション属性との一般的な組合せに対応するWS-AtomicTransaction 1.2ポリシー・アサーションをまとめたものです。他のすべての組合せではビルド時にエラーが発生します。

表15-4 Webサービス原子性トランザクションのポリシー・アサーションの値(WS-AtomicTransaction 1.2)

原子性トランザクションのフロー・タイプ EJB @TransactionAttribute WS-AtomicTransaction 1.2ポリシー・アサーション

MANDATORY

MANDATORYREQUIREDSUPPORTS

<wsat:ATAssertion/>

SUPPORTS

REQUIREDSUPPORTS

<wsat:ATAssertion wsp:Optional="true"/>

NEVER

REQUIREDREQUIRES_NEWNEVERSUPPORTSNOT_SUPPORTED

ポリシーの通知なし

wsdlc Antタスクを使用すると、既存のWSDLファイルから一連のアーティファクトを生成し、それをまとめて、WSDLファイルに記述されたWebサービスの部分的なJava実装を提供することができます。WSDLファイルで通知されたWS-AtomicTransactionポリシー・アサーションは、wsdlcによって生成された新しいWebサービスのWSDLファイルに送られ、その中に組み込まれます。

wsdlc Antタスクでは、生成されたJWSインタフェースの部分的な(途中まで作成済の)実装を含むJWSファイルが生成されます。このファイルを変更してビジネス・コードを組み込む必要があります。ビジネス・ロジックを含むJWSファイルをコーディングしたら、jwsc Antタスクを実行して、Webサービスの完全なJava実装を生成します。wsdlc Antタスクによって生成されたJARファイル(JWSインタフェース・ファイルとデータ・バインディング・アーティファクトを含む)を指定するには、jwsccompiledWsdl属性を使用します。この属性を指定した場合、jwsc Antタスクでは新しいWSDLファイルが生成されるかわりに、JARファイル内のWSDLファイルが使用されます。そのため、WebサービスをデプロイしてそのWSDLを参照すると、デプロイ済のWSDLは開始当初のWSDLとまったく同じように見えます(WS-AtomicTransactionポリシー・アサーションが付いています)。

wsdlcを使用した、WSDLファイルからのWebサービスの生成の詳細は、「WSDLファイルから開始するWebLogic Webサービスの開発: 主な手順」を参照してください

Webサービス・クライアントに対するWebサービス原子性トランザクションの有効化

Webサービス・クライアントに対しては、次のいずれかの方法でWebサービス原子性トランザクションを有効にします。

  • クライアントのWebサービス参照インジェクション・ポイントに@weblogic.wsee.wstx.wsat.Transactionalアノテーションを追加します。詳細は、「@Transactionalアノテーションと@WebServiceRefアノテーションの併用」を参照してください。

  • Webサービスのプロキシまたはディスパッチの作成時にweblogic.wsee.wstx.wsat.TransactionalFeatureのインスタンスをパラメータとして渡します。詳細は、「TransactionalFeatureをクライアントに渡す」を参照してください。

  • デプロイメント時に、WebLogic Server管理コンソールを使用して、Webサービス・クライアントのエンドポイント・レベルまたはメソッド・レベルでWebサービス原子性トランザクションを有効にして構成します。詳細は、「管理コンソールを使用したWebサービス原子性トランザクションの構成」を参照してください。

  • 実行時に、原子性トランザクションに対応していないWebサービス・クライアントが。原子性トランザクションに対応しているWebサービスを呼び出すと、WSDLで示されるフロー・タイプの設定に基づいて次の処理が行われます。

    • サービス側でフロー・タイプがSUPPORTSまたはNEVERに設定されている場合、呼出しはトランザクションの一部として組み込まれます。

    • フロー・タイプがMANDATORYに設定されている場合、例外がスローされます。

    注意:

    Webサービス原子性トランザクションは、Java SEクライアントではサポートされていません。

Webサービス原子性トランザクションを有効にする際に設定可能な構成オプションについては、表15-2を参照してください。

@Transactionalアノテーションと@WebServiceRefアノテーションの併用

Webサービス原子性トランザクションを有効にするには、Webサービス・クライアントのWebサービス参照(@WebServiceRef)インジェクション・ポイントに@weblogic.wsee.wstx.wsat.Transactionalアノテーションを指定します。

@Transactionalアノテーションを指定する際の形式は次のとおりです。

@Transactional(
     version=Transactional.Version.[WSAT10|WSAT11|WSAT12|DEFAULT],
     value=Transactional.TransactionFlowType.[MANDATORY|SUPPORTS|NEVER]
)

バージョンおよびフロー・タイプの構成オプションの詳細は、表15-2を参照してください。

次の例は、Webサービス参照インジェクション・ポイントにアノテーションを追加する方法を示しています。関連するコードは太字で示されています。例に示すように、アクティブなJTAトランザクションは原子性トランザクションの一部になります。

注意:

次のコードは、WebLogic Serverサンプル・サーバー付属のWebサービス原子性トランザクションの例から抜粋したものです。詳細は、「Webサービス原子性トランザクションのその他の使用例」を参照してください。

package examples.webservices.jaxws.wsat.simple.client;
. . .
import javax.servlet.*;
import javax.servlet.http.*;
. . .
import java.net.URL;
import javax.xml.namespace.QName;

import javax.transaction.UserTransaction;
import javax.transaction.SystemException;
 
import javax.xml.ws.WebServiceRef;
import weblogic.wsee.wstx.wsat.Transactional;
*/
 
/**
 * This example demonstrates using a WS-Atomic Transaction to create or delete an account,
 * or transfer money via web service as a single atomic transaction.
 */
 
public class WsatBankTransferServlet extends HttpServlet {
. . . 
        String url = "http://localhost:7001";
        URL wsdlURL = new URL(url + "/WsatBankTransferService/WsatBankTransferService");
. . . 
        DataSource ds = null;
        UserTransaction utx = null;
 
        try {
            ctx = new InitialContext();
            utx = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction");
            utx.setTransactionTimeout(900);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
 
        WsatBankTransferService port = getWebService(wsdlURL);
 
        try {
            utx.begin();
            if (remoteAccountNo.length() > 0) {
                if (action.equals("create")) {
                    result = port.createAccount(remoteAccountNo, amount);
                } else if (action.equals("delete")) {
                    result = port.deleteAccount(remoteAccountNo);
                } else if (action.equals("transfer")) {
                    result = port.transferMoney(remoteAccountNo, amount, direction);
                }
            }
            utx.commit();
            result = "The transaction is committed " + result;
       } catch (java.lang.Exception e) {
           try {
                  e.printStackTrace();   
                  utx.rollback();
                  result = "The transaction is rolled back.    " + e.getMessage();
           } catch(java.lang.Exception ex) {
             e.printStackTrace();
             result = "Exception is caught. Check stack trace.";
           }
      }
      request.setAttribute("result", result);
 . . . 
    @Transactional(value = Transactional.TransactionFlowType.MANDATORY, 
                    version = Transactional.Version.WSAT10)
     @WebServiceRef(wsdlLocation =
          "http://localhost:7001/WsatBankTransferService/WsatBankTransferService?WSDL", value =
          examples.webservices.jaxws.wsat.simple.service.WsatBankTransferService.class)
    WsatBankTransferService_Service service;
    private WsatBankTransferService getWebService() {
          return service.getWSHttpBindingIService();
    }
 
    public String createAccount(String acctNo, String amount) throws java.lang.Exception{
        Context ctx = null;         UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
            try {
                DataSource dataSource = (DataSource)ctx.lookup("examples-dataSource-demoXAPool");
                String sql = "insert into wsat_acct_local (acctno, amount) values (
                    " + acctNo + ", " + amount + ")";
                int insCount = dataSource.getConnection().prepareStatement(sql).executeUpdate();
                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at local.");
                return ":acctno=" + acctNo + " amount=" + amount + " creating.. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();
               throw new SQLException("SQL Exception during createAccount() at local.");
            }
        } catch (java.lang.Exception e) {
        System.out.println("**** Exception caught *****");
            e.printStackTrace();
        throw new java.lang.Exception(e);
        }
    }
 
    public String deleteAccount(String acctNo) throws java.lang.Exception{
    . . .
    }
    public String transferMoney(String acctNo, String amount, String direction) throws 
         java.lang.Exception{
    . . .
    }
    public String listAccount() throws java.lang.Exception{
    . . .
    }
}
package examples.webservices.service_to_service;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.WebServiceRef;
import weblogic.wsee.wstx.wsat.Transactional;
import weblogic.wsee.wstx.wsat.Transactional.TransactionalFlowType;
import weblogic.wsee.wstx.wsat.Transactional.Version;
import examples.webservices.complex.ComplexPortType;
import examples.webservices.complex.ComplexService;
...
@WebService(name="ClientPortType", serviceName="ClientService",
            targetNamespace="http://examples.org")
public class ClientServiceImpl {
  @Transactional(value = Transactional.TransactionFlowType.SUPPORTS, 
       version = Transactional.Version.WSAT12)
  @WebServiceRef()
  ComplexService service;
  @WebMethod()
  public String callComplexService(BasicStruct input)
  {
    // Create service and port stubs to invoke ComplexService
    ComplexPortType port = service.getComplexPortTypePort();
    // Include your implementation here.
  }
}

TransactionalFeatureをクライアントに渡す

Webサービスのクライアントに対してWebサービス原子性トランザクションを有効にするには、次の例のように、Webサービスのプロキシまたはディスパッチの作成時にweblogic.wsee.wstx.wsat.TransactionalFeatureのインスタンスをパラメータとして渡します。関連するコードは太字で示されています。

注意:

次のコードは、WebLogic Serverサンプル・サーバー付属のWebサービス原子性トランザクションの例から抜粋したものです。詳細は、「Webサービス原子性トランザクションのその他の使用例」を参照してください。

package examples.webservices.jaxws.wsat.simple.client;
. . .
import javax.servlet.*;
import javax.servlet.http.*;
. . .
import java.net.URL;
import javax.xml.namespace.QName;

import javax.transaction.UserTransaction;
import javax.transaction.SystemException;
 
import weblogic.wsee.wstx.wsat.TransactionalFeature;
import weblogic.wsee.wstx.wsat.Transactional.Version;
import weblogic.wsee.wstx.wsat.Transactional.TransactionFlowType;
*/
 
/**
 * This example demonstrates using a WS-Atomic Transaction to create or delete an account,
 * or transfer money via web service as a single atomic transaction.
 */
 
public class WsatBankTransferServlet extends HttpServlet {
. . . 
        String url = "http://localhost:7001";
        URL wsdlURL = new URL(url + "/WsatBankTransferService/WsatBankTransferService");
. . . 
        DataSource ds = null;
        UserTransaction utx = null;
 
        try {
            ctx = new InitialContext();
            utx = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction");
            utx.setTransactionTimeout(900);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
 
        WsatBankTransferService port = getWebService(wsdlURL);
 
        try {
            utx.begin();
            if (remoteAccountNo.length() > 0) {
                if (action.equals("create")) {
                    result = port.createAccount(remoteAccountNo, amount);
                } else if (action.equals("delete")) {
                    result = port.deleteAccount(remoteAccountNo);
                } else if (action.equals("transfer")) {
                    result = port.transferMoney(remoteAccountNo, amount, direction);
                }
            }
            utx.commit();
            result = "The transaction is committed " + result;
       } catch (java.lang.Exception e) {
           try {
                  e.printStackTrace();   
                  utx.rollback();
                  result = "The transaction is rolled back.    " + e.getMessage();
           } catch(java.lang.Exception ex) {
             e.printStackTrace();
             result = "Exception is caught. Check stack trace.";
           }
      }
      request.setAttribute("result", result);
 . . . 
    // Passing the TransactionalFeature to the Client
    private WsatBankTransferService getWebService(URL wsdlURL) {
        TransactionalFeature feature = new TransactionalFeature(); 
        feature.setFlowType(TransactionFlowType.MANDATORY);
        feature.setVersion(Version.WSAT10);
        WsatBankTransferService_Service service = new WsatBankTransferService_Service(wsdlURL, 
              new QName("http://tempuri.org/", "WsatBankTransferService"));
        return service.getWSHttpBindingIService(new javax.xml.ws.soap.AddressingFeature(), 
              feature);
    }
 
    public String createAccount(String acctNo, String amount) throws java.lang.Exception{
        Context ctx = null;         UserTransaction tx = null;
        try {
            ctx = new InitialContext();
            tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
            try {
                DataSource dataSource = (DataSource)ctx.lookup("examples-dataSource-demoXAPool");
                String sql = "insert into wsat_acct_local (acctno, amount) values (
                    " + acctNo + ", " + amount + ")";
                int insCount = dataSource.getConnection().prepareStatement(sql).executeUpdate();
                if (insCount != 1)
                    throw new java.lang.Exception("insert fail at local.");
                return ":acctno=" + acctNo + " amount=" + amount + " creating.. ";
            } catch (SQLException e) {
                System.out.println("**** Exception caught *****");
                e.printStackTrace();
               throw new SQLException("SQL Exception during createAccount() at local.");
            }
        } catch (java.lang.Exception e) {
        System.out.println("**** Exception caught *****");
            e.printStackTrace();
        throw new java.lang.Exception(e);
        }
    }
 
    public String deleteAccount(String acctNo) throws java.lang.Exception{
    . . .
    }
    public String transferMoney(String acctNo, String amount, String direction) throws 
         java.lang.Exception{
    . . .
    }
    public String listAccount() throws java.lang.Exception{
    . . .
    }
}
package jaxws.interop.rsp;
...
import javax.jws.WebService;
import javax.xml.ws.*;
import weblogic.wsee.wstx.wsat.TransactionalFeature;
...
@WebService(
     portName = "TravelAgencyServiceBindings_Basic", 
     serviceName = "TravelAgencyService",
     targetNamespace ="http://wsinterop.org/samples",
     wsdlLocation = "/wsdls/TravelAgencyService.wsdl", 
     endpointInterface = "jaxws.interop.rsp.ITravelAgencyService"
)
@BindingType("http://schemas.xmlsoap.org/wsdl/soap/http")
@javax.xml.ws.soap.Addressing()
public class TravelAgencyServiceImpl implements ITravelAgencyService {
...
   private IFlightService getFlightProxy(String endpoint, String stsEndpoint) throws Exception {
        TransactionalFeature feature = new TransactionalFeature();
        // Optional setting.
        feature.setVersion(Transactional.Version.WSAT12);
        // Optional setting.
        feature.setEnabled("ReserveFlight", true);
        IFlightService flightProxy = flightService.getFlightServiceBindingsBasic(feature);
...
   }
}

管理コンソールを使用したWebサービス原子性トランザクションの構成

次の項では、WebLogic Server管理コンソールを使用してWebサービス原子性トランザクションを構成する方法について説明します。

コーディネータと参加者の間で交換されるメッセージの保護

トランスポート・レベルのセキュリティを使用して、Webサービス原子性トランザクションのコーディネータと参加者の間で交換されるメッセージを保護するには、WebLogic Server管理コンソールで、次の表に定義されているプロパティを構成します。これらのプロパティは、ドメイン・レベルで構成します。詳細な手順は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプWebサービス原子性トランザクションの構成を参照してください。

表15-5 Webサービス原子性トランザクションの保護

プロパティ 説明

Webサービス・トランザクションのトランスポート・セキュリティ・モード

コーディネータと参加者の間のメッセージ交換に双方向SSLを使用するかどうかを指定します。このプロパティは、次のいずれかの値に設定できます。

  • SSLは不要: Webサービス・トランザクションのプロトコル・メッセージはすべて、HTTPチャネル経由で交換されます。

  • SSLが必要: Webサービス・トランザクションのプロトコル・メッセージはすべて、HTTPSチャネル経由で交換されます。このフラグは、原子性トランザクションが有効になっているMicrosoft .NET Webサービスを起動する際に有効にする必要があります。

  • クライアント証明書が必要: Webサービス・トランザクションのプロトコル・メッセージはすべてHTTPS経由で交換され、クライアント証明書が必要となります。

詳細は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプの双方向SSLの構成に関する説明を参照してください。

Webサービス・トランザクションの発行済みトークンを有効化

発行済トークンを使用してコーディネータと参加者の間の認証を有効にするかどうかを指定するフラグ。

IssuedTokenは、コーディネータによって発行され、セキュリティ・コンテキスト・トークン(SCT)と署名用のセッション・キーで構成されます。参加者は、共有セッション・キーを使用して署名した署名を登録メッセージに入れて送信します。コーディネータは、セッション・キーを使用して署名を検証することにより、参加者を認証します。

Webサービス原子性トランザクションの有効化および構成

Webサービス原子性トランザクションを有効にしてバージョンとフロー・タイプを構成する場合、Webサービスまたはクライアントのエンドポイント・レベルまたはメソッド・レベルで構成をカスタマイズできます。詳細な手順は、Oracle WebLogic Server管理コンソール・オンライン・ヘルプWebサービス原子性トランザクションの構成を参照してください。

クラスタ環境でのWebサービス原子性トランザクションの使用

原子性トランザクションに対応しているWebサービスをクラスタ環境で使用する際の考慮事項については、クラスタ内のWebサービスの管理を参照してください。

Webサービス原子性トランザクションのその他の使用例

Webサービス原子性トランザクションのその他の使用例については、次の項を参照してください。

  • Webサービス原子性トランザクションで交換されるメッセージ・ヘッダーの署名と暗号化の方法を示す例は、Oracle WebLogic Server WebLogic Webサービスの保護のWebサービス原子性トランザクションの保護を参照してください。

    注意:

    Webサービス原子性トランザクションが有効なアプリケーションを保護するために使用できるのは、WebLogic Webサービスのセキュリティ・ポリシーのみです。Oracle Web Services Manager (WSM)ポリシーを使用して保護することはできません。

  • Webサービス原子性トランザクションの詳しい例がWebLogic Serverサンプル・アプリケーションの一部として提供されています。サンプル・アプリケーションの実行と例へのアクセスの詳細は、Oracle WebLogic Serverの理解のサンプル・アプリケーションおよびサンプル・コードを参照してください。