I am trying to run a camel transacted() route (a standalone java process) with JPATransactionManager is the spring PlatformTransactionManager (as I want camel route to run in a single DB transaction) but I am not able to suppress redelivery from MQ Broker in case a transactional method fails even though I have used handled(true) in onException clause along with my custom redelivery policy (which is executed successfully). I only want MQ to redeliver when there is a service crash.
Tried below but it doesn't work:
- Setting setTransacted(false) in JMSComponent config so as to prevent camel jms to run is transacted_session jms mode but it does not work
- doTry and doCatch the exception from transactional block
camel redeliveries followed by handled(true).
onException(Exception.class) .log("ERROR OCCURRED") .redeliveryPolicyRef("myRedeliveryPolicy") .handled(true) .to(getPostExceptionRoute()); @Bean @Autowired public RedeliveryPolicy myRedeliveryPolicy() { RedeliveryPolicy myRedeliveryPolicy= new RedeliveryPolicy(); myRedeliveryPolicy.setMaximumRedeliveries(2); myRedeliveryPolicy.setMaximumRedeliveryDelay(2000); return myRedeliveryPolicy; } @Bean @Autowired public JmsComponent jms(IJMSConnectionFactory cf) throws JMSException { JmsComponent jmsComponent = new JmsComponent(); jmsComponent.setConfiguration(jmsConfig(cf)); jmsComponent.setTransacted(false); return jmsComponent; } from("jms:queue:TestQueue?acknowledgementModeName=CLIENT_ACKNOWLEDGE") .unmarshal().json(JsonLibrary.Jackson, TestObject.class) .transacted() .processRef("myPersistInDBProcessor")
I expect camel to try redeliveries as per redelivery policy (working) but MQ should not redeliver.
- I expect my camel route to run in a single db transaction.
- I expect MQ broker to redeliver only when my java service crashes in middle of processing, so that I do not lose the message.
When MQ must never do a redelivery (because you handle errors in Camel), you should remove
acknowledgementModeName=CLIENT_ACKNOWLEDGE
or explicitly setAUTO_ACKNOWLEDGE
(default value).As long as a message is not acknowledged, it is from the broker perspective not delivered.
AUTO_ACKNOWLEDGE
immediately acknowledges the message after consumption what makes sense if you never want to get redeliveries.CLIENT_ACKNOWLEDGE
on the other hand only acknowledges a message under certain conditions, see this post for some more info about this.EDIT due to comment with new information
If you want MQ redeliveries, but "override" them with Camel in most cases, you have to consume messages transacted.
Use local JMS broker transactions by configuring your JMS component like this
For this type of transaction you don't need a Spring TransactionManager at all. So I guess the
JPATransactionManager
is ignored by JMS and your JMS consumptions should be transactional.Now, when your Camel error handler "swallows" an Exception by using
handled(true)
, there must be no MQ redelivery. But MQ does a redelivery when an Exception is propagated back to the broker.I did not find anything in your question about not working database transactions. There seems to be just one processor that does database stuff. If this is not working correctly, please describe the problem in your question or a separate question.