IBM MQ でのトランザクション処理

IBM MQ のトランザクション接続を使用すると、一連の操作をトランザクションがコミットされたときにまとめて実行するように設定できます。主な 2 つのシナリオは次のとおりです。

  • トランザクションの一環でメッセージをパブリッシュする: パブリッシュすると、メッセージはトランザクションがコミットされた後で宛先に送信されます。 何らかの理由でトランザクションが失敗してロールバックが発生すると、メッセージは送信されません。

  • トランザクションの一環でメッセージをコンシュームする: リスナーまたはコンシューマーによってコンシュームされたメッセージは、トランザクションがコミットされてはじめて肯定応答され、トランザクションがロールバックされた場合は、再配信のために宛先に戻されます。

IBM MQ Connector は、Mule の transactionalAction 設定を使用して、トランザクションとしての操作の実行をサポートしています。

操作をトランザクションの一部として実行するには、次の 2 つのオプションがあります。

新規メッセージのトランザクションセッションでの処理

IBM MQ の ​On New Message​ リスナーでトランザクションセッションを使用してメッセージをディスパッチしたい場合は、transactionalAction を ​ALWAYS_BEGIN​ に設定します。

<ibm-mq:listener
     config-ref="IBM_MQ_Config"
     destination="${originQueue}"
     transactionalAction="ALWAYS_BEGIN"/>

この設定により、それぞれの新規メッセージはトランザクションで処理され、このトランザクションはすべてのフローのコンポーネントに伝播されて、フローの実行が正常に完了した時点でコミットされます。 フローがエラーで完了した場合は、トランザクションはロールバックされます。

注意:​ デフォルトでは、フローの他のコンポーネントは、リスナーが作成したトランザクションには加わりません。他の操作をリスナーのトランザクションで実行するには、​ALWAYS_JOIN​ または ​JOIN_IF_POSSIBLE​ でそれらを宣言する必要があります。

トランザクションの一部としての操作の実行

パブリッシュやコンシュームなどの操作をトランザクションの一環として実行するには、transactionalAction を ​ALWAYS_JOIN​ または ​JOIN_IF_POSSIBLE​ に設定します。

このように設定した操作は、リスナーが開始するトランザクションの一部となります。

<flow name="joiningToListenerTransaction">
    <ibm-mq:listener config-ref="IBM_MQ_Config"
      destination="${originQueue}"
      transactionalAction="ALWAYS_BEGIN"/>
    <ibm-mq:publish config-ref="IBM_MQ_Config"
      destination="#[attributes.properties.userProperties.redirectDestination]"
      transactionalAction="JOIN_IF_POSSIBLE"/>
    <ibm-mq:consume config-ref="IBM_MQ_Config"
      destination="#[attributes.properties.userProperties.callbackDestination]"
      transactionalAction="JOIN_IF_POSSIBLE"/>
</flow>

スコープ付きトランザクションの一部として実行する場合は次のように設定します。

<flow name="nonTxPublishMustNotJoinCurrentTx">
    <http:listener config-ref="HTTP_Config" path="/orders"/>
    <try transactionalAction="ALWAYS_BEGIN">
        <ibm-mq:publish config-ref="config"
	destination="${billingService}"
	transactionalAction="ALWAYS_JOIN"/>
        <ibm-mq:publish config-ref="config"
	destination="${shipmentService}"
	transactionalAction="ALWAYS_JOIN"/>
        <ibm-mq:publish-consume config-ref="IBM_MQ_Config"
	destination="${invoicesVerificationService}"/>
        <validation:is-true expression="#[payload]"/>
    </try>
</flow>

XA トランザクション

IBM MQ Connector では、XA トランザクションの作成と結合をサポートしており、複数リソースのトランザクションに関与することができます。これにより、IBM MQ の他の接続や、Database Connector や VM Connector などの接続を使用してトランザクションのアクションを実行することもできます。

IBM MQ Connector では、IBM MQ ドライバーの制限により、ネストされた XA トランザクションはサポートされません。ネストされたトランザクションを操作すると、外側のトランザクションが停止され、内側のトランザクションが終了した後に再開されます。このエラーが発生するのは、ドライバーの実装が原因で、外側のトランザクションが再開された場合です。

XA トランザクションを有効にするには:

  1. enableXa​ を true に設定して、XA 対応接続を作成します。

    <ibm-mq:config name="IBM_MQ_Config" >
    		<ibm-mq:connection enableXa="true" >
    			<ibm-mq:connection-mode >
    				<ibm-mq:client host="0.0.0.0" queueManager="QM1" />
    			</ibm-mq:connection-mode>
    		</ibm-mq:connection>
    	</ibm-mq:config>
  2. transactionType を XA に設定して、XA トランザクションを作成するように設定します。

    <flow name="joiningToListenerTransaction">
        <ibm-mq:listener config-ref="IBM_MQ_Config"
        destination="${originQueue}"
        transactionalAction="ALWAYS_BEGIN"
        transactionType="XA"/>
        <ibm-mq:publish config-ref="IBM_MQ_Config"
        destination="#[attributes.properties.userProperties.redirectDestination]"
        transactionalAction="JOIN_IF_POSSIBLE"
        transactionType="XA"/>
        <ibm-mq:consume config-ref="IBM_MQ_Config"
        destination="#[attributes.properties.userProperties.callbackDestination]"
        transactionalAction="JOIN_IF_POSSIBLE" transactionType="XA"/>
    </flow>

    スコープ付きトランザクションの一部として実行する場合は次のように設定します。

    <flow name="nonTxPublishMustNotJoinCurrentTx">
        <http:listener config-ref="HTTP_Config" path="/orders"/>
        <try transactionalAction="ALWAYS_BEGIN" transactionType="XA">
            <ibm-mq:publish config-ref="config"
    	destination="${billingService}"
    	transactionalAction="ALWAYS_JOIN"
    	transactionType="XA"/>
            <ibm-mq:publish config-ref="config"
    	destination="${shipmentService}"
    	transactionalAction="ALWAYS_JOIN"/>
    
            <ibm-mq:publish-consume config-ref="IBM_MQ_Config"
    	destination="${invoicesVerificationService}"/>
            <validation:is-true expression="#[payload]"/>
        </try>
    </flow>