1. 序章

Atomikos は、Javaアプリケーション用のトランザクションライブラリです。 このチュートリアルでは、Atomikosを使用する理由と方法を理解します。

その過程で、トランザクションの基本と、トランザクションが必要な理由についても説明します。

次に、AtomikosのさまざまなAPIを利用するトランザクションを使用して単純なアプリケーションを作成します。

2. 基本を理解する

Atomikosについて説明する前に、トランザクションとは何か、およびトランザクションに関連するいくつかの概念を理解しましょう。 簡単に言うと、トランザクションは論理的な作業単位であり、その効果はトランザクションの外部で完全に表示されるか、まったく表示されません

これをよりよく理解するために例を見てみましょう。 一般的な小売アプリケーションは、在庫を予約してから注文します。

ここでは、これら2つの操作を同時に実行するか、まったく実行しないようにします。 これらの操作を単一のトランザクションにラップすることで、これを実現できます。

2.1. ローカル対。 分散トランザクション

トランザクションには、複数の独立した操作が含まれる場合があります。 これらの操作は、同じリソースまたは異なるリソースで実行できます。 ここでは、データベースなどのトランザクションに参加しているコンポーネントをリソースと呼びます。

単一のリソース内のトランザクションはローカルトランザクションと呼ばれ、複数のリソースにまたがって生成されるトランザクションは分散トランザクションと呼ばれます。

ここで、在庫と注文は、同じデータベース内の2つのテーブルにすることも、2つの異なるデータベースにすることもできます。場合によっては、まったく異なるマシンで実行することもできます。

2.2. XA仕様とJavaトランザクションAPI

XAは、分散トランザクション処理の仕様である eXtendedArchitectureを指します。 XAの目標は、異種コンポーネントを含むグローバルトランザクションで原子性を提供することです。

XA仕様は、2フェーズコミットと呼ばれるプロトコルを通じて整合性を提供します。 2フェーズコミットは、分散トランザクションをコミットするかロールバックするかの決定を容易にするために広く使用されている分散アルゴリズムです。

Java Transaction API(JTA)は、JavaCommunityProcessの下で開発されたJavaEnterpriseEditionAPIです。 JavaアプリケーションとアプリケーションサーバーがXAリソース全体で分散トランザクションを実行できるようにします。

JTAは、2フェーズコミットを活用してXAアーキテクチャをモデルにしています。 JTAは、トランザクションマネージャと分散トランザクションの他の関係者との間の標準Javaインターフェイスを指定します。

3. アトミコス入門

トランザクションの基本を終えたので、Atomikosを学ぶ準備ができました。 このセクションでは、Atomikosとは何か、XAやJTAなどの概念とどのように関連しているかを理解します。 また、Atomikosのアーキテクチャを理解し、その製品の提供について説明します。

3.1. アトミコスとは

これまで見てきたように、JTAは分散トランザクションを使用してアプリケーションを構築するためのJavaのインターフェースを提供します。 現在、JTAは単なる仕様であり、実装を提供していません。 私たちがJTAを活用するアプリケーションを実行するには、JTAの実装が必要です。 このような実装は、トランザクションマネージャーと呼ばれます。

通常、アプリケーションサーバーはトランザクションマネージャーのデフォルトの実装を提供します。 たとえば、Enterprise Java Beans(EJB)の場合、EJBコンテナは、アプリケーション開発者による明示的な介入なしにトランザクションの動作を管理します。 ただし、多くの場合、これは理想的ではない可能性があり、アプリケーションサーバーから独立してトランザクションを直接制御する必要がある場合があります。

Atomikosは、Java 用の軽量トランザクションマネージャーであり、分散トランザクションを使用するアプリケーションを自己完結型にすることができます。 基本的に、私たちのアプリケーションは、トランザクションのためにアプリケーションサーバーのような重いコンポーネントに依存する必要はありません。 これにより、分散トランザクションの概念がクラウドネイティブアーキテクチャに近づきます。

3.2. アトミコスアーキテクチャ

Atomikosは主にJTAトランザクションマネージャーとして構築されているため、は2フェーズコミットプロトコルを使用してXAアーキテクチャを実装します。 Atomikosを使用した高レベルのアーキテクチャを見てみましょう。

ここで、Atomikosは、データベースとメッセージキューにまたがる2フェーズコミットベースのトランザクションを促進しています。

3.3. Atomikos製品の提供

Atomikosは、JTA/XAが要求するよりも多くの機能を提供する分散トランザクションマネージャーです。 オープンソース製品とはるかに包括的な商用製品があります。

  • TransactionsEssentials:データベースとメッセージキューを操作するJavaアプリケーション用のJTA/XAトランザクションマネージャーを提供するAtomikosのオープンソース製品。 これは主に、テストと評価の目的で役立ちます。
  • ExtremeTransactions: Atomikosの商用製品であり、複合アプリケーション全体に分散トランザクションを提供します。データベースやメッセージキュー以外のRESTサービスも含まれます。 これは、Extreme Transaction Processing(XTP)を実行するアプリケーションを構築するのに役立ちます。

このチュートリアルでは、TransactionsEssentialsライブラリを使用して、Atomikosの機能を構築およびデモンストレーションします。

4. Atomikosのセットアップ

前に見たように、Atomikosのハイライトの1つは、組み込みトランザクションサービスであるということです。 これが意味するのは、アプリケーションと同じJVMで実行できるということです。 したがって、Atomikosの設定は非常に簡単です。

4.1. 依存関係

まず、依存関係を設定する必要があります。 ここで行う必要があるのは、Maven pom.xmlファイルで依存関係を宣言することだけです。

<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jdbc</artifactId>
    <version>5.0.6</version>
</dependency>
<dependency>
    <groupId>com.atomikos</groupId>
    <artifactId>transactions-jms</artifactId>
    <version>5.0.6</version>
</dependency>

この場合、JDBCJMSにAtomikos依存関係を使用していますが、他のXA苦情リソースについても同様の依存関係をMavenCentralで利用できます。

4.2. 構成

Atomikosはいくつかの構成パラメーターを提供し、それぞれに適切なデフォルトがあります。 これらのパラメータを上書きする最も簡単な方法は、クラスパスにtransactions.propertiesファイルを提供することです。 トランザクションサービスの初期化と操作のためにいくつかのパラメータを追加できます。 ログファイルが作成されるディレクトリを上書きする簡単な構成を見てみましょう。

com.atomikos.icatch.file=path_to_your_file

同様に、トランザクションのタイムアウトを制御したり、アプリケーションに一意の名前を設定したり、シャットダウン動作を定義したりするために使用できる他のパラメーターがあります。

4.3. データベース

このチュートリアルでは、前に説明したような単純な小売アプリケーションを作成します。このアプリケーションは、在庫を予約してから注文します。 簡単にするために、リレーショナルデータベースを使用します。 さらに、複数のデータベースを使用して分散トランザクションを示します。 ただし、これは、メッセージキューやトピックなどの他のXAクレームリソースに非常によく拡張できます。

在庫データベースには、製品の在庫をホストするための簡単なテーブルがあります。

CREATE TABLE INVENTORY (
    productId VARCHAR PRIMARY KEY,
    balance INT
);

また、注文データベースには、発注された注文をホストするための単純なテーブルがあります。

CREATE TABLE ORDERS (
    orderId VARCHAR PRIMARY KEY,
    productId VARCHAR,
    amount INT NOT NULL CHECK (amount <= 5)
);

これは非常に基本的なデータベーススキーマであり、デモンストレーションにのみ役立ちます。 ただし、スキーマの制約により、製品の数量が5を超える注文は許可されないことに注意してください。

5. Atomikosでの作業

これで、Atomikosライブラリの1つを使用して、分散トランザクションでアプリケーションを構築する準備が整いました。 次のサブセクションでは、組み込みのAtomikosリソースアダプターを使用して、バックエンドデータベースシステムに接続します。 これは、Atomikosを開始するための最も速くて簡単な方法です。

5.1. UserTransactionのインスタンス化

JTA UserTransaction を活用して、トランザクションの境界を定めます。 トランザクションサービスに関連するすべてのその他の手順は自動的に処理されます。 これには、トランザクションサービスへのリソースの参加と除外が含まれます。

まず、AtomikosからUserTransactionをインスタンス化する必要があります。

UserTransactionImp utx = new UserTransactionImp();

5.2. DataSourceのインスタンス化

次に、AtomikosからDataSourceをインスタンス化する必要があります。 Atomikosが提供するDataSourceの2つのバージョンがあります。

最初のAtomikosDataSourceBeanは、基になるXADataSourceを認識しています。

AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();

AtomikosNonXADataSourceBean は通常のJDBCドライバークラスを使用しますが、次のようになります。

AtomikosNonXADataSourceBean dataSource = new AtomikosNonXADataSourceBean();

名前が示すように、AtomikosNonXADataSourceはXAに準拠していません。 したがって、そのようなデータソースで実行されるトランザクションは、アトミックであることが保証されません。 では、なぜこれを使用するのでしょうか。 XA仕様をサポートしていないデータベースがある可能性があります。 Atomikosは、そのようなデータソースの使用を禁止しておらず、トランザクションにそのようなデータソースが1つある場合でも、アトミック性を提供しようとします。 この手法は、2フェーズコミットプロセスのバリエーションであるLastResourceGambitに似ています。

さらに、データベースとドライバーに応じて、DataSourceを適切に構成する必要があります。

5.3. データベース操作の実行

構成が完了すると、アプリケーションのトランザクションのコンテキスト内でDataSourceを使用するのはかなり簡単です。

public void placeOrder(String productId, int amount) throws Exception {
    String orderId = UUID.randomUUID().toString();
    boolean rollback = false;
    try {
        utx.begin();
        Connection inventoryConnection = inventoryDataSource.getConnection();
        Connection orderConnection = orderDataSource.getConnection();
        
        Statement s1 = inventoryConnection.createStatement();
        String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" +
          productId + "'";
        s1.executeUpdate(q1);
        s1.close();
        
        Statement s2 = orderConnection.createStatement();
        String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )";
        s2.executeUpdate(q2);
        s2.close();
        
        inventoryConnection.close();
        orderConnection.close();
    } catch (Exception e) {
        rollback = true;
    } finally {
        if (!rollback)
            utx.commit();
        else
            utx.rollback();
    }
}

ここでは、トランザクション境界内の在庫と注文のデータベーステーブルを更新しています。 これにより、これらの操作がアトミックに行われるという利点が自動的に提供されます。

5.4. トランザクション動作のテスト

最後に、トランザクションの動作が期待どおりであることを検証するために、単純な単体テストでアプリケーションをテストできる必要があります。

@Test
public void testPlaceOrderSuccess() throws Exception {
    int amount = 1;
    long initialBalance = getBalance(inventoryDataSource, productId);
    Application application = new Application(inventoryDataSource, orderDataSource);
    
    application.placeOrder(productId, amount);
    
    long finalBalance = getBalance(inventoryDataSource, productId);
    assertEquals(initialBalance - amount, finalBalance);
}
  
@Test
public void testPlaceOrderFailure() throws Exception {
    int amount = 10;
    long initialBalance = getBalance(inventoryDataSource, productId);
    Application application = new Application(inventoryDataSource, orderDataSource);
    
    application.placeOrder(productId, amount);
    
    long finalBalance = getBalance(inventoryDataSource, productId);
    assertEquals(initialBalance, finalBalance);
}

ここでは、有効な注文で在庫が減少することを期待していますが、無効な注文で在庫が変更されないことを期待しています。 データベースの制約により、商品の数量が5を超える注文は、無効な注文と見なされることに注意してください。

5.5. 高度なAtomikosの使用法

上記の例は、Atomikosを使用する最も簡単な方法であり、おそらくほとんどの要件に十分対応できます。 ただし、Atomikosを使用してアプリケーションを構築する方法は他にもあります。 これらのオプションのいくつかはAtomikosを使いやすくしますが、他のオプションはより柔軟性を提供します。 選択は、要件によって異なります。

もちろん、JDBC /JMS用のAtomikosアダプターを常に使用する必要はありません XAResource を直接操作しながら、Atomikosトランザクションマネージャーを使用することを選択できます。 ただし、その場合、トランザクションサービスでXAResourceインスタンスの登録と除外を明示的に処理する必要があります。

Atomikosは、独自のインターフェースであるUserTransactionServiceを介してより高度な機能を使用することも可能にします。 このインターフェイスを使用して、リカバリ用のリソースを明示的に登録できます。 これにより、どのリソースを回復するか、どのように回復するか、いつ回復するかをきめ細かく制御できます。

6. アトミコスの統合

Atomikosは分散トランザクションの優れたサポートを提供しますが、そのような低レベルのAPIを使用することが常に便利であるとは限りません。 ビジネスドメインに焦点を合わせ、ボイラープレートコードの乱雑さを回避するために、さまざまなフレームワークとライブラリのサポートが必要になることがよくあります。 Atomikosは、バックエンド統合に関連する一般的なJavaフレームワークのほとんどをサポートしています。 ここでは、それらのいくつかについて説明します。

6.1. SpringおよびDataSourceを使用したAtomikos

Springは、制御の反転(IoC)コンテナを提供するJavaで人気のあるフレームワークの1つです。 特に、トランザクションも素晴らしいサポートがあります。 アスペクト指向プログラミング(AOP)技術を使用した宣言型トランザクション管理を提供します。

Springは、分散トランザクション用のJTAを含むいくつかのトランザクションAPIをサポートしています。 AtomikosをSpring内のJTAトランザクションマネージャーとして、それほど労力をかけずに使用できます。 最も重要なことは、Springのおかげで、アプリケーションがAtomikosにほとんど依存しないことです。

今回はSpringを活用して、以前の問題をどのように解決できるかを見てみましょう。 まず、Applicationクラスを書き直します。

public class Application {
    private DataSource inventoryDataSource;
    private DataSource orderDataSource;
    
    public Application(DataSource inventoryDataSource, DataSource orderDataSource) {
        this.inventoryDataSource = inventoryDataSource;
        this.orderDataSource = orderDataSource;
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void placeOrder(String productId, int amount) throws Exception {
        String orderId = UUID.randomUUID().toString();
        Connection inventoryConnection = inventoryDataSource.getConnection();
        Connection orderConnection = orderDataSource.getConnection();
        
        Statement s1 = inventoryConnection.createStatement();
        String q1 = "update Inventory set balance = balance - " + amount + " where productId ='" + 
          productId + "'";
        s1.executeUpdate(q1);
        s1.close();
        
        Statement s2 = orderConnection.createStatement();
        String q2 = "insert into Orders values ( '" + orderId + "', '" + productId + "', " + amount + " )";
        s2.executeUpdate(q2);
        s2.close();
        
        inventoryConnection.close();
        orderConnection.close();
    }
}

ここでわかるように、トランザクション関連のボイラープレートコードのほとんどは、メソッドレベルで単一のアノテーションに置き換えられています。 さらに、Springは、アプリケーションが依存する DataSource、のインスタンス化と注入を処理します。

もちろん、Springに関連する構成を提供する必要があります。 単純なJavaクラスを使用して、これらの要素を構成できます。

@Configuration
@EnableTransactionManagement
public class Config {
    @Bean(initMethod = "init", destroyMethod = "close")
    public AtomikosDataSourceBean inventoryDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        // Configure database holding order data
        return dataSource;
    }
    
    @Bean(initMethod = "init", destroyMethod = "close")
    public AtomikosDataSourceBean orderDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        // Configure database holding order data
        return dataSource;
    }
    
    @Bean(initMethod = "init", destroyMethod = "close")
    public UserTransactionManager userTransactionManager() throws SystemException {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setTransactionTimeout(300);
        userTransactionManager.setForceShutdown(true);
        return userTransactionManager;
    }
    
    @Bean
    public JtaTransactionManager jtaTransactionManager() throws SystemException {
        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
        jtaTransactionManager.setTransactionManager(userTransactionManager());
        jtaTransactionManager.setUserTransaction(userTransactionManager());
        return jtaTransactionManager;
    }
    
    @Bean
    public Application application() {
        return new Application(inventoryDataSource(), orderDataSource());
    }
}

ここでは、在庫データと注文データを保持する2つの異なるデータベース用にAtomikosDataSourceBeanを構成しています。 さらに、JTAトランザクションマネージャーに必要な構成も提供しています。

これで、以前と同じようにアプリケーションのトランザクション動作をテストできます。 繰り返しになりますが、有効な注文によって在庫残高が減少し、無効な注文によって変更されないことを検証する必要があります。

6.2. Atomikos With Spring、JPA、およびHibernate

Springはボイラープレートコードをある程度削減するのに役立ちましたが、それでもかなり冗長です。 一部のツールを使用すると、Javaでのリレーショナルデータベースの操作がさらに簡単になります。 Java Persistence API(JPA)は、Javaアプリケーションでのリレーショナルデータの管理を説明する仕様です。 これにより、データアクセスと操作コードが大幅に簡素化されます。

Hibernateは、JPA仕様の最も一般的な実装の1つです。 Atomikosは、Hibernateを含むいくつかのJPA実装を強力にサポートしています。 以前と同様に、SpringとJPAのおかげで、アプリケーションはAtomikosとHibernateに依存しません。

Spring、JPA、およびHibernateが、Atomikos を介した分散トランザクションの利点を提供しながら、アプリケーションをさらに簡潔にする方法を見てみましょう。 前と同じように、Applicationクラスを書き直すことから始めます。

public class Application {
    @Autowired
    private InventoryRepository inventoryRepository;
    @Autowired
    private OrderRepository orderRepository;
    
    @Transactional(rollbackFor = Exception.class)
    public void placeOrder(String productId, int amount) throws SQLException { 
        String orderId = UUID.randomUUID().toString();
        Inventory inventory = inventoryRepository.findOne(productId);
        inventory.setBalance(inventory.getBalance() - amount);
        inventoryRepository.save(inventory);
        Order order = new Order();
        order.setOrderId(orderId);
        order.setProductId(productId);
        order.setAmount(new Long(amount));
        orderRepository.save(order);
    }
}

ご覧のとおり、現在、低レベルのデータベースAPIは扱っていません。 ただし、この魔法を機能させるには、SpringDataJPAのクラスと構成を構成する必要があります。 まず、ドメインエンティティを定義します。

@Entity
@Table(name = "INVENTORY")
public class Inventory {
    @Id
    private String productId;
    private Long balance;
    // Getters and Setters
}
@Entity
@Table(name = "ORDERS")
public class Order {
    @Id
    private String orderId;
    private String productId;
    @Max(5)
    private Long amount;
    // Getters and Setters
}

次に、これらのエンティティのリポジトリを提供する必要があります。

@Repository
public interface InventoryRepository extends JpaRepository<Inventory, String> {
}
  
@Repository
public interface OrderRepository extends JpaRepository<Order, String> {
}

これらは非常に単純なインターフェースであり、Spring Dataは、データベースエンティティを操作するために、実際のコードを使用してこれらを作成します。

最後に、在庫データベースと注文データベースの両方のデータソースとトランザクションマネージャーに関連する構成を提供する必要があります。

@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.inventory",
  entityManagerFactoryRef = "inventoryEntityManager", transactionManagerRef = "transactionManager")
public class InventoryConfig {
    @Bean(initMethod = "init", destroyMethod = "close")
    public AtomikosDataSourceBean inventoryDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        // Configure the data source
        return dataSource;
    }
    
    @Bean
    public EntityManagerFactory inventoryEntityManager() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        // Configure the entity manager factory
        return factory.getObject();
    }
}
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.atomikos.spring.jpa.order", 
  entityManagerFactoryRef = "orderEntityManager", transactionManagerRef = "transactionManager")
public class OrderConfig {
    @Bean(initMethod = "init", destroyMethod = "close")
    public AtomikosDataSourceBean orderDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        // Configure the data source
        return dataSource;
    }
    
    @Bean
    public EntityManagerFactory orderEntityManager() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        // Configure the entity manager factory
        return factory.getObject();
    }
}
@Configuration
@EnableTransactionManagement
public class Config {
    @Bean(initMethod = "init", destroyMethod = "close")
    public UserTransactionManager userTransactionManager() throws SystemException {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setTransactionTimeout(300);
        userTransactionManager.setForceShutdown(true);
        return userTransactionManager;
    }
    
    @Bean
    public JtaTransactionManager transactionManager() throws SystemException {
        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
        jtaTransactionManager.setTransactionManager(userTransactionManager());
        jtaTransactionManager.setUserTransaction(userTransactionManager());
        return jtaTransactionManager;
    }
    
    @Bean
    public Application application() {
        return new Application();
    }
}

これはまだ私たちがしなければならないかなり多くの構成です。 これは、2つの別々のデータベース用にSpringJPAを構成していることが一因です。 また、 Spring Boot を使用してこれらの構成をさらに減らすこともできますが、それはこのチュートリアルの範囲を超えています。

以前と同様に、同じトランザクション動作についてアプリケーションをテストできます。 今回は、HibernateでSpring Data JPAを使用していることを除いて、新しいことは何もありません。

7. JTAを超えたアトミコス

JTAは分散システムに優れたトランザクションサポートを提供しますが、これらのシステムは、ほとんどのリレーショナルデータベースやメッセージキューと同様にXAに準拠している必要があります。 ただし、これらのシステムの1つが2フェーズコミットプロトコルのXA仕様をサポートしていない場合、JTAは役に立ちません。 特にマイクロサービスアーキテクチャ内では、いくつかのリソースがこのカテゴリに分類されます。

いくつかの代替プロトコルは分散トランザクションをサポートします。 これらの1つは、補正を利用する2フェーズコミットプロトコルのバリエーションです。 このようなトランザクションには、緩和された分離保証があり、報酬ベースのトランザクションとして知られています。 参加者は、第1フェーズ自体でトランザクションの個々の部分をコミットし、第2フェーズでのロールバックの可能性に対する補償ハンドラーを提供します。

報酬ベースのトランザクションを実装するためのいくつかのデザインパターンとアルゴリズムがあります。 たとえば、Sagasはそのような人気のあるデザインパターンの1つです。 ただし、これらは通常、実装が複雑でエラーが発生しやすくなります。

Atomikosは、Try-Confirm / Cancel(TCC)と呼ばれる報酬ベースのトランザクションのバリエーションを提供します。 TCCは、トランザクションの下のエンティティにより良いビジネスセマンティクスを提供します。 ただし、これは参加者からの高度なアーキテクチャサポートによってのみ可能であり、TCCはAtomikosの商用製品であるExtremeTransactionsでのみ利用できます。

8. アトミコスの代替品

私たちは、アトミコスが提供するものを理解するのに十分な数のアトミコスを経験しました。 さらに、さらに強力な機能を備えたAtomikosの商用製品があります。 ただし、JTAトランザクションマネージャーの選択に関しては、Atomikosだけが選択肢ではありません。 選択できる他のいくつかの信頼できるオプションがあります。 彼らがアトミコスとどのように戦うか見てみましょう。

8.1. ナラヤナ

Narayana おそらく最も古いオープンソースの分散トランザクションマネージャーの1つであり、現在RedHatによって管理されています。 業界全体で広く使用されており、コミュニティのサポートを通じて進化し、いくつかの仕様や規格に影響を与えてきました。

Narayanaは、いくつか例を挙げると、JTA、JTS、Webサービス、RESTなどの幅広いトランザクションプロトコルをサポートしています。 さらに、ナラヤナはさまざまな容器に埋め込むことができます。

Atomikosと比較すると、Narayanaは分散トランザクションマネージャーのほとんどすべての機能を提供します。 多くの場合、Narayanaは、アプリケーションに統合して使用するための柔軟性が高くなっています。 たとえば、Narayanaには、C /C++とJavaの両方の言語バインディングがあります。 ただし、これには複雑さが増すという代償が伴い、Atomikosの構成と使用は比較的簡単です。

8.2. Bitronix

Bitronix は、完全に機能するXAトランザクションマネージャーであり、JTAAPIに必要なすべてのサービスを提供します。 重要なのは、Bitronixは埋め込み可能なトランザクションライブラリであり、広範囲で有用なエラーレポートとログを提供します。 分散トランザクションの場合、これにより障害の調査が容易になります。 さらに、Springのトランザクション機能を優れた方法でサポートし、最小限の構成で動作します。

Atomikosと比較すると、Bitronixはオープンソースプロジェクトであり、製品をサポートする商用製品はありません。 Atomikosの商用製品の一部であるが、Bitronixには欠けている主要な機能には、マイクロサービスのサポートと宣言型のエラスティックスケーリング機能が含まれます。

9. 結論

要約すると、このチュートリアルでは、トランザクションの基本的な詳細について説明しました。 分散トランザクションとは何か、そしてAtomikosのようなライブラリがそれらの実行をどのように促進できるかを理解しました。 その過程で、Atomikos APIを利用して、分散トランザクションを備えたシンプルなアプリケーションを作成しました。

また、Atomikosが他の一般的なJavaフレームワークやライブラリとどのように連携するかについても理解しました。 最後に、利用可能なAtomikosの代替案をいくつか検討しました。

いつものように、この記事のソースコードはGitHubにあります。