Hi We also discussed Camel and transactions within Red Hat with some customers recently. And Duane Hawkins wrote this nice piece of response which I am allow to share here in the public with his permissions
There are a couple of possible gotchas here: 1. It is important to note that Camel redelivery is different and separate from ActiveMQ redelivery. Camel redelivery will retry a failed exchange, but the broker is unaware of these redelivery attempts, so they don't count against the JMS redelivery maximum. 2. If we mark an exception as "handled" with "<handled>true</handled> then no exception will be propagated back to the session, so the default listener will ack the message and as far as the broker is concerned, the message delivery was successful, so the message will be dequeued, so if we want the jms subsystem to handle failures, handled should be marked "false." If we want Camel to handle redelivery, then we need to set up a dead-letter channel (https://camel.apache.org/dead-letter-channel.html) to push the message to some specific address (and mark handled as "true" to dequeue the message on the originating broker). In my experience, the simplest most reliable solution is to use a transacted session or use CLIENT_ACKNOWLEDGE mode and set handled to "false" in the errorhandler to let the exception propagate out of the handler, which should rollback the session and result in an incremented delivery count at the broker level, then we can set up a targeted DLQ for the destination in question on the broker. We can still use an errorHandler on the client side if we would like to log a friendly error message or copy the message to another destination, or send an alert, etc. If you have 2 transacted resources (an upstream "from" broker and downstream "to" broker) and don't want to use XA, you can use a client acknowledgment mode on the source broker (or a local transaction), and try setting maxReconnectAttempts to "0" or "1" on the CF servicing the downstream connector to force the connector to get evicted from the pool on a failure and this should throw out an exception and rollback the session / prevent acking the message to the upstream broker and increment the delivery count. On Wed, Jun 26, 2019 at 9:01 AM sujin sr <suji...@gmail.com> wrote: > > I am facing a issue while trying to implement JMS transaction using Camel. > > Here is the scenario > > 1. Primary route which read the message from the queue(JMS_IN), pass the > same exchange to the two sub route(direct route) > 2. First sub route process the message successfully and send to the another > queue(JMS_ONE) > 3. Second sub route process the message and send to the another > queue(JMS_TWO). > 4. If any error occurred during the sub route processing all the message > should rollback and original message sent to another queue(ERROR) that is > dead letter queue. > 5. In the example Context I have created throw RuntimeException during > second sub route processing. > 6. So expected behavior is to move the original message to ERROR queue, > same time no message should send to JMS_ONE & JMS_TWO > 7. But actual behavior is original message was sent to the ERROR queue, but > message sent the JMS_ONE. > > I am using Apache Camel 2.24.0, Jboss HornetQ and spring transaction > manager. > > Kindly help me on this, I am struck at this for couple of days > > Camel Context Below > > <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"> > <property name="environment"> > <props> > <prop > key="java.naming.factory.initial">org.jboss.naming.remote.client.InitialContextFactory</prop> > <prop > key="java.naming.provider.url">http-remoting://localhost:9089</prop> > <!--<prop > key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>--> > <prop key="java.naming.security.principal">TESTUSR</prop> > <prop key="java.naming.security.credentials">TESTUSR</prop> > </props> > </property> > </bean> > > <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> > <property name="connectionFactory" ref="jmsConnectionFactory"/> > </bean> > > <bean id="jmsConnectionFactory" > class="org.springframework.jndi.JndiObjectFactoryBean"> > <property name="jndiTemplate" ref="jndiTemplate"/> > <property name="jndiName" value="jms/RemoteConnectionFactory"/> > </bean> > > <bean id="jmsTransactionManager" > class="org.springframework.jms.connection.JmsTransactionManager"> > <property name="connectionFactory" ref="jmsConnectionFactory"/> > </bean> > > <bean id="jmsConfig" > class="org.apache.camel.component.jms.JmsConfiguration"> > <property name="connectionFactory" ref="jmsConnectionFactory"/> > <property name="transactionManager" ref="jmsTransactionManager"/> > <property name="transacted" value="true"/> > </bean> > > <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> > <property name="configuration" ref="jmsConfig"/> > </bean> > > <bean id="successProcessor" class="com.test.SuccessTestProcessor"/> > <bean id="errorProcessor" class="com.test.ErrorTestProcessor"/> > <bean id="deadChannelProcessor" > class="com.test.DeadChannelTestProcessor"/> > > > <bean id="myDeadLetterErrorHandler" > class="org.apache.camel.builder.DeadLetterChannelBuilder"> > <property name="deadLetterUri" value="direct:dead_letter_channel"/> > <property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/> > </bean> > > <bean id="myRedeliveryPolicyConfig" > class="org.apache.camel.processor.RedeliveryPolicy"> > <property name="maximumRedeliveries" value="0"/> > </bean> > > <camelContext xmlns="http://camel.apache.org/schema/spring" > errorHandlerRef="myDeadLetterErrorHandler"> > > <route id="route-one" > > <from uri="jms:queue:t24IFInboundQueue"/> > <transacted/> > <to uri="direct:success-route"/> > <to uri="direct:error-route"/> > </route> > > <route id="direct-success-route"> > <from uri="direct:success-route"/> > <transacted/> > <process ref="successProcessor"/> > <to uri="jms:queue:JMS_ONE"/> > </route> > > <route id="direct-error-route"> > <from uri="direct:error-route"/> > <transacted/> > <process ref="errorProcessor"/> > <to uri="jms:queue:JMS_TWO"/> > </route> > > <route id="direct_dead_letter_channel"> > <from uri="direct:dead_letter_channel"/> > <process ref="deadChannelProcessor"/> > <to uri="jms:queue:ERROR"/> > </route> > > </camelContext> > > Thanks!!! -- Claus Ibsen ----------------- http://davsclaus.com @davsclaus Camel in Action 2: https://www.manning.com/ibsen2