Message Redelivery with DMLC + ActiveMQ + TxManager not working
We are currently trying to integrate ActiveMQ (5.5.0) into a product using Spring DMLC (2.5.6). The integration works so far except that the message redelivery is broken and we have no clue how to solve this. We want to rollback the transaction programmatically when there are certain error cases hit (no throwing of RuntimeExceptions).
Config:
<bean id="queueConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFa ctory">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFacto ry">
<property name="brokerURL">
<value>${amq.broker.url}</value>
</property>
<property name="redeliveryPolicy" ref="amqRedeliveryPolicy" />
</bean>
</property>
</bean>
with a defined Redelivery Policy:
<bean id="amqRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<property name="useExponentialBackOff" value="true" />
<property name="backOffMultiplier" value="2" />
<property name="initialRedeliveryDelay" value="1000" />
<property name="maximumRedeliveries" value="5" />
</bean>
<bean id="txManager" class="org.springframework.jms.connection.JmsTrans actionManager">
<property name="connectionFactory" ref="queueConnectionFactory"/>
</bean>
JMS Consumer:
<property name="connectionFactory" ref="queueConnectionFactory"/>
<property name="transactionManager" ref="springPlatformTxManager"/>
<property name="cacheLevelName" value="CACHE_AUTO"/>
The problem is that we can only either get a setup with an external transaction manager using the correct transactional behaviour, but with incorrect redelivery behaviour to work OR the correct redelivery behaviour if using a single consumer, but without external control over a TM (autocommit and rollback via exceptions).
The ActiveMQ redelivery handling is done on the consumer side to avoid overhead in the broker (change from 3.x to 4.x, see http://activemq.apache.org/message-r...andling.html):
"On rollback, since nothing has been acked yet, and all messages are still available in an internal consumer queue, the messages are re-dispatched from the internal consumer queue. This reduces redelivery dispatch overhead, at the cost of the broker not being aware that redeliveries are occurring."
If redelivery is handled on a consumer level, all consumers need to share the current state and coordinate their work. You can also find a lot of user complaints in the Spring forums struggling with the same problem and the answer is always the same � use consumer caching (cacheLevel=CACHE_CONSUMER).
It looks like the broker is delivering the message again, although it should not have received and ack from the client in the case we are doing the rollback. I suspect that if we have a transaction, something in the code is sending the broker the information, that he can resend the message and another consumer will pick it and handle it as a first time delivery � so completely without any delay in between.
Maybe someone has an idea how to get this combination running (without the consumer caching workaround and with a transaction manager).
Thanks!
Marek