Retry mechanism using Camel and ActiveMq - Retry Policy gets ignored - spring

I am working on a retry mechanism using camel and activeMq. What I want to do is to start a retry mechanism if one of the servers I am calling is down, add the request into my queue and from hour to hour resend it to the server. Everything works fine except my Retry Policy that seems to be ignored (my requests are resent when they get into my queue and they are never added into the DLQ after the number of retries is reached)
My configuration looks as follows (Values are readed from a .cfg file):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${activemq.broker.url}"/>
<property name="userName" value="${activemq.broker.username}"/>
<property name="password" value="${activemq.broker.password}"/>
<property name="redeliveryPolicy" ref="policy"/>
</bean>
<bean id="policy" class="org.apache.activemq.RedeliveryPolicy">
<property name="queue" value="*"/>
<property name="initialRedeliveryDelay" value="${activemq.redelivery.delay}"/>
<property name="redeliveryDelay" value="${activemq.redelivery.delay}"/>
<property name="useExponentialBackOff" value="false"/>
<property name="maximumRedeliveries" value="${activemq.number.of.redeliveries}"/>
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="maxConnections" value="8"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="transactionManager" ref="jmsTransactionManager"/>
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
<property name="concurrentConsumers" value="8"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
Camel route that calls my service:
<route id="addRegistrationRoute">
<from uri="direct:addRegistrationRoute"/>
<to uri="cxf:bean:addRegistrationEndpoint"/>
<onException>
<exception>java.net.ConnectException</exception>
<onWhen>
<el>${in.headers['previousRoute'] != 'registrationRetryRoute'}</el>
</onWhen>
<handled>
<constant>true</constant>
</handled>
<setBody>
<simple>${headers.request}</simple>
</setBody>
<removeHeaders pattern="*"/>
<to uri="activemq:queue:registrationRetryQueue"/>
<stop/>
</onException>
<onException>
<exception>org.apache.cxf.interceptor.Fault</exception>
<onWhen>
<el>${in.headers['previousRoute'] != 'registrationRetryRoute'}</el>
</onWhen>
<handled>
<constant>true</constant>
</handled>
<setBody>
<simple>${headers.request}</simple>
</setBody>
<removeHeaders pattern="*"/>
<to uri="activemq:queue:registrationRetryQueue"/>
<stop/>
</onException>
<onException>
<exception>javax.xml.soap.SOAPFault</exception>
<handled>
<constant>true</constant>
</handled>
</onException>
</route>
<route id="registrationRetryRoute">
<from uri="activemq:queue:registrationRetryQueue"/>
<setHeader headerName="previousRoute">
<simple>registrationRetryRoute</simple>
</setHeader>
<to uri="direct:addRegistrationRoute"/> <!-- Back to the initial flow. -->
</route>
If somebody can please tell me what I have did wrong in configuring activeMq I will be really thankful!
Regards,
Roxana

ActiveMQ pushes messages into DLQ only if you are throwing an error from your consumers (or message listeners). So try to catch your exception and throw it back so that retry policy will be enabled accordingly.

Related

JMS Message Redelivery not working for Topic in Spring + ActiveMQ + Atomikos + JTA + Tomcat

I have following configuration in the application that works perfectly fine with queues and redelivers the messages when a RuntimeException occurs with transaction rollback as expected.
But the same configuration fails to redeliver message with topics and emits following warning message:
WARN DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'XXX_TOPIC' - trying to recover. Cause: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: One or more resources refused to commit (possibly because of a timeout in the resource - see the log for details). This transaction has been rolled back instead.
Configuration:
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<!-- <property name="sendTimeout" value="1000"/> -->
<property name="redeliveryPolicy" ref="redeliveryPolicy"/>
</bean>
<!-- Atomikos Connection Factory Wrapper For Gobal Tx -->
<bean id="queueConnectionFactoryBean" class="com.atomikos.jms.AtomikosConnectionFactoryBean">
<property name="uniqueResourceName" value="amq1" />
<property name="xaConnectionFactory" ref="amqConnectionFactory" />
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="queueConnectionFactoryBean"/>
</property>
<property name="sessionCacheSize" value="20"/>
<property name="cacheConsumers" value="false"/>
</bean>
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init"
destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean>
<!-- Topic configuration -->
<bean id="messageListener1" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container1" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_TOPIC"/>
<property name="messageListener" ref="messageListener1" />
<property name="pubSubDomain" value="true" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<property name="receiveTimeout" value="3000" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
<!-- Bean configuration -->
<bean id="messageListener2" class="com.x.y.impl.JmsMessageListener"></bean>
<bean id="container2" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destinationName" value="XXX_QUEUE"/>
<property name="messageListener" ref="messageListener2" />
<property name="pubSubDomain" value="false" />
<property name="transactionManager" ref="jtaTransactionManager" />
<property name="concurrency" value="1" />
<!-- For local session and Atomikos-->
<property name="sessionTransacted" value="true"/>
</bean>
The Spring version used is 3.1, ActiveMQ 5.14, Atomikos 4.0.6.
Please let me know if i missed any configuration for topic DMLC.

How to migrate from activeMQ to ibmMQ in camelContext configuration?

I am currently using AciveMQ for routing purpose. But now i need to migrate to ibmMq. Here is my camelContext.xml configuration for AciveMq. Please help me with ibmMq config..
Thanks in advance.
<bean id="jmsConnectionFactory"
class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="pooledConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="8"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
</bean>
<bean id="jmsConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
<route id="*****">
<from uri="+++++++++" />
<choice>
<to uri="activemq:queue:**********"/>
</choice>
</route>
</camelContext>
Can anybody help me change all my configuration with respective to IBMmq
I am new to IBMmq :(
Here I managed to configure with ibm mq :)
<broker xmlns="http://activemq.apache.org/schema/core"
brokerName="${broker-name}"
dataDirectory="${data}"
start="false">
...
</broker>
...
<!-- Configure IBM WebSphere MQ connection factory -->
<bean id="weblogicConnectionFactory"
class="com.ibm.mq.jms.MQConnectionFactory">
<property name="transportType" value="1"/>
<property name="hostName" value="localhost"/>
<property name="port" value="1414"/>
<property name="queueManager" value="QM_TEST"/>
</bean>
<bean id="weblogicConfig"
class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="weblogicConnectionFactory"/>
<property name="concurrentConsumers" value="10"/>
</bean>
<bean id="weblogic"
class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="weblogicConfig"/>
</bean>
Successfully :)

Activemq jdbcPersistenceAdapter flushingmessages to database

I have a activemq jdbcPersistenceAdapter configured to use Oracle. The primary broker gets a lock, but when I send messages to the queue, I cannot see them in a database table. I do not want the the messages cached in any way, since they will not be consumed until there are no more producers (long story).
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="primary" useJmx="true" useShutdownHook="false">
<managementContext>
<!-- use appserver provided context instead of creating one,
for jboss use: -Djboss.platform.mbeanserver -->
<managementContext createConnector="false"/>
</managementContext>
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#oracle-ds" createTablesOnStartup="false" lockKeepAlivePeriod="30000"/>
</persistenceAdapter>
<transportConnectors>
<transportConnector uri="tcp://localhost:61616"/>
</transportConnectors>
<!-- Spring JMS Producer Configuration -->
<bean id="jmsProducerTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="defaultDestination" ref="p3dPausedTransactionDestination"/>
<property name="deliveryPersistent" value="true"/>
</bean>
<!-- Message Listener Container -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="destination" ref="p3dPausedTransactionDestination"/>
<property name="messageListener" ref="transactionMessageConsumer" />
<property name="sessionTransacted" value="true"/>
<property name="autoStartup" value="true"/>
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE"/>
</bean>
<!-- JMS Factory -->
<beans profile="local, test, dev, dev2, sit, uat, tt, prod">
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/activemq/p3dConnectionFactory"/>
<property name="lookupOnStartup" value="true"/>
</bean>
</property>
</bean>
</beans>
Once I added the second broker, the messages started appearing in the database.

Spring JMS message redelivery is not working

I am not sure what i am missing, when consumer is not able to process messsage it throws JMSException but i see failed messages are not getting redeliver otherwise below code is working fine , please help me what i am missing ?
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/jms
http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
<!-- Use Springs JNDI support to look up JMS Connection Factory and Queue definitions from the
container. This means that specific connection details are not embedded in the application
-->
<bean id="mqConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>vm://localhost:61616</value>
</property>
<property name="nonBlockingRedelivery" value="true"/>
<property name="redeliveryPolicy">
<bean class="org.apache.activemq.RedeliveryPolicy">
<property name="initialRedeliveryDelay" value="5000" />
<property name="backOffMultiplier" value="2" />
<property name="queue" value="*" />
<property name="useExponentialBackOff" value="true" />
<property name="redeliveryDelay" value="5000" />
<property name="maximumRedeliveries" value="20"/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="mqProducerConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL">
<value>vm://localhost:61616</value>
</property>
</bean>
</property>
</bean>
<bean id="test_queue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="test_queue" />
</bean>
<bean id="testConsumer" class="com.test.jms.listener.TestConsumer">
</bean>
<bean id="poiMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref ="mqConnectionFactory" />
<property name="destination" ref ="test_queue"/>
<property name="messageListener" ref ="testConsumer"/>
<property name="concurrentConsumers" value="1" />
<property name="sessionTransacted" value="true"/>
</bean>
<bean id="testProducer" class="com.test.jms.producer.testProducer">
<property name="destination" ref="test_queue"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="mqProducerConnectionFactory" />
</bean>
<jms:listener-container
container-type="default"
connection-factory="mqConnectionFactory"
acknowledge="transacted">
<jms:listener destination="test_queue" ref="testConsumer" method="onMessage" />
</jms:listener-container>
</beans>
Above code is working fine but it does not work for message re-delivery

Camel JMS request/Reply timeouts

I am trying to send request/reply a message to a remote broker from camel but the it times out. See config below:
<bean id="providerJMSConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="alwaysSessionAsync" value="false"/>
<property name="alwaysSyncSend" value="true"/>
<property name="brokerURL"><value>${remote-broker-broker-url}</value></property>
<property name="clientID" value=""/>
<property name="closeTimeout" value="15000"/>
<property name="copyMessageOnSend" value="true"/>
<property name="disableTimeStampsByDefault" value="false"/>
<property name="dispatchAsync" value="false"/>
<property name="objectMessageSerializationDefered" value="false"/>
<property name="optimizeAcknowledge" value="false"/>
<property name="optimizedMessageDispatch" value="true"/>
<property name="password" value=""/>
<property name="producerWindowSize" value="0"/>
<property name="statsEnabled" value="false"/>
<property name="useAsyncSend" value="false"/>
<property name="useCompression" value="false"/>
<property name="useRetroactiveConsumer" value="false"/>
<property name="userName" value=""/>
<property name="watchTopicAdvisories" value="true"/>
<property name="sendTimeout" value="0"/>
</bean>
<bean id="providerJMSConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="aeroProviderJMSConnectionFactory"/>
<property name="deliveryPersistent" value="true"/>
<property name="explicitQosEnabled" value="true"/>
<property name="priority" value="${jms-message-priority}"/>
<property name="acceptMessagesWhileStopping" value="false"/>
</bean>
<bean id="providerJMS" class="org.apache.camel.component.jms.JmsComponent">
<property name="configuration" ref="aeroProviderJMSConfig"/>
</bean>
<osgi:camelContext xmlns="http://camel.apache.org/schema/spring" trace="true">
<endpoint id="providerEndpoint" uri="providerJMS:queue:provider?replyTo=providerResponse&requestTimeout=120000"/>
<route>
<from .....>
<to ref="providerEndpoint"/>
....
</route>
<osgi:camelContext>
Why does this happen? I realised on the remote broker the number of consumers are always more than 1 even though I did not specify how many consumers it should have. Also, whene I removed the replyTo destination, the name still keep coming up on the remote broker.
Pls, is there any tool I can use to debug activemq so that I can see who is picking messages off a queue?
When doing request/reply over JMS with Camel, it uses a 20 sec default timeout. Is it that timeout you hit?
You can alter it, its the requestTimeout option
http://camel.apache.org/jms

Resources