Reputation: 79
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:
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.
Upvotes: 1
Views: 889
Reputation: 163
According to the Apache Karaf Transaction Guide should doTry and doCatch work as expected. What is probably the problem in your case is the Exception triggering the error scenario. Only checked exceptions (no RuntimeException or it's descendant) don't mark ongoing transaction for rolling back.
Upvotes: 0
Reputation: 7005
I expect camel to try redeliveries as per redelivery policy (working) but MQ should not redeliver
When MQ must never do a redelivery (because you handle errors in Camel), you should remove acknowledgementModeName=CLIENT_ACKNOWLEDGE
or explicitly set AUTO_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.
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
jmsComponent.setLazyCreateTransactionManager(false);
jmsComponent.setTransacted(true);
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 expect my camel route to run in a single db transaction
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.
Upvotes: 0