6.8 XAでのJAX-RSアプリケーションの開発

JAX-RSアプリケーションでMicroTxライブラリを使用します。

6.8.1 JAX-RSアプリケーションのMicroTxライブラリについて

MicroTxライブラリをJAX-RSアプリケーションと統合します。

JAX-RS用のMicroTxライブラリは次の機能を実行します:

  • 参加側サービスをトランザクション内でトランザクション・コーディネータに登録します。
  • 使用する参加側アプリケーション・コードのために依存関係インジェクションを介してXADataSourceオブジェクトを注入し、関連付けられたXAResourceに対してstart()をコールします。参加側マイクロサービス(XAトランザクションのコンテキストでコールされるマイクロサービス)は、XA準拠のデータ・ソースを使用する必要があります。Javaでは、これはXADataSourceオブジェクトの使用を意味します。

    MicroTxライブラリは、構成済のデータ・ソースを参加側サービスに自動的に注入するため、アプリケーション開発者は@Injectまたは@Context注釈をアプリケーション・コードに追加する必要があります。アプリケーション・コードは、この関連付けを使用してDMLを実行します。

  • リソース・マネージャをコールして操作を実行します。

6.8.2 トランザクション・イニシエータとしてのJAX-RSアプリケーションの構成

トランザクション・イニシエータ・サービスは、トランザクションを開始します。トランザクション・イニシエータ・サービスは、アプリケーションのビジネス・ロジックに基づいて、トランザクションの開始のみ、またはトランザクションの開始とトランザクションへの参加を行うことができます。

開始する前に、アプリケーションがトランザクションを開始するだけか、トランザクションを開始して参加するのかを確認します。2つのシナリオでは要件が若干異なるため、それに応じてアプリケーションを構成します。

2つのシナリオを検討して、アプリケーションがトランザクションを開始するだけか、トランザクションにも参加するかを理解します。
  • シナリオ1: 銀行振込アプリケーションによって、ある部門から別の部門に送金します。この場合、振込アプリケーションはトランザクションを開始するだけで、トランザクションには参加しません。振込アプリケーションは、トランザクションを完了するためにビジネス・ロジックに基づいて様々なサービスをコールします。データベース・インスタンスは、振込アプリケーションにアタッチされる場合とアタッチされない場合があります。
  • シナリオ2: 銀行振込アプリケーションによって、ある部門から別の部門に送金します。振込アプリケーションは、トランザクションごとに手数料として1%を請求します。この場合、振込アプリケーションはトランザクションを開始して参加します。データベース・インスタンスは、トランザクション情報を保存するために振込アプリケーションにアタッチされる必要があります。
Javaアプリケーションをトランザクション・イニシエータとして構成するには:
  1. MicroTxライブラリのプロパティ値を指定します。ライブラリ・プロパティの構成を参照してください。
  2. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  3. oracle.tmm.jta.TrmUserTransactionパッケージをインポートします。
    import oracle.tmm.jta.TrmUserTransaction;
  4. すべての新しいトランザクションでTrmUserTransactionクラスのオブジェクトを初期化し、アプリケーション・コード内のトランザクション境界(トランザクションの開始、コミットまたはロールバックなど)を定めます。アプリケーション・ロジックがトランザクションを開始する前にオブジェクトを初期化します。
    次のコード・サンプルは、utというTrmUserTransactionクラスのインスタンスを作成する方法を示しています。
    UserTransaction ut = new oracle.tmm.jta.TrmUserTransaction();
  5. 次のコード・サンプルは、コールされた新しいXAトランザクションを開始する方法を示しています。
    • アプリケーションがトランザクションを開始するだけでトランザクションに参加しない場合は、次の行をアプリケーション・コードに追加して、XAトランザクションを開始します。

      
      ut.begin();
      ... // Implement the business logic to begin a transaction.
    • アプリケーションがトランザクションを開始して参加する場合は、次の行をアプリケーション・コードに追加して、XAトランザクションを開始します。

      
      ut.begin(true);
      ... // Implement the business logic to begin a transaction.
      
  6. RESTクライアントを作成します。

    次のコマンドによって、svcClientという新しいクライアントが作成されます。

    Client svcClient = ClientBuilder.newClient();

    このRESTクライアントを使用して、トランザクション参加側サービスのエンドポイントをコールし、トランザクションを実行します。トランザクション・イニシエータ・サービスはトランザクションを開始します。トランザクションを完了するために、イニシエータ・サービスは1つ以上の参加側サービスをコールする必要があります。参加側サービスをコールするときに、作成したRESTクライアントを使用します。

  7. ビジネス・ロジックに基づいて、トランザクションをコミットまたはロールバックします。
    • トランザクションをコミットするには:

      ut.commit();
    • トランザクションをロールバックするには:

      ut.rollback();
  8. JAX-RS APIを使用するSpring Bootアプリケーションの場合のみ、次のサンプル・コード・スニペットに示すように、準備、コミット、ロールバックのために、フィルタとXAResourceCallbacksを登録します。
    @Component
    public class Configuration extends ResourceConfig
    {
        public Configuration()
        {
            // Register the MicroTx XA resource callback which
            // coordinates with the transaction coordinator
            register(XAResourceCallbacks.class);
            // Register the filters for the MicroTx libraries that 
            // intercept the JAX_RS calls and manage the XA transactions
            register(TrmTransactionResponseFilter.class);
            register(TrmTransactionRequestFilter.class);
        }
    }
トランザクション・イニシエータ・サービスのサンプルXAアプリケーション・コードは、installation_directory\otmm-RELEASE\samples\xa\java\accountsにあります。これは、MicroTx JavaライブラリをJavaイニシエータ・アプリケーションのビジネス・ロジックとともに使用する方法の例です。このサンプル・アプリケーションは振込(Teller)という名前です。これは2つの部門間のトランザクションを開始します。部門Aをコールして一定金額を引き出し、部門Bをコールして預け入れます。
イニシエータ・サービスが、トランザクションを開始するだけでなくトランザクションに参加する場合、トランザクションに参加してリソース・マネージャと通信するアプリケーションのために追加の構成を行う必要があります。「トランザクション参加側としてのJAX-RSアプリケーションの構成」を参照してください。

6.8.3 トランザクション参加側としてのJAX-RSアプリケーションの構成

リソース・マネージャがXAに準拠しているかどうかに基づいて、環境変数を設定し、MicroTxライブラリの様々なクラスを実装して参加側アプリケーションを構成します。

6.8.3.1 XA準拠リソース・マネージャを使用するJAX-RSアプリケーションの構成

XA準拠のリソース・マネージャを使用する場合は、この項に記載されている情報を使用してJAX-RS参加側アプリケーションを構成します。

  1. MicroTxクライアント・ライブラリのプロパティ値を指定します。

    次の例では、プロパティのサンプル値を指定しています。ご自身の環境に基づいて値を指定してください。

    oracle.tmm.TcsConnPoolSize = 15
    oracle.tmm.CallbackUrl = https://bookTicket-app:8081
    oracle.tmm.PropagateTraceHeaders = true
    oracle.tmm.TransactionTimeout = 60000
    oracle.tmm.xa.XaSupport = true

    oracle.tmm.xa.XaSupporttrueに設定されていることを確認します。

    各プロパティおよびその他のオプション・プロパティの詳細は、「ライブラリ・プロパティの構成」を参照してください。

  2. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  3. XADatasourceオブジェクトを初期化します。

    MicroTxクライアント・ライブラリは、XADatasourceオブジェクトにアクセスする必要があります。このオブジェクトを使用してXAConnectionオブジェクトおよびXAResourceオブジェクトを作成し、リソース・マネージャまたはデータベース・サーバーに接続します。次のコードでは、接続オブジェクトを作成する際にアプリケーション・コードの先頭にXADatasourceオブジェクトをどのように定義するかを示しています。

    class oracle.tmm.jta.TrmConfig
    static void initXaDataSource(XADataSource xaDs)

    XADataSourceの詳細は、https://docs.oracle.com/javase/8/docs/api/javax/sql/XADataSource.htmlを参照してください。

  4. トランザクション参加側関数またはブロックで、MicroTxクライアント・ライブラリで使用されるXADatasourceオブジェクトを指定します。リソース・マネージャに接続するための資格証明およびその他の詳細を指定します。
    //Example for a participant using an Oracle Database:
    OracleXADataSource dataSource = new oracle.jdbc.xa.client.OracleXADataSource();
    dataSource.setURL(url); //database connection string
    dataSource.setUser(user); //username to access database
    dataSource.setPassword(password); //password to access database
    TrmConfig.initXaDataSource((XADataSource)dataSource);

    アプリケーション開発者は、XADataSourceを割り当てる際に、XA準拠JDBCドライバおよび必要なパラメータを設定する必要があります。

    MicroTxクライアント・ライブラリは、XADatasourceオブジェクトを使用してデータベース接続を作成します。

  5. トランザクション参加側の関数すなわちブロックで、XADatasourceオブジェクトを初期化した後に次のコード行を1回だけ追加します。
    oracle.tmm.jta.TrmConfig.initXaDataSource((XADataSource)xaDs);

    XADatasourceはJTAで定義されたインタフェースであり、JDBCドライバによって実装が提供されます。

    MicroTxクライアント・ライブラリは、このオブジェクトを使用してデータベースに接続し、XAトランザクションを開始し、準備、コミット、ロールバックなどの様々な操作を実行します。MicroTxライブラリは、依存関係インジェクションを使用してDMLを実行するためのSQL接続オブジェクトもアプリケーション・コードに提供します。

  6. 参加側サービスのコードに次の行を挿入して、アプリケーションがMicroTxクライアント・ライブラリによって渡された接続を使用するようにします。参加側アプリケーションの次のコードは、MicroTxクライアント・ライブラリによって作成されたconnectionオブジェクトを注入します。
    @Inject
    @TrmSQLConnection 
    private Connection connection;
  7. 参加側サービスのコードに次の行を挿入して、参加側サービスがDML操作を実行するたびに、注入されたconnectionオブジェクトを使用するようにします。
    Statement stmt1 = connection.createStatement();
    stmt1.execute(query);
    stmt1.close();

    ここで、connectionは、前のステップで注入したConnectionオブジェクトの名前です。

    これらのコード行は、参加側サービスが実行するDML操作ごとに挿入します。DML操作ごとにstmt1stmt2などの新しい文オブジェクトを作成しますが、MicroTxクライアント・ライブラリによって作成された同一のconnectionオブジェクトを使用します。

  8. JAX-RS APIを使用するSpring Bootアプリケーションの場合のみ、XAトランザクションに参加するリソース・エンドポイントを登録した後で次のタスクを実行します。
    1. 次のサンプル・コード・スニペットに示すように、準備、コミット、ロールバックのために、フィルタとXAResourceCallbacksを登録します。

      @Component
      public class JerseyConfig extends ResourceConfig
      {
          public JerseyConfig()
          {
              // Register the MicroTx XA resource callback which
              // coordinates with the transaction coordinator
              register(XAResourceCallbacks.class);
              // Register the filters for the MicroTx libraries that 
              // intercept the JAX_RS calls and manage the XA transactions
              register(TrmTransactionResponseFilter.class);
              register(TrmTransactionRequestFilter.class);
              
              // Bind the connection
              ...
          }
      }
    2. Spring Bootアプリケーションで1つのリソース・マネージャを使用している場合は、TrmXAConnectionFactoryオブジェクトをXAConnectionにバインドします。後で、TrmXAConnectionFactoryオブジェクト(MicroTx接続ファクトリ・オブジェクト)を使用します。これによってMicroTxが接続を処理します。

      @Component
      public class JerseyConfig extends ResourceConfig
      {
          public JerseyConfig()
          {
              // Register the filters as shown in the previous step
              ....
      
              register(new AbstractBinder() {
                  @Override
                  protected void configure() {
                  //Bind the TrmXAConnectionFactory object to an XAConnection object
                  bindFactory(TrmXAConnectionFactory.class).to(XAConnection.class);
                  }
              });
          }
      }
  9. 変更内容を保存します。
複数のJAX-RSトランザクション参加側サービスがある場合は、すべての参加側サービスでこれらのステップを完了します。

6.8.3.2 複数のXA準拠リソース・マネージャを使用するJAX-RSアプリケーションの構成

複数のXA準拠のリソース・マネージャを使用する場合は、この項に記載されている情報を使用してJAX-RS参加側アプリケーションを構成します。

アプリケーションは、複数のXA準拠リソース・マネージャに接続できます。また、アプリケーションは1つの非XAリソースに接続できます。
  1. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  2. リソース・マネージャごとにDataSourceInfoオブジェクトを作成します。必ず、アプリケーションのYAMLファイルで指定したデータ・ソース名とリソース・マネージャIDを指定してください。

    サンプル・コマンド

    DataSourceInfo departmentDataSourceInfo = new DataSourceInfo("ORCL1-8976-9776-9873");
    departmentDataSourceInfo.setDataSourceName(departmentDataSource);
    
    DataSourceInfo creditDataSourceInfo = new DataSourceInfo("ORCL2-2134-5668-8672");
    creditDataSourceInfo.setDataSourceName(creditDataSource);

    説明

    • departmentDataSourceおよびcreditDataSourceは、アプリケーションのYAMLファイルで指定したXAデータ・ソースの名前です。
    • ORCL1-8976-9776-9873およびORCL2-2134-5668-8672は、アプリケーションのYAMLファイルでdepartmentDataSourceおよびcreditDataSourceにそれぞれ指定したリソース・マネージャIDです。

    後で、@Inject注釈を使用して、アプリケーションでこれらのデータ・ソースが使用されることを確認します。

  3. 作成したDataSourceInfoオブジェクトごとに、次のMicroTxクライアント・ライブラリ・プロパティの1つのみを入力します。次の例では、creditDataSourceオブジェクトのプロパティ値を指定します。同様に、他のリソース・マネージャのプロパティ値を指定できます。値を指定しない場合、リソースはデフォルトでXA準拠とみなされます。
    • XA準拠リソースの場合は、次を入力します:
      creditDataSource.setXaSupport();
    • Oracle RACデータベースの場合は、次のように入力します:
      creditDataSource.setRAC(true);
    • LLRの最適化を使用する非XAリソースの場合は、次を入力します:
      creditDataSource.setLLRSupport();
    • LRCの最適化を使用する非XAリソースの場合は、次を入力します:
      creditDataSource.setLRCSupport();
  4. XADatasourceオブジェクトを初期化します。アプリケーションで複数のリソース・マネージャを使用している場合は、XA準拠リソース・マネージャごとに次の方法でXADatasourceオブジェクトを初期化します。

    MicroTxクライアント・ライブラリは、XADatasourceオブジェクトにアクセスする必要があります。このオブジェクトを使用してXAConnectionオブジェクトおよびXAResourceオブジェクトを作成し、リソース・マネージャまたはデータベース・サーバーに接続します。次のコードでは、接続オブジェクトを作成する際にアプリケーション・コードの先頭にXADatasourceオブジェクトをどのように定義するかを示しています。

    class oracle.tmm.jta.TrmConfig
    static void initXaDataSource(XADataSource dataSource, DataSourceInfo creditDataSource)

    ここで、creditDataSourceは、以前に作成したDataSourceInfoオブジェクトです。

    すべてのリソース・マネージャについてこのステップを繰り返します。

    XADataSourceの詳細は、https://docs.oracle.com/javase/8/docs/api/javax/sql/XADataSource.htmlを参照してください。

  5. トランザクション参加側関数またはブロックで、MicroTxクライアント・ライブラリで使用されるXADatasourceオブジェクトを指定します。リソース・マネージャに接続するための資格証明およびその他の詳細を指定します。
    //Example for a participant using an Oracle Database:
    OracleXADataSource dataSource = new oracle.jdbc.xa.client.OracleXADataSource();
    dataSource.setURL(url); //database connection string
    dataSource.setUser(user); //username to access database
    dataSource.setPassword(password); //password to access database

    アプリケーション開発者は、XADataSourceを割り当てる際に、XA準拠JDBCドライバおよび必要なパラメータを設定する必要があります。

    MicroTxクライアント・ライブラリは、XADatasourceオブジェクトを使用してデータベース接続を作成します。

    すべてのリソース・マネージャについてこのステップを繰り返します。

  6. トランザクション参加側の関数すなわちブロックで、XADatasourceオブジェクトを初期化した後に次のコード行を1回だけ追加します。
    oracle.tmm.jta.TrmConfig.initXaDataSource(dataSource, creditDataSource)

    ここで、 creditDataSourceは、以前に作成したDataSourceInfoオブジェクトです。

    MicroTxクライアント・ライブラリは、このオブジェクトを使用してデータベースに接続し、XAトランザクションを開始し、準備、コミット、ロールバックなどの様々な操作を実行します。MicroTxライブラリは、依存関係インジェクションを使用してDMLを実行するためのSQL接続オブジェクトもアプリケーション・コードに提供します。

    すべてのリソース・マネージャについてこのステップを繰り返します。

  7. JAX-RS APIを使用するSpring Bootアプリケーションの場合のみ、XAトランザクションに参加するリソース・エンドポイントを登録した後で次のタスクを実行します。
    1. 次のサンプル・コード・スニペットに示すように、準備、コミット、ロールバックのために、フィルタとXAResourceCallbacksを登録します。

      @Component
      public class JerseyConfig extends ResourceConfig
      {
          public JerseyConfig()
          {
              // Register the MicroTx XA resource callback which
              // coordinates with the transaction coordinator
              register(XAResourceCallbacks.class);
              // Register the filters for the MicroTx libraries that 
              // intercept the JAX_RS calls and manage the XA transactions
              register(TrmTransactionResponseFilter.class);
              register(TrmTransactionRequestFilter.class);
              
              // Bind the connection
              ...
          }
      }
    2. リソース・マネージャごとにBeanを初期化します。次のサンプル・コード・スニペットでは、2つのBean (アプリケーションが使用するリソース・マネージャごとに1つ)を初期化する方法を示しています。次のコード・サンプルで、departmentDataSourceおよびcreditDataSourceは、アプリケーションのYAMLファイルで指定したXAデータ・ソースの名前です。後で@Inject注釈を使用して参加側アプリケーションでこれらの接続が使用されることを確認するため、データ・ソースの名前を書き留めておきます。
      @Component
      public class JerseyConfig extends ResourceConfig
      {
          public JerseyConfig()
          {
              // Register the filters as shown in the previous step
              ....
          @Bean
          @TrmSQLConnection(name = "departmentDataSource")
          @Lazy
          @RequestScope
          public Connection departmentDSSqlConnectionBean(){
              return new TrmConnectionFactory().getConnection("departmentDataSource");
          }
      
          @Bean
          @TrmSQLConnection(name = "creditDataSource")
          @Lazy
          @RequestScope
          public Connection creditDSSqlConnectionBean(){
              return new TrmConnectionFactory().getConnection("creditDataSource");
          }
          }
      }
  8. 参加側サービスのコードに次の行を挿入して、アプリケーションがMicroTxクライアント・ライブラリによって渡された接続を使用するようにします。参加側アプリケーションの次のコードは、MicroTxクライアント・ライブラリによって作成されたconnectionオブジェクトを注入します。

    アプリケーションで複数のリソース・マネージャを使用している場合は、XA準拠リソース・マネージャごとに次の方法でconnectionオブジェクトを注入します。

    @Inject
    @TrmSQLConnection(name = "creditDataSource")
    private Connection creditConnection;

    ここで、creditDataSourceは、oracle.tmm.jta.common.DataSourceInfoパッケージのDataSourceInfoクラスのdataSourceName文字列に指定した値です。

    すべてのリソース・マネージャについてこのステップを繰り返します。

  9. 参加側サービスのコードに次の行を挿入して、参加側サービスがDML操作を実行するたびに、注入されたconnectionオブジェクトを使用するようにします。
    Statement stmt1 = creditConnection.createStatement();
    stmt1.execute(query);
    stmt1.close();

    ここで、creditConnectionは、前のステップで注入したConnectionオブジェクトの名前です。

    これらのコード行は、参加側サービスが実行するDML操作ごとに挿入します。DML操作ごとにstmt1stmt2などの新しい文オブジェクトを作成しますが、MicroTxクライアント・ライブラリによって作成された同一のcreditConnectionオブジェクトを使用します。

    すべてのリソース・マネージャについてこのステップを繰り返します。

  10. 変更内容を保存します。
複数のJAX-RSトランザクション参加側サービスがある場合は、すべての参加側サービスでこれらのステップを完了します。

6.8.3.3 非XA JDBCリソースを使用するJAX-RSアプリケーションの構成

XAをサポートしないJDBCリソースを使用する場合は、この項に記載されている情報を使用してJAX-RS参加側アプリケーションを構成します。

アプリケーションは、複数のXA準拠リソース・マネージャに接続できます。また、アプリケーションは1つの非XAリソースに接続できます。
  1. 1つのリソース・マネージャを使用する場合は、すべてのMicroTxクライアント・ライブラリ・プロパティの値を1つのファイル(tmm.propertiesファイルなど)に指定します。アプリケーションで複数のリソース・マネージャを使用している場合は、このステップをスキップします。

    oracle.tmm.xa.XaSupportfalseoracle.tmm.xa.LLRSupportまたはoracle.tmm.xa.LRCSupporttrueに設定されていることを確認します。

    • ロギング・ラスト・リソース(LLR)の最適化を有効にするには、環境変数に次の値を設定します。
      oracle.tmm.xa.XaSupport = false
      oracle.tmm.xa.LLRSupport = true
      oracle.tmm.xa.LRCSupport = false
      oracle.tmm.TcsConnPoolSize = 15
      oracle.tmm.CallbackUrl = https://bookHotel-app:8081
      oracle.tmm.PropagateTraceHeaders = true
      oracle.tmm.TransactionTimeout = 60000
    • ラスト・リソース・コミット(LRC)の最適化を有効にするには、環境変数に次の値を設定します。
      oracle.tmm.xa.XaSupport = false
      oracle.tmm.xa.LLRSupport = false
      oracle.tmm.xa.LRCSupport = true
      oracle.tmm.TcsConnPoolSize = 15
      oracle.tmm.CallbackUrl = https://bookHotel-app:8081
      oracle.tmm.PropagateTraceHeaders = true
      oracle.tmm.TransactionTimeout = 60000
  2. アプリケーションで複数のリソース・マネージャを使用している場合は、次のステップを実行して、MicroTxクライアント・ライブラリのプロパティ値を構成します。1つのリソース・マネージャを使用している場合は、このステップをスキップします。
    1. リソース・マネージャごとにDataSourceInfoオブジェクトを作成します。必ず、アプリケーションのYAMLファイルで指定したデータ・ソース名とリソース・マネージャIDを指定してください。

      サンプル・コマンド

      DataSourceInfo departmentDataSourceInfo = new DataSourceInfo("ORCL1-8976-9776-9873");
      departmentDataSourceInfo.setDataSourceName(departmentDataSource);
      
      DataSourceInfo creditDataSourceInfo = new DataSourceInfo("ORCL2-2134-5668-8672");
      creditDataSourceInfo.setDataSourceName(creditDataSource);

      説明

      • departmentDataSourceおよびcreditDataSourceは、アプリケーションのYAMLファイルで指定したXAデータ・ソースの名前です。
      • ORCL1-8976-9776-9873およびORCL2-2134-5668-8672は、アプリケーションのYAMLファイルでdepartmentDataSourceおよびcreditDataSourceにそれぞれ指定したリソース・マネージャIDです。

      後で、@Inject注釈を使用して、アプリケーションでこれらのデータ・ソースが使用されることを確認します。

    2. 作成したDataSourceInfoオブジェクトごとに、次のMicroTxクライアント・ライブラリ・プロパティの1つのみを入力します。次の例では、creditDataSourceオブジェクトのプロパティ値を指定します。同様に、他のリソース・マネージャのプロパティ値を指定できます。値を指定しない場合、リソースはデフォルトでXA準拠とみなされます。
      • XA準拠リソースの場合は、creditDataSource.setXaSupport();と入力します。
      • LLRの最適化を使用する非XAリソースの場合は、 creditDataSource.setLLRSupport();と入力します。
      • LRCの最適化を使用する非XAリソースの場合は、 creditDataSource.setLRCSupport();と入力します。
  3. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  4. セッション・アフィニティを有効にします。「セッション・アフィニティの有効化」を参照してください。
  5. Datasourceオブジェクトを初期化します。

    MicroTxライブラリは、データ・ソース・オブジェクトにアクセスする必要があります。データ・ソース・オブジェクトを使用してjava.sql.Connectionオブジェクトを作成し、リソース・マネージャに接続します。次のコードは、データ・ソース・オブジェクトを定義する方法を示しています。

    このコードはアプリケーションの最初に指定する必要があります。したがって、initNonXaDataSourceメソッドは、サーバーの起動直後に、他のすべてのリクエストが処理される前にコールされます。

    • アプリケーションで1つのリソース・マネージャを使用している場合は、次のようにデータ・ソースを初期化します。

      class oracle.tmm.jta.TrmConfig
      static void initNonXaDataSource(DataSource NonXaDs)
    • アプリケーションで複数のリソース・マネージャを使用している場合は、非XA JDBCリソースに対して次の方法でデータ・ソース・オブジェクトを初期化します。参加側サービスは複数のXA準拠リソース・マネージャに接続できますが、1つのトランザクションでサポートされる非XAリソースは1つのみです。

      class oracle.tmm.jta.TrmConfig
      static void initNonXaDataSource(DataSource departmentDataSource, DataSourceInfo departmentDataSourceInfo)

      ここで、dataSourceInfoは、ステップ2で作成したオブジェクトです。

  6. トランザクション参加側関数またはブロックで、MicroTxライブラリで使用されるDataSourceオブジェクトを指定します。リソース・マネージャに接続するための資格証明およびデータベース・ドライバの詳細を指定します。次の例は、MySQLデータベースをLLRとして使用する場合に指定する必要がある詳細を示しています。同様に、他のデータベースの資格証明およびデータベース・ドライバ情報を指定できます。
    //Example for a participant using a MySQL database as resource manager
    this.dataSource = PoolDataSourceFactory.getPoolDataSource();
    this.dataSource.setURL(url); //Database connection string
    this.dataSource.setUser(user); //User name to access the database
    this.dataSource.setPassword(password); //Password to access the database
    //Database driver information for the MySQL database.
    //Provide the JDBC driver information that is specific to your database.
    this.dataSource.setConnectionFactoryClassName("com.mysql.cj.jdbc.MysqlDataSource");
    this.dataSource.setMaxPoolSize(15);

    アプリケーション開発者は、DataSourceを割り当てる際に、データベース固有のJDBCドライバおよび必要なパラメータを設定する必要があります。

    MicroTxライブラリは、DataSourceオブジェクトを使用してデータベース接続を作成します。

  7. トランザクション参加側の関数すなわちブロックで、Datasourceオブジェクトを初期化した後に次のコード行を1回だけ追加します。MicroTxライブラリは、このオブジェクトを使用してデータベース・トランザクションを開始します。MicroTxライブラリは、依存関係インジェクションを使用してDMLを実行するためのSQL接続オブジェクトもアプリケーション・コードに提供します。
    oracle.tmm.jta.TrmConfig.initNonXaDataSource((DataSource) NonXaDs);

    ここで、DatasourceはJTAで定義されたインタフェースであり、JDBCドライバによって実装が提供されます。

  8. 参加側サービスのコードに次の行を挿入して、アプリケーションがMicroTxライブラリによって渡された接続を使用するようにします。参加側アプリケーションの次のコードは、MicroTxライブラリによって作成されたconnectionオブジェクトを注入します。
    @Inject @TrmNonXASQLConnection private Connection connection;
  9. 参加側サービスにコードを挿入して、参加側サービスがDML操作を実行するたびに、注入されたconnectionオブジェクトを使用するようにします。ビジネス・シナリオに基づいて、注入されたconnectionオブジェクトを使用するコードを作成できます。次に、例のコード・スニペットを示します。
    Statement stmt1 = connection.createStatement();
    stmt1.execute(query);
    stmt1.close();

    これらのコード行は、参加側サービスが実行するDML操作ごとに挿入します。DML操作ごとにstmt1stmt2などの新しい文オブジェクトを作成しますが、MicroTxライブラリによって作成された同一のconnectionオブジェクトを使用します。

  10. JAX-RS APIを使用するSpring Bootアプリケーションの場合のみ、次のサンプル・コード・スニペットに示すように、準備、コミット、ロールバックなどのXAResourceコールバックと様々なフィルタを登録します。
    @Component
    public class JerseyConfig extends ResourceConfig
    {
        public JerseyConfig()
        {
            register(XAResourceCallbacks.class);
            register(TrmTransactionResponseFilter.class);
            register(TrmTransactionRequestFilter.class);
            register(new AbstractBinder() {
                @Override
                protected void configure() {
                bindFactory(TrmXAConnectionFactory.class).to(XAConnection.class);
                }
            });
        }
    }

    これは、XAトランザクションに参加するリソース・エンドポイントの登録に加えて行います。

  11. 変更内容を保存します。

6.8.3.4 非XAかつ非JDBCのリソースを使用するJAX-RSアプリケーションの構成

XAもJDBCもサポートしないリソースを使用する場合は、この項に記載されている情報を使用してJAX-RS参加側アプリケーションを構成します。

アプリケーションは、複数のXA準拠リソース・マネージャに接続できます。ただし、トランザクションに参加できるのは1つの非XAリソースのみです。
  1. 開始する前に、MicroTxライブラリのプロパティ値を構成していることを確認してください。ライブラリ・プロパティの構成を参照してください。
    oracle.tmm.xa.XaSupportfalseoracle.tmm.xa.LLRSupportまたはoracle.tmm.xa.LRCSupporttrueに設定されていることを確認します。
    • ロギング・ラスト・リソース(LLR)の最適化を有効にするには、環境変数に次の値を設定します。
      oracle.tmm.xa.XaSupport = false
      oracle.tmm.xa.LLRSupport = true
      oracle.tmm.xa.LRCSupport = false
    • ラスト・リソース・コミット(LRC)の最適化を有効にするには、環境変数に次の値を設定します。
      oracle.tmm.xa.XaSupport = false
      oracle.tmm.xa.LLRSupport = false
      oracle.tmm.xa.LRCSupport = true
  2. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  3. セッション・アフィニティを有効にします。「セッション・アフィニティの有効化」を参照してください。
  4. NonXAResourceインタフェースを実装します。
    public class MongoDbNonXAResource implements NonXAResource {
    // Provide application-specific code for all the methods in the NonXAResource interface.
    }

    NonXAResourceインタフェースの詳細は、Transaction Manager for Microservices Java APIリファレンスを参照してください。

    LRCの最適化を有効にした場合、recover()メソッドをNonXAResourceインタフェースに実装する必要はありません。LRCでは、commit()メソッドがcommitRecordNULLを返すためです。

  5. NonXAResourceインタフェースを実装した後、MicroTxライブラリ・ファイルをインポートし、非XAリソースを生成します。作成した非XAリソースに@NonXa注釈を付けます。MicroTxライブラリは、注釈を付けたオブジェクトを消費します。

    次の例は、MongoDBリソースの実装例を示しています。業務要件に基づいてアプリケーションのコードを作成します。この例で、NonXaResourceFactoryクラスがNonXAResourceを提供します。非XAリソースを生成し、MicroTxライブラリが非XAリソースを消費します。

    package com.oracle.mtm.sample.nonxa;
    
    import oracle.tmm.jta.nonxa.NonXAResource;
    import oracle.tmm.jta.nonxa.NonXa;
    
    import javax.enterprise.inject.Produces;
    import javax.inject.Inject;
    import javax.ws.rs.ext.Provider;
    import java.util.function.Supplier;
    
    @Provider
    public class NonXaResourceFactory implements Supplier<NonXAResource> {
    
        @Inject
        MongoDbNonXAResource nonXAResource;
    
        @Produces    
        @NonXa
        public NonXAResource getNonXAResource() {
            return nonXAResource;
        }
    
      @Override
        public NonXAResource get() {
            return getNonXAResource();
        }
    }
  6. 変更内容を保存します。

6.8.4 トランザクション参加側としてのJPAベースのJavaアプリケーションの構成

この項に記載されている情報を使用して、HibernateまたはEclipseLinkを、HelidonまたはSpring BootアプリケーションのJPAプロバイダとして構成します。

トランザクション参加側としてのJPAベースのアプリケーションの構成は、トランザクション参加側としてのJDBCベースのJavaアプリケーションの構成に似ています。

JDBCベースのJavaアプリケーションをトランザクション参加側として構成するには、カスタム・データ・ソース・オブジェクトを作成し、このオブジェクトをMicroTxライブラリに渡します。Javaアプリケーション・コードで、カスタム・データ・ソースの詳細をTrmSQLConnection接続オブジェクトに注入してから、注入されたオブジェクトを使用するようにアプリケーション・コードを更新します。

JPAベースのJavaアプリケーションをトランザクション参加側として構成するには、カスタム・データ・ソース・オブジェクトを作成し、このオブジェクトをMicroTxライブラリに渡します。アプリケーション・コードで、カスタム・データ・ソースの詳細をTrmEntityManagerオブジェクトに注入してから、注入されたオブジェクトを使用するようにアプリケーション・コードを更新します。

6.8.4.1 XA準拠リソース・マネージャを使用するJPAベースのJavaアプリケーションの構成

XA準拠のリソース・マネージャを使用する場合は、この項に記載されている情報を使用して、XAトランザクションに参加するHelidonまたはSpring BootアプリケーションのJPAプロバイダとしてHibernateまたはEclipseLinkを使用します。

アプリケーションは、複数のXA準拠リソース・マネージャに接続できます。アプリケーションで複数のXA準拠リソース・マネージャを使用している場合は、リソース・マネージャごとに次のステップを実行します。
  1. MicroTxクライアント・ライブラリ・プロパティのプロパティ値を指定します。

    次の例では、プロパティのサンプル値を指定しています。ご自身の環境に基づいて値を指定してください。

    oracle.tmm.TcsConnPoolSize = 15
    oracle.tmm.CallbackUrl = https://bookTicket-app:8081
    oracle.tmm.PropagateTraceHeaders = true
    oracle.tmm.TransactionTimeout = 60000
    oracle.tmm.xa.XaSupport = true

    oracle.tmm.xa.XaSupporttrueに設定されていることを確認します。

    各プロパティおよびその他のオプション・プロパティの詳細は、「ライブラリ・プロパティの構成」を参照してください。

  2. MicroTx Javaライブラリ・ファイルをアプリケーションのpom.xmlファイルにmaven依存関係として含めます。次のサンプル・コードは23.4.2リリース用です。使用するリリース・バージョンに基づいて、正しいバージョンを指定してください。
    • Helidon 2.xなどのJakarta EE8環境では、TmmLibファイルを使用します。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib</artifactId>
           <version>23.4.2</version>
      </dependency>
    • Helidon 3.xおよびSpring Boot 3.xアプリケーションなどのJakarta EE9環境では、TmmLib-jakartaファイルを使用します。Helidon 3.x。

      <dependency>
           <groupId>com.oracle.tmm.jta</groupId>
           <artifactId>TmmLib-jakarta</artifactId>
           <version>23.4.2</version>
      </dependency>
  3. このタスクは、JAX-RS APIを使用するSpring Bootアプリケーションに対してのみ実行します。アプリケーション・コードを含むフォルダに.javaファイルを作成して、XADataSourceConfigオブジェクトを初期化します。XADataSourceConfigクラスには、カスタム・データ・ソース・オブジェクトおよびエンティティ・マネージャ・ファクトリ・オブジェクトを作成するメソッドが含まれています。

    次のコード例は、XADataSourceConfigクラス内のライブラリを初期化し、departmentDataSourceというカスタム・データ・ソースを作成し、emfというエンティティ・マネージャ・ファクトリ・オブジェクトを作成する方法を示しています。ご自身のアプリケーション用に同様のコードを作成できます。

    カスタム・データ・ソース・オブジェクトには、リソース・マネージャに接続するための詳細が含まれています。アプリケーション開発者は、カスタム・データ・ソース・オブジェクトを作成する際に、XA準拠JDBCドライバおよび必要なパラメータを設定する必要があります。

    package com.oracle.mtm.sample;
    
    import oracle.tmm.common.TrmConfig;
    import oracle.tmm.jta.jpa.hibernate.HibernateXADataSourceConnectionProvider;
    import oracle.ucp.jdbc.PoolDataSourceFactory;
    import oracle.ucp.jdbc.PoolXADataSource;
    import org.hibernate.jpa.HibernatePersistenceProvider;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.persistence.EntityManagerFactory;
    import javax.sql.DataSource;
    import java.sql.SQLException;
    import java.util.Properties;
    
    @Configuration
    @EnableTransactionManagement
    public class XADataSourceConfig {
        @Value("${spring.xads.datasource.url}")
        private String url;
        @Value("${spring.xads.datasource.username}")
        private String username;
        @Value("${spring.xads.datasource.password}")
        private String password;
        @Value("${spring.xads.datasource.oracleucp.min-pool-size}")
        private String minPoolSize;
        @Value("${spring.xads.datasource.oracleucp.initial-pool-size:10}")
        private String initialPoolSize;
    
        @Value("${spring.xads.datasource.oracleucp.max-pool-size}")
        private String maxPoolSize;
    
        @Value("${spring.xads.datasource.oracleucp.data-source-name}")
        private String dataSourceName;
    
        @Value("${spring.xads.datasource.oracleucp.connection-pool-name}")
        private String connectionPoolName;
    
        @Value("${spring.xads.datasource.oracleucp.connection-factory-class-name:oracle.jdbc.xa.client.OracleXADataSource}")
        private String connectionFactoryClassName;
        
        //Create a custom data source object. Provide credentials and other details to connect to the resource manager.
        @Bean(name = "departmentDataSource")
        @Primary
        public DataSource getDataSource() {
            DataSource pds = null;
            try {
                pds = PoolDataSourceFactory.getPoolXADataSource();
    
                ((PoolXADataSource) pds).setConnectionFactoryClassName(connectionFactoryClassName);
                ((PoolXADataSource) pds).setURL(url);
                ((PoolXADataSource) pds).setUser(username);
                ((PoolXADataSource) pds).setPassword(password);
                ((PoolXADataSource) pds).setMinPoolSize(Integer.valueOf(minPoolSize));
                ((PoolXADataSource) pds).setInitialPoolSize(10);
                ((PoolXADataSource) pds).setMaxPoolSize(Integer.valueOf(maxPoolSize));
    
                ((PoolXADataSource) pds).setDataSourceName(dataSourceName);
                ((PoolXADataSource) pds).setConnectionPoolName(connectionPoolName);
    
                System.out.println("XADataSourceConfig: XADataSource created");
            } catch (SQLException ex) {
                System.err.println("Error connecting to the database: " + ex.getMessage());
            }
            return pds;
        }
    
        // Create an entity manager factory object
        @Bean(name = "entityManagerFactory")
        public EntityManagerFactory createEntityManagerFactory() throws SQLException {
            LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    
            entityManagerFactoryBean.setDataSource(getDataSource());
            entityManagerFactoryBean.setPackagesToScan(new String[] { "com.oracle.mtm.sample.entity" });
            entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    
            entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
            entityManagerFactoryBean.setPersistenceUnitName("mydeptxads");
            Properties properties = new Properties();
            properties.setProperty( "javax.persistence.transactionType", "RESOURCE_LOCAL"); // change this to resource_local
            properties.put("hibernate.show_sql", "true");
            properties.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
            properties.put("hibernate.format_sql", "true");
            properties.put("hbm2ddl.auto", "validate");
            properties.put("hibernate.connection.provider_class", "oracle.tmm.jta.jpa.hibernate.HibernateXADataSourceConnectionProvider");
            entityManagerFactoryBean.setJpaProperties(properties);
            entityManagerFactoryBean.afterPropertiesSet();
            EntityManagerFactory emf = (EntityManagerFactory) entityManagerFactoryBean.getObject();
            System.out.println("entityManagerFactory = " + emf);
            // Pass the entity manager factory object to the MicroTx Library
    
            // If you are using a single resource manager with your application, 
            //pass the entity manager factory object to the MicroTx library in the following way.
            TrmConfig.initEntityManagerFactory(emf);
            // If you are using multiple resource managers with your application,
            // pass the entity manager factory object to the MicroTx library in the following way. 
            TrmConfig.initEntityManagerFactory(emf, departmentDataSource, ORCL1-8976-9776-9873);
    
            return emf;
        }
    }

    エンティティ・マネージャ・ファクトリ・オブジェクトを初期化するには、アプリケーションが1つのリソース・マネージャまたは複数のリソース・マネージャに接続するかに応じて、必要なパラメータをTrmConfig.initEntityManagerFactory()に渡します。

    • アプリケーションが1つのリソース・マネージャに接続する場合は、エンティティ・マネージャ・ファクトリ・オブジェクトを作成し、それをMicroTxライブラリに渡します。次のサンプル・コードで、emfはエンティティ・マネージャ・ファクトリ・オブジェクトの名前です。

      TrmConfig.initEntityManagerFactory(emf);
    • アプリケーションが複数のリソース・マネージャに接続する場合は、TrmConfig.initEntityManagerFactory()をコールするときに次のパラメータを渡す必要があります。

      TrmConfig.initEntityManagerFactory(emf, departmentDataSource, ORCL1-8976-9776-9873);

      説明

      • emfは、作成したエンティティ・マネージャ・ファクトリ・オブジェクトです。これをMicroTxライブラリに渡します。
      • departmentDataSourceは、前述のサンプル・コードでTrmConfig.initEntityManagerFactory()をコールする前に作成したデータ・ソースの名前です。
      • ORCL1-8976-9776-9873は、リソース・マネージャID (RMID)です。
  4. JAX-RS APIを使用するSpring Bootアプリケーションの場合のみ、XAトランザクションに参加するリソース・エンドポイントを登録した後で次のタスクを実行します。
    1. 次のサンプル・コード・スニペットに示すように、準備、コミット、ロールバックのために、フィルタとXAResourceCallbacksを登録します。

      @Component
      public class Configuration extends ResourceConfig
      {
          public Configuration()
          {
              // Register the MicroTx XA resource callback which
              // coordinates with the transaction coordinator
              register(XAResourceCallbacks.class);
              // Register the filters for the MicroTx libraries that 
              // intercept the JAX_RS calls and manage the XA transactions
              register(TrmTransactionResponseFilter.class);
              register(TrmTransactionRequestFilter.class);
              
              // Bind the connection
              ...
          }
      }
    2. 複数のリソース・マネージャを使用している場合は、このステップをスキップします。Spring Bootアプリケーションで1つのリソース・マネージャを使用している場合は、TrmEntityManagerオブジェクトをEntityManagerにバインドします。後で、TrmEntityManager オブジェクトをアプリケーション・コードで使用します。これによってMicroTxが接続を処理します。

      @Component
      public class Configuration extends ResourceConfig
      {
          public Configuration()
          {
              // Register the filters as shown in the previous step
              ....
              // Bind the connection
              register(new AbstractBinder() {
                  @Override
                  protected void configure() {
                      //Bind the TrmEntityManager object to an EntityManager object
                      bindFactory(TrmEntityManagerFactory.class).to(EntityManager.class);
                  }
              });
          }
      }
    3. 1つのリソース・マネージャを使用している場合は、このステップをスキップします。複数のリソース・マネージャを使用している場合は、リソース・マネージャごとにBeanを初期化します。次のサンプル・コード・スニペットでは、2つのBean (アプリケーションが使用するリソース・マネージャごとに1つ)を初期化する方法を示しています。次のコード・サンプルで、departmentDataSourceおよびcreditDataSourceは、アプリケーションのYAMLファイルで指定したXAデータ・ソースの名前です。後で@Inject注釈を使用して参加側アプリケーションでこれらの接続が使用されることを確認するため、データ・ソースの名前を書き留めておきます。
      @Component
      public class Configuration extends ResourceConfig
      {
          public Configuration()
          {
              // Register the filters as shown in the previous step
              ....
          // Initialize a bean for every resource manager that you want to use with your app
          @Bean
          @TrmEntityManager(name = "departmentDataSource")
          @Lazy
          @RequestScope
          public EntityManager departmentDSSqlConnectionBean() throws SQLException {
              return new TrmEntityManagerFactory().getEntityManagerByName("departmentDataSource");
          }
      
          @Bean
          @TrmEntityManager(name = "creditDataSource")
          @Lazy
          @RequestScope
          public EntityManager creditDSSqlConnectionBean() throws SQLException {
              return new TrmConnectionFactory().getConnection("creditDataSource");
          }
          }
      }
  5. アプリケーション・コードを含むフォルダに.javaファイルを作成して、PoolXADataSourceオブジェクトを初期化します。PoolXADataSourceクラスには、カスタム・データ・ソース・オブジェクトおよびエンティティ・マネージャ・ファクトリ・オブジェクトを作成するメソッドが含まれています。

    次のコード例は、PoolXADataSourceクラス内のライブラリを初期化し、departmentDataSourceというカスタム・データ・ソースを作成し、エンティティ・マネージャ・ファクトリ・オブジェクトを作成する方法を示しています。ご自身のアプリケーションで同様のコードを作成できます。

    カスタム・データ・ソース・オブジェクトには、リソース・マネージャに接続するための詳細が含まれています。アプリケーション開発者は、カスタム・データ・ソース・オブジェクトを作成する際に、XA準拠JDBCドライバおよび必要なパラメータを設定する必要があります。

    package com.oracle.mtm.sample;
    ​
    import oracle.tmm.common.TrmConfig;
    import oracle.ucp.jdbc.PoolDataSourceFactory;
    import oracle.ucp.jdbc.PoolXADataSource;
    import org.eclipse.microprofile.config.inject.ConfigProperty;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    ​
    import javax.enterprise.context.ApplicationScoped;
    import javax.enterprise.context.Initialized;
    import javax.enterprise.event.Observes;
    import javax.enterprise.inject.Produces;
    import javax.inject.Inject;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import java.lang.invoke.MethodHandles;
    import java.sql.SQLException;
    import java.util.HashMap;
    import java.util.Map;
    ​
    @ApplicationScoped
    public class Configuration {
    ​
        private PoolXADataSource dataSource;
        final static Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
    ​
        private EntityManagerFactory entityManagerFactory;
    ​
        @Inject
        @ConfigProperty(name = "departmentDataSource.url")
        String url;
        @Inject
        @ConfigProperty(name = "departmentDataSource.user")
        String user;
        @Inject
        @ConfigProperty(name = "departmentDataSource.password")
        String password;
    ​
    ​
        private void init(@Observes @Initialized(ApplicationScoped.class) Object event) {
            initialiseDataSource();
            createEntityManagerFactory();
        }
    ​
        /**
         * Initializes the datasource into the MicroTx library that manages the lifecycle of the XA transaction
         *
         */
        private void initialiseDataSource() {
            try {
                this.dataSource = PoolDataSourceFactory.getPoolXADataSource();
                this.dataSource.setURL(url);
                this.dataSource.setUser(user);
                this.dataSource.setPassword(password);
                this.dataSource.setConnectionFactoryClassName("oracle.jdbc.xa.client.OracleXADataSource");
                this.dataSource.setMaxPoolSize(15);
            } catch (SQLException e) {
                logger.error("Failed to initialise database");
            }
        }
    ​
        public PoolXADataSource getDatasource() {
            return dataSource;
        }
    ​
        public void createEntityManagerFactory(){
            Map<String, Object> props = new HashMap<String, Object>();
    ​
            props.put("hibernate.connection.datasource", getDatasource());
            props.put("hibernate.show_sql", "true");
            props.put("hibernate.dialect", "org.hibernate.dialect.Oracle12cDialect");
            props.put("hibernate.hbm2ddl.auto", "none");
            props.put("hibernate.format_sql", "true");
            props.put("hibernate.connection.provider_class", "oracle.tmm.jta.jpa.hibernate.HibernateXADataSourceConnectionProvider");
            props.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
            props.put("javax.persistence.jdbc.driver", "oracle.jdbc.OracleDriver");
            props.put("javax.persistence.jdbc.url", url);
            props.put("javax.persistence.jdbc.user", user);
            props.put("javax.persistence.jdbc.password", password);
    ​
            this.entityManagerFactory = Persistence.createEntityManagerFactory("mydeptxads", props);
    ​        
            //Initialize the MicroTx Library
    
            // If you are using a single resource manager with your application, 
            //pass the entity manager factory object to the MicroTx library in the following way.
            TrmConfig.initEntityManagerFactory(this.entityManagerFactory); 
            
            //If you are using multiple resource managers with your application,
            //set the setRAC property if you are using an Oracle RAC Database
            departmentDataSource.setRAC(true);
    
            //If you are using multiple resource managers with your application,
            //pass the entity manager factory object to the MicroTx library in the following way. 
            TrmConfig.initEntityManagerFactory(this.entityManagerFactory, departmentDataSource, ORCL1-8976-9776-9873);
        }
    ​
        public EntityManagerFactory getEntityManagerFactory() {
            return this.entityManagerFactory;
        }
    ​
        public Logger getLogger() {
            return logger;
        }
    ​
        /**
         * EntityManager bean for non-distributed database operations.
         */
        @Produces
        public EntityManager getEntityManager() {
            EntityManager entityManager = null;
            try {
                entityManager = this.getEntityManagerFactory().createEntityManager();
            } catch (RuntimeException e){
                e.printStackTrace();
                logger.error("Entity manager bean for local transactions creation failed!");
            }
            return entityManager;
        }
    }

    エンティティ・マネージャ・ファクトリ・オブジェクトを初期化するには、アプリケーションが1つのリソース・マネージャまたは複数のリソース・マネージャに接続するかに応じて、必要なパラメータをTrmConfig.initEntityManagerFactory()に渡します。

    • アプリケーションが1つのリソース・マネージャに接続する場合は、エンティティ・マネージャ・ファクトリ・オブジェクトを作成し、それをMicroTxライブラリに渡します。

      TrmConfig.initEntityManagerFactory(this.entityManagerFactory);
    • アプリケーションが複数のリソース・マネージャに接続する場合は、TrmConfig.initEntityManagerFactory()をコールするときに次のパラメータを渡す必要があります。

      TrmConfig.initEntityManagerFactory(this.entityManagerFactory, departmentDataSource, ORCL1-8976-9776-9873);

      説明

      • departmentDataSourceは、前述のサンプル・コードでTrmConfig.initEntityManagerFactory()をコールする前に作成したデータ・ソースの名前です。
      • ORCL1-8976-9776-9873は、リソース・マネージャID (RMID)です。

    複数のリソース・マネージャを使用している場合は、Oracle RACデータベースを使用するデータ・ソースにdepartmentDataSource.setRAC(true)を設定する必要があります。

  6. 参加側サービスのコードに次の行を挿入して、アプリケーションがMicroTxクライアント・ライブラリによって渡された接続を使用するようにします。参加側アプリケーションの次のコードは、MicroTxクライアント・ライブラリによって作成されたconnectionオブジェクトを注入します。
    • 1つのアプリケーションで1つのリソース・マネージャを使用する場合は、次のコード・サンプルに示すようにEntityManagerオブジェクトを注入します。

      @Inject
      @TrmEntityManager 
      private EntityManager emf;
    • アプリケーションで複数のリソース・マネージャを使用する場合は、次のコード・サンプルに示すようにリソース・マネージャごとにEntityManagerオブジェクトを注入します。

      @Inject
      @TrmEntityManager(name = "departmentDataSource")
      private EntityManager emf;
      
      @Inject
      @TrmEntityManager(name = "creditDataSource")
      private EntityManager emf;

      ここで、emfはエンティティ・マネージャ・ファクトリ・オブジェクト、departmentDataSourceおよびcreditDataSourceは前のステップで作成したデータ・ソース・オブジェクトです。前のコード・サンプルは、departmentDataSourceの詳細を示しています。同様の方法で、creditDataSourceなどの他のリソース・マネージャの情報を指定します。

  7. アプリケーション・コードで、MicroTxライブラリに渡したエンティティ・マネージャ・オブジェクトを注入します。ビジネス・ロジックに基づいてアプリケーション・コード内でエンティティ・マネージャ・オブジェクトを使用し、このオブジェクトを使用してデータベースに接続します。

    次のコード例は、エンティティ・マネージャ・オブジェクトの注入および使用の方法を示しています

    @POST
        @Path("{accountId}/withdraw")
        public Response withdraw(@PathParam("accountId") String accountId, @QueryParam("amount") double amount, @Context EntityManager entityManager) {
        // Application code or business logic
            if(amount == 0){
                return Response.status(422,"Amount must be greater than zero").build();
            }
            try {
                if (this.accountService.getBalance(accountId, entityManager) < amount) {
                    return Response.status(422, "Insufficient balance in the account").build();
                }
                if(this.accountService.withdraw(accountId, amount, entityManager)) {
                    config.getLogger().log(Level.INFO, amount + " withdrawn from account: " + accountId);
                    return Response.ok("Amount withdrawn from the account").build();
                }
            } catch (SQLException | IllegalArgumentException e) {
                config.getLogger().log(Level.SEVERE, e.getLocalizedMessage());
                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
            }
            return Response.serverError().entity("Withdraw failed").build();
        }
  8. 変更内容を保存します。
複数のトランザクション参加側サービスがある場合は、すべての参加側サービスでこれらのステップを完了します。