spring-integrationspring-integration-amqp

Global transaction between AMQP Inbound and JMS Outbound


We need to transfer messages between a RabbitMQ and MQSeries.

enter image description here For this we use the configuration below.


<int:channel id="channelRmqMQ"></int:channel>

<int-amqp:inbound-channel-adapter   channel="channelRmqMQ" 
                                    queue-names=" QUEUE_OUT " 
                                    connection-factory="rabbitConnectionFactory" 
                                    auto-startup="true" 
                                    id="inboundChannelAdapter" 
                                    channel-transacted="true" 
                                    concurrent-consumers= " 1" 
                                    prefetch-count="40" 
                                    tx-size="40"
/>

<int-jms:outbound-channel-adapter   channel="channelRmqMQ" 
                                    id="jmsOut" 
                                    destination="jmsQueue" 
                                    connection-factory="connectionFactoryCaching" 
                                    delivery-persistent="true" 
                                    explicit-qos-enabled="true" 
                                    session-transacted="true" >
    <int-jms:request-handler-advice-chain>
        <ref bean="requestHandler" />
    </int-jms:request-handler-advice-chain>
</int-jms:outbound-channel-adapter>


We want to acknowledge the message in the RabbitMQ queue that in case the writing in MQSeries is good. For this we use the attribute channel-transacted on the amqp inbound and session-transacted on the jms outbound.

Is this the right way to do it?

How can we test the scenario where the message is well written in the MQSeries Queue (blue arrow) but an error occurs during the confirmation to RabbitMQ (green arrow)? Is it possible then to rollback on MQSeries? and retry with this message from RabbitMQ.

Thanks for your help.


Solution

  • No; that is not possible; RabbitMQ cannot participate in a Global (JTA) transaction.

    You will get a duplicate publish to MQ and will need to deal with it on the JMS consumer side.

    You don't really need channel-transacted for this scenario; RabbitMQ transactions are mainly about publishing messages to RabbitMQ.

    Consumption of messages is not transactional, but sending the ack is done in the transaction and can be rolled back.

    Non-transactional consumption in this use case will provide the same semantics as transactional.

    You can read about the limitation of RabbitMQ transactions here.