ActiveMQ Camel: Every other message sends with multicast - apache-camel

I am trying to route an XML packet from one ActiveMQ queue to another ActiveMQ queue on another box. I am using camel to achieve this. I intend to send it to other boxes later so I am using the multicast to duplicate the message.
I am sending and receiving the messages using the C-Stomp library on both ends.
ActiveMQ-5.9.0 and Camel-2.12.3
camel.xml
<camelContext>
<route>
<from uri="activemq:queue:out" />
<multicast>
<to uri="otheractivemq:queue:in" />
</multicast>
</route>
</camelContext>
<!-- ActiveMQs -->
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
<bean id="otheractivemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://[differentip]:61616"/>
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
</property>
</bean>
On my ActiveMQ broker, I can see that messages are being added into the queue on the local side the promptly dequeued; but, when I check the other ActiveMQ, only every other message gets enqueued.
I attempted to add a "clone" of the destination queue on the other box and added it to the multicast; so, my route liked like the following:
<route>
<from uri="activemq:queue:out" />
<multicast>
<to uri="otheractivemq:queue:in" />
<to uri="otheractivemq:queue:in_clone" />
</multicast>
</route>
But, then the "clone" only received every other message, while the other queue received them all.

Related

Azure Service Bus (ASB) with Camel, MessageProducer has been closed (amqp:link:detach-forced)

I am using Apache Camel and camel-amqp component in order to communicate with an ASB queue.
<bean id="jmsConnectionFactory" class="org.apache.qpid.jms.JmsConnectionFactory">
<property name="remoteURI" value="amqps://${service.bus.uri}?amqp.idleTimeout=120000" />
<property name="username" value="${service.bus.username}" />
<property name="password" value="${service.bus.password}" />
<property name="receiveLocalOnly" value="true" />
</bean>
<bean id="jmsCachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsCachingConnectionFactory"/>
<property name="cacheLevelName" value="CACHE_CONSUMER"/>
</bean>
...
<route>
...
<to uri="amqp:queue:{{service.bus.queue}}?exchangePattern=InOnly"/>
</route>
The first time that my route is running a AmqpFixedProducer is created for the {{service.bus.queue}}. If i manage to re-run the route (after 10 minutes) then I am getting the following error:
Caused by: javax.jms.JMSException: The link 'G24:360891:qpid-jms:sender:ID:b60452dd-5a2e-4478-a462-7ca280ecd953:1:2:1:themis-test' is force detached by the broker due to errors occurred in publisher(link252). Detach origin: AmqpMessagePublisher.IdleTimerExpired: Idle timeout: 00:10:00. [condition = amqp:link:detach-forced]
at org.apache.qpid.jms.provider.amqp.AmqpSupport.convertToException(AmqpSupport.java:164)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at org.apache.qpid.jms.provider.amqp.AmqpSupport.convertToException(AmqpSupport.java:117)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at org.apache.qpid.jms.provider.amqp.AmqpAbstractResource.processRemoteClose(AmqpAbstractResource.java:262)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at org.apache.qpid.jms.provider.amqp.AmqpProvider.processUpdates(AmqpProvider.java:903)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at org.apache.qpid.jms.provider.amqp.AmqpProvider.access$1800(AmqpProvider.java:101)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at org.apache.qpid.jms.provider.amqp.AmqpProvider$17.run(AmqpProvider.java:789)[149:org.apache.qpid.jms.client:0.26.0.redhat-1]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)[:1.8.0_111]
at java.util.concurrent.FutureTask.run(FutureTask.java:266)[:1.8.0_111]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)[:1.8.0_111]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)[:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_111]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_111]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_111]
It seems that application uses the same producer for both calls bu the connection to the ASB is closed after 10 minutes.
My question is how can I manage this?
Is there a way to retrieve the producer that was automatically created by Camel, and an OnException part close it and retry again? How can I get the producer?
Thanks a lot!
Problem was solved by modifying cacheLevelName to CACHE_NONE instead of CACHE_CONSUMER.
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsCachingConnectionFactory"/>
<property name="cacheLevelName" value="CACHE_NONE"/>
</bean>

How to use transaction in Apache Camel with mybatis?

How to use transaction in mybatis? I have two inserts and I want to be sure that. Second insert won't be executed if first didn't. Sorry for my english.
<route>
<from uri="nomatterhere" />
<transacted/>
<to uri="mybatis:insertHeader?statementType=Insert"/>
<to uri="mybatis:insertBody?statementType=Insert"/>
</route>
My beans:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${database.driver_class_name}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="txManager"/>
<property name="propagationBehaviorName" value="PROPAGATION_NESTED"/>
</bean>
#Edit
I added beans and route.
this transacted isn't working. I mean when something will go wrong in insertBody (for example null value) then header is inserted anyway. I want to back transaction then. How can I achive this?

output is getting repeated , should be printed only once

It is a simple select statement from mysql server and showing output on console. Somehow the result is getting printed in loop though I haven’t used any timer as such.
<beans>
<context:component-scan base-package="com.java"/>
<bean destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property value="com.mysql.jdbc.Driver" name="driverClassName"/>
<property value="jdbc:mysql://localhost:3306/world" name="url"/>
<property value="root" name="username"/>
<property value="mysql" name="password"/>
</bean>
<!-- configure the Camel SQL component to use the JDBC data source -->
<bean class="org.apache.camel.component.sql.SqlComponent" id="sql">
<property name="dataSource" ref="dataSource"/>
</bean>
<camel:camelContext>
<camel:route>
<camel:from uri="sql:select id from city where countryCode='AFG' and district ='Kabol' "/>
<camel:log message="${body[id]}"/>
<camel:to uri="stream:out"/>
</camel:route>
</camel:camelContext>
</beans>
Client code is:
public static void main(String rgs[]) throws InterruptedException{
PropertyConfigurator.configure("C:/Users/payal.bansal/workspace/CamelOneProject/src/resources/log4j.properties");
//AbstractApplicationContext ctx= new ClassPathXmlApplicationContext("resources/camel-configThree.xml");
AbstractApplicationContext ctx= new ClassPathXmlApplicationContext("resources/camel-configEight.xml");
Thread.sleep(5000);
ctx.close();
}
The from SQL will repeat the SQL call every 500 milli seconds by default (its scheduled).
http://camel.apache.org/sql-component.html
If you want the SQL to fire only once, then use a timer
from timer
to sql
And configure the timer to only run once.
http://camel.apache.org/timer

Configuring 2 database in mybatis + springs

I have an existing setup of mybatis + springs for working with Oracle DB. I have a set of java mapper interfaces, a set of corresponding mapper xmls (each having reference to their corresponding java mapper). I need to setup support for MSSQL also, but finding it hard to do that. I have created a separate set of xmls (specific to queries of MSSQL) in com/mycomp/mob/db/mappers/mssql.
Below is the extract of my applicationConext.xml (Here DBDataSource is an internal class which reads a config files to get all DB details).
<bean name="dataSource" class="com.mycomp.mob.core.db.DBDataSource">
<constructor-arg index="0" name="dbAlias" value="mob" />
<constructor-arg index="1" name="cfgSection" value="primary" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mycomp.mob.db.mappers.oracle" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.mycomp.mob.db.mappers.oracle" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
Below is part of mybatis-config.xml (here ${} params are replaced using the earlier DBDatasource)
<configuration>
<typeAliases>
<package name="com.mycomp.mob.db.model" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/mycomp/mob/db/mappers/oracle/tenant.xml" />
<mapper resource="com/mycomp/mob/db/mappers/oracle/functionenty.xml" />
</mappers>
</configuration>
com.mycomp.mob.db.model contains POJO for tenant and functionentry.
Usage is as below :
ITenantMapper mappper = sqlSessionFactory.openSession().getMapper(ItenantMapper.class)
Tenant t = mapper.getTenant();
Now at a time only one DB (which is configured as primary in DB config file) will be used. So how to make sure that XML corresponding to that particular DB is invoked by the java mapper interface.
Also need to know can I configure same java mapper class name inside the mapper xmls of mssql ?
Is the flow used correct or I need to change the flow for supporting multiple databases.
Create two datasources and two SessionFactories in spring one for Oracle another for MSSQL.

"Cannot rollback() inside an XASession" error on Fuse ESB 7.1.0

Yesterday I tried to migrate my bundles from ServiceMix 4.4.1 to Fuse ESB Enterprise 7.1.0. Bundles with local transactions work fine, but other ones with XA transaction don't work well. They write continuously tracebacks with the following messages to the log file:
13:30:29,283 | WARN | cation-stageOne] | PooledSession | 139 - org.apache.activemq.activemq-spring - 5.7.0.fuse-71-047 | Caught exception trying rollback() when putting session back into the pool, will invalidate. javax.jms.TransactionInProgressException: Cannot rollback() inside an XASession
javax.jms.TransactionInProgressException: Cannot rollback() inside an XASession
at org.apache.activemq.ActiveMQXASession.rollback(ActiveMQXASession.java:76)279:org.apache.activemq.activemq-core:5.7.0.fuse-71-047
at org.apache.activemq.pool.PooledSession.close(PooledSession.java:120)139:org.apache.activemq.activemq-spring:5.7.0.fuse-71-047
at org.springframework.jms.connection.JmsResourceHolder.closeAll(JmsResourceHolder.java:193)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:412)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.jms.connection.ConnectionFactoryUtils$JmsResourceSynchronization.releaseResource(ConnectionFactoryUtils.java:1)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.transaction.support.ResourceHolderSynchronization.afterCompletion(ResourceHolderSynchronization.java:98)148:org.springframework.transaction:3.0.7.RELEASE
at org.springframework.transaction.support.TransactionSynchronizationUtils.invokeAfterCompletion(TransactionSynchronizationUtils.java:168)148:org.springframework.transaction:3.0.7.RELEASE
at org.springframework.transaction.support.AbstractPlatformTransactionManager.invokeAfterCompletion(AbstractPlatformTransactionManager.java:996)148:org.springframework.transaction:3.0.7.RELEASE
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletion(AbstractPlatformTransactionManager.java:971)148:org.springframework.transaction:3.0.7.RELEASE
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:799)148:org.springframework.transaction:3.0.7.RELEASE
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)148:org.springframework.transaction:3.0.7.RELEASE
at org.apache.aries.transaction.GeronimoPlatformTransactionManager.commit(GeronimoPlatformTransactionManager.java:76)
at sun.reflect.GeneratedMethodAccessor243.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25):1.6.0_35
at java.lang.reflect.Method.invoke(Method.java:597):1.6.0_35
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:58)114:org.springframework.osgi.core:1.2.1
at org.springframework.osgi.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:62)114:org.springframework.osgi.core:1.2.1
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:56)114:org.springframework.osgi.core:1.2.1
at org.springframework.osgi.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:39)114:org.springframework.osgi.core:1.2.1
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.osgi.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:59)114:org.springframework.osgi.core:1.2.1
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)110:org.springframework.aop:3.0.7.RELEASE
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)110:org.springframework.aop:3.0.7.RELEASE
at $Proxy178.commit(Unknown Source)[:]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:257)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050)153:org.springframework.jms:3.0.7.RELEASE
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)153:org.springframework.jms:3.0.7.RELEASE
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886):1.6.0_35
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908):1.6.0_35
at java.lang.Thread.run(Thread.java:662):1.6.0_35
It happens with an empty queue.
My activemq endpoint configuration looks as following:
<osgi:reference id="osgiPlatformTransactionManager" interface="org.springframework.transaction.PlatformTransactionManager"/>
<osgi:reference id="osgiJtaTransactionManager" interface="javax.transaction.TransactionManager"/>
<bean id="jmstx" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsTxConfig" />
</bean>
<bean id="jmsTxConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="jmsXaPoolConnectionFactory"/>
<property name="transactionManager" ref="osgiPlatformTransactionManager"/>
<property name="transacted" value="true"/>
<property name="cacheLevelName" value="CACHE_NONE"/>
<property name="concurrentConsumers" value="${jms.concurrentConsumers}" />
</bean>
<bean id="jmsXaPoolConnectionFactory" class="org.apache.activemq.pool.XaPooledConnectionFactory">
<property name="maxConnections" value="${jms.maxConnections}" />
<property name="connectionFactory" ref="jmsXaConnectionFactory" />
<property name="transactionManager" ref="osgiJtaTransactionManager" />
</bean>
<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="${jms.broker.url}"/>
<property name="redeliveryPolicy">
<bean class="org.apache.activemq.RedeliveryPolicy">
<property name="maximumRedeliveries" value="-1"/>
<property name="initialRedeliveryDelay" value="2000" />
<property name="redeliveryDelay" value="5000" />
</bean>
</property>
</bean>
This endpoint is used very easy in the camel context as:
<route id="route">
<from uri="jmstx:queue:somequeue" />
<!-- some logic here -->
</route>
I would be glad if someone can help me to solve this issue. I can provide more deatails if it necessary.
EDIT
It seems that the issue is connected to the JMS connection pool: when I change connection factory to a simple ActiveMQXAConnectionFactory, then the exception disappears.
This is a known problem in the activemq-pool of version 5.7.0 (and most likely earlier versions) and has been reported http://fusesource.com/issues/browse/ENTMQ-441.

Resources