スタートアップ(英語)
コミュニティ(英語)
トレーニング(英語)
チュートリアル(英語)
ドキュメント
API、AI、ツール (英語)
トランザクションの管理
トランザクションとは、結果が不確定になることができない Mule アプリケーションの操作です。フローの一連のステップが 1 つの単位として成功または失敗する必要がある場合、Mule はトランザクションを使用して、それらのステップを単位として区分します。
たとえば、トランザクションを使用して、データベースに情報をコミットするためのフロー内の複数のステップをカプセル化することができます。このようなシナリオでは、コミット (トランザクション) は、全体が完了 (成功) するか、不完全に終了 (失敗) するかのどちらかとなります。部分的に完了しても、コミットは失敗となります。トランザクションが失敗すると、一部だけで部分的な完了とならないように Mule は操作をトランザクション内でロールバックします。
アプリケーションが非トランザクションコネクタからメッセージを受信する場合であっても、信頼性の高いメッセージングができるように信頼性パターンを実装してアプリケーションをデザインしてください。
Mule アプリケーションでトランザクションを管理するように Bitronix を設定することもできます。
トランザクション種別
Mule は、単一リソース (ローカル、デフォルト) および拡張アーキテクチャ (XA) トランザクション種別 (transactionType) をサポートします。トランザクション種別を定義できるコンポーネントはイベントソース (たとえば、jms:listener や vm:listener) と Try スコープのみです。
次の表で、各トランザクション種別の特性とトランザクションを結合するための操作の要件について説明します。
| トランザクション種別 | 特性 | トランザクションを結合するための要件 |
|---|---|---|
|
|
|
|
|
トランザクションのアクション
トランザクションアクション (transactionalAction) は、トランザクションに関して操作で実行できるアクションの種別を定義します。次の表で、使用可能なすべてのトランザクションアクションについて説明します。
| アクション | 動作 | 使用可能な場所 |
|---|---|---|
|
メッセージの受信時に常に新しいトランザクションを開始します。単一リソーストランザクションが存在する場合、エラーが発生します。XA トランザクションが存在する場合、ネストされたトランザクションが作成されます。 |
|
|
メッセージの受信時に常にトランザクションが進行中であると想定します。トランザクションがない場合、エラーが発生します。 |
|
|
メッセージの受信時にトランザクションが進行中である場合、可能であればトランザクションを結合します。可能でなければ新しいトランザクションを開始します。 |
|
|
現在のトランザクションが使用可能な場合、そのトランザクションを結合します。可能でなければトランザクションは作成されません。 |
|
|
アクションをトランザクションとして扱いません。 |
|
|
トランザクションを開始しません。 |
|
|
存在するトランザクションの外部で実行します。 |
|
イベントソースでのトランザクションの設定
トランザクションを Mule イベントソースから開始できます。この場合は、フロー全体が 1 つのトランザクションとなります。この方法は、メッセージングコネクタを使用して、メッセージングの処理中に問題が発生した場合にはメッセージをコンシュームしないようにして、後で (ロールバックによって) 再試行できるようにしたいときに便利です。
トランザクションを Mule イベントソースから開始するには、そのトランザクション種別とトランザクションアクションを設定します。
-
Anypoint Studio では、次の手順を実行します。
リスナーの [Advanced (詳細)] タブで、[Transaction type (トランザクション種別)] と [Transactional action (トランザクションアクション)] の値を設定します。
-
[Configuration XML (設定 XML)] では、次の手順を実行します。
transactionalAction 要素と transactionType 要素 (必要な場合) を追加し、その値を設定します。次の XML 例は、単一リソース (ローカル) トランザクションを開始するように設定された
vm:listener イベントソースを示しています。<?xml version="1.0" encoding="UTF-8"?> <mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd"> <vm:config name="VM_Config1" > <vm:queues > <vm:queue queueName="input" /> <vm:queue queueName="output" /> </vm:queues> </vm:config> <flow name="source-transactionsFlow"> <vm:listener config-ref="VM_Config1" queueName="input" transactionalAction="ALWAYS_BEGIN"/> <http:request method="GET" url="www.google.com"/> <vm:publish config-ref="VM_Config1" queueName="output"/> </flow> </mule>
Try スコープでのトランザクションの設定
Mule フローは、フロー内のトランザクションを必要とする非トランザクションコネクタ (HTTP など) で開始する場合もあります。たとえば、Mule フローで外部 Web サービスから情報を受け入れ、クレジットカードに請求してインボイス情報をデータベースに保存する前にデータを変換するとします。この場合は Try スコープを使用して、クレジットカードへの請求操作とデータベースへのコミット操作をラップすることでトランザクションをセットアップすれば、常に完全な成功または完全な失敗とロールバックのどちらかの結果になることを保証できます。
トランザクション種別とトランザクションアクションを設定して、Try スコープコンポーネントでトランザクションを設定できます。
-
Anypoint Studio では、次の手順を実行します。
Try スコープの [General (一般)] タブで、[Transaction type (トランザクション種別)] と [Transactional action (トランザクションアクション)] の値を設定します。
-
[Configuration XML (設定 XML)] では、次の手順を実行します。
transactionalAction 要素と transactionType 要素 (必要な場合) を追加し、その値を設定します。次の XML 例では、Try スコープによってデータベース操作 (
db:insert) と VM 操作 (vm:publish) を含むトランザクションを区分しています。プロセス全体が成功した場合は両方が適用され、Try スコープ内でエラーが発生した場合はどちらも適用されません。<?xml version="1.0" encoding="UTF-8"?> <mule xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns:db="http://www.mulesoft.org/schema/mule/db" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd"> <db:config name="Database_Config"> <db:derby-connection database="myDb" create="true" /> </db:config> <vm:config name="VM_Config"> <vm:queues> <vm:queue queueName="myQueue" /> </vm:queues> </vm:config> <flow name="transactionsFlow"> <try transactionalAction="ALWAYS_BEGIN" transactionType="XA"> <db:insert doc:name="Insert" transactionalAction="ALWAYS_JOIN"> <db:sql> INSERT INTO main_flow_audit (errorType, description) VALUES (:errorType, :description) </db:sql> <db:input-parameters><![CDATA[ #[{ 'errorType' : 'AUTHENTICATION', 'description' : 'invalid authentication credentials', }] ]]></db:input-parameters> </db:insert> <vm:publish config-ref="VM_Config" queueName="myQueue" transactionalAction="ALWAYS_JOIN"/> </try> </flow> </mule>
トランザクションによるスコープとルーターへの影響
トランザクションスコープで実行する場合は、プロセス全体を同じスレッドで実行する必要があります。これにより、スコープの実行方法、またはトランザクションの処理方法を変更できます。以下で、トランザクションスコープで実行するときに考慮する必要があるスコープおよびルーターの動作について詳しく説明します。
スコープ
-
Async: トランザクション内で実行した場合、Async スコープは引き続き別のスレッドで実行されます (非同期のまま)。ただし、これはこのスコープ内のプロセッサーの実行全体がトランザクションスコープ外で行われることを意味します。そのため、Async スコープ内でエラーが発生してもロールバックにはなりません。
-
Until Successful: トランザクション内で実行した場合、Until Successful スコープはスレッドをブロックします。つまり、Until Successful スコープが再試行間の遅延を実行している間、この実行によって使用されるスレッドを使用して他の要求を処理することはできません。
-
Parallel Foreach: トランザクション内で実行した場合、Parallel Foreach スコープは並列で実行されません。つまり、Foreach スコープとして実行することになります。コレクションの 2 番目の要素は最初の要素が完了した後に処理されます。これは、このスコープによるエラーの処理に影響を及ぼしません。
-
Batch Processing: Batch Processing は Async スコープとして並列で機能するように設計されており、すべてのレコードはトランザクションとして扱われるため (内部 Batch トランザクションを含む)、Batch 実行はトランザクションの一部ではありません。
ルーター
-
Scatter Gather: トランザクション内で実行した場合、Scatter Gather は並列で実行されません。つまり、2 番目のルーターは最初のルーターが処理された後で実行され、3 番目のルーターは 2 番目のルーターの後で実行される、といった具合になります。 これは、このコンポーネントによるエラーの処理に影響を及ぼしません。
-
Flow Reference: 実行中のフロー (またはサブフロー) がトランザクション内で実行されている場合、Flow Reference コンポーネントによって参照先のフロー (またはサブフロー) の実行は同じトランザクションで続行されます。参照先のフローにトランザクションを開始する Mule イベントソースがある場合 (たとえば、
transactionalAction="ALWAYS_BEGIN" の jms:listener ソース)、transactionalAction は無視されます。Flow Reference コンポーネントは、そのイベントソースを除いて参照先のフローコンポーネントを実行します。
その他のルーターまたはスコープ (たとえば、Foreach) はトランザクションで続行され、その動作は変更されません。
エラー処理
トランザクション中にエラーが発生した場合、アプリケーションはエラーを処理して続行するか、ロールバックを実行する必要があります。
エラーハンドラーには 2 つの種別があり、トランザクション中にエラーが発生したときの動作が異なります。
-
On Error Propagate
-
on-error-propagate エラーハンドラーがトランザクションを開始したコンポーネントに対応する error-handler スコープ内にある場合:on-error-propagate スコープのプロセッサーを実行する前にトランザクションがロールバックされます。つまり、エラーハンドラー内のプロセッサーはトランザクション内で実行されません。 -
on-error-propagate エラーハンドラーがトランザクションを開始しなかった要素内にある場合:トランザクションはロールバックされず、
on-error-propagate エラーハンドラー内のプロセッサーはトランザクション内で実行されます。一部のスコープやルーターでは、トランザクション内で実行したときに動作が異なります。
-
-
On Error Continue
エラーが処理され、トランザクションはアクティブなままになり、コミット可能です。
on-error-continue 内のプロセッサーはトランザクション内で実行されます。
例: Try スコープでのエラー発生
イベントソース (jms:listener) がトランザクションを開始し、このトランザクションが Try スコープによって続行される (transactionalAction はデフォルトの INDIFFERENT に設定) 例について考えてみます。
エラーが発生すると、最初に Try スコープの error-handler によって処理されます。エラーは on-error-propagate エラーハンドラーによって処理されますが、トランザクションを開始したのが Try スコープではないため、トランザクションはロールバックされません。トランザクションはフローレベルで (そのイベントソースから) 開始されたため、トランザクションをロールバックできるのはフローエラーハンドラーのみです。
on-error-propagate エラーハンドラー内の jms:publish 操作はトランザクションを結合します。次にエラーはフロー error-handler に伝播され、このフローが on-error-continue エラーハンドラーを使用してエラーを処理します。on-error-continue エラーハンドラー内の jms:consume 操作はトランザクション内で実行されます。最後に、トランザクションがコミットされます。
<flow name="someFlowWithTx">
<jms:listener config-ref="JMS_Config" destination="test.in" transactionalAction="ALWAYS_BEGIN"/>
<!-- Processors -->
<try>
<raise-error type="APP:SOME"/>
<error-handler>
<on-error-propagate>
<jms:publish config-ref="JMS_Config" destination="test.out" transactionalAction="ALWAYS_JOIN"/>
</on-error-propagate>
</error-handler>
</try>
<error-handler>
<on-error-continue>
<jms:consume config-ref="JMS_Config" destination="test.in2" transactionalAction="ALWAYS_JOIN"/>
</on-error-continue>
</error-handler>
</flow>
前の例で on-error-continue エラーハンドラーを on-error-propagate エラーハンドラーに置き換えると、プロセッサーの実行前にトランザクションがロールバックされます。このシナリオでは、jms:consume 操作はトランザクションを結合できないため、この設定は正しくありません。
例: 参照先のフローでのエラー発生
次の例の動作は前の例と同じですが、Try スコープの代わりに Flow Reference を使用し、参照先のフローでエラーが発生します。
<flow name="someFlowWithTx">
<jms:listener config-ref="JMS_Config" destination="test.in" transactionalAction="ALWAYS_BEGIN"/>
<!-- Processors -->
<flow-ref name="someFlowContinuesTx"/>
<error-handler>
<on-error-continue>
<jms:consume config-ref="JMS_Config" destination="test.in2" transactionalAction="ALWAYS_JOIN"/>
</on-error-continue>
</error-handler>
</flow>
<flow name="someFlowContinuesTx">
<raise-error type="APP:SOME"/>
<error-handler>
<on-error-propagate>
<jms:publish config-ref="JMS_Config" destination="test.out" transactionalAction="ALWAYS_JOIN"/>
</on-error-propagate>
</error-handler>
</flow>
someFlowContinuesTx フローがトランザクションを開始したのではないため、そのエラーハンドラーはトランザクションをロールバックしません。
例: エラーハンドラーの比較
この例は、on-error-continue エラーハンドラーと on-error-propagate エラーハンドラーの違いを示しています。
<flow name="flow1">
<jms:listener config-ref="JMS_Config" destination="test.in" transactionalAction="ALWAYS_BEGIN"/>
<raise-error type="APP:SOME"/>
<error-handler>
<on-error-continue>
<try transactionalAction="ALWAYS_BEGIN">
<logger message="hello"/>
</try>
</on-error-continue>
</error-handler>
</flow>
<flow name="flow2">
<jms:listener config-ref="JMS_Config" destination="test.in" transactionalAction="ALWAYS_BEGIN"/>
<raise-error type="APP:SOME"/>
<error-handler>
<on-error-propagate>
<try transactionalAction="ALWAYS_BEGIN">
<logger message="hello"/>
</try>
</on-error-propagate>
</error-handler>
</flow>
flow1 で、on-error-continue エラーハンドラーはトランザクションをアクティブに保ちますが、その中の Try スコープは新しいトランザクションを開始しようとします。この設定は有効ではなく、エラーが発生します。
flow2 で、on-error-propagate エラーハンドラーがトランザクションをロールバックし、on-error-propagate エラーハンドラー内のプロセッサーが実行され、トランザクションが新規作成されます。この設定は正しくなります。


