1

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.

Eric NICOLAS
  • 27
  • 1
  • 6

1 Answers1

0

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.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • It is not very clear to me. In the `int-amqp:inbound-channel-adapter` , no `acknowledge-mode` is set ( AUTO by default), when is ack the message to RabbitMQ? The channel get this message (green arrow) and publish it to MQ (orange arrow), and then confirm it to RabbitMQ? is it the same thread that processes reading in amqp and writing in jms? and then send the ack once the writing is finished? – Eric NICOLAS Mar 11 '20 at 15:06
  • Yes; using a direct channel (the default) the JMS publish occurs on the AMQP consumer thread and and ack is sent when the thread returns to the listener container. – Gary Russell Mar 11 '20 at 15:10
  • Thank you for your return, it's clear! With the definition of the `int-jms: outbound-channel-adapter`, if an error occurs after writing in MQ and before returning to the channel (orange arrow), there will be a roll back (delete message on MQ) because we use `session-transacted`? And the channel will retry later with the message not acked from Rabbit? – Eric NICOLAS Mar 11 '20 at 15:42
  • Correct but not "later", almost immediately (but it depends on the prefetch whether the failed record is redelivered next or whether it will be redelivered after the pre-fetched messages). – Gary Russell Mar 11 '20 at 15:51