Need help setting variable in Camel - xpath

I am trying to set a variable inside of my camel code so I can call this variable when I log my route execution. This variable needs to be set from an xpath statement.
Below is the code that is not working and I suspect that I need to set a variable that is equal to my xpath statement that is found in the log message but I don't know how to do that.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/blueprint"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<bean id="activemq"
class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="user"/>
<property name="password" value="password"/>
</bean>
<camelContext id="blueprintContext" trace="false" xmlns="http://camel.apache.org/schema/blueprint">
<route id="Test_Message_Content_Route">
<from uri="activemq:queue:FirstQueue?username=user&password=password&concurrentConsumers=1&maxConcurrentConsumers=5"/>
<choice>
<when>
<xpath>//destination[text()='TEST']</xpath>
<log message="Test route invoked"/>
<split>
<xpath resultType="java.lang.String">//message_payload/text()</xpath>
<log message="Routed $xpath{//id/text()} to TEST QUEUE"/>
<to uri="activemq:queue:TestQueue?username=user&password=password"/>
</split>
</when>
<when>
<xpath>//destination[text()='DEV']</xpath>
<log message="Dev route invoked"/>
<split>
<xpath resultType="java.lang.String">//message_payload/text()</xpath>
<log message="Routed $xpath{//id/text()} to DEV QUEUE"/>
<to uri="activemq:queue:DevQueue?username=user&password=password"/>
</split>
</when>
<otherwise>
<log message="Sending message to DL Queue"/>
<to uri="activemq:queue:DLQueue?username=user&password=password"/>
</otherwise>
</choice>
</route>
</camelContext>
</blueprint>

I now have this working by using setHeader in my camel context like the following:
<setHeader headerName="id"><xpath>//id/text()</xpath></setHeader>
<log message="Routed ${header.id} to Test queue"/>

Related

Camel Route not working asynchronously once message is received from topic

We have camel route which reads from topic and then performs some transformation on message received it.
Given its durable topic only one message is processed at time, until route finishes its work.
To achieve concurrency, added threadpool so once message is received from topic to further work asynchronously, threads are spawning but its sequential one. Like once message is received thread is picked from pool and starts processing until that thread doesn't finish processing next message is not picked up.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:broker="http://activemq.apache.org/schema/core" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.5.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="threadPool" class="java.util.concurrent.Executors" factory-method="newFixedThreadPool">
<constructor-arg index="0" value="10"/>
</bean>
<camel:camelContext id="camel-etl" trace="true"
xmlns="http://camel.apache.org/schema/spring">
<route id="topicRoute" errorHandlerRef="deadLetterErrorHandler" >
<from uri="{{inbound.topic}}"/>
<camel:threads executorServiceRef="threadPool">
<choice>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<when>
...
...
<multicast>
some loigc ...
</multicast>
<bean ref="persistData"/>
</when>
<otherwise>
...
<bean ref="deadLetterErrorHandler"/>
</otherwise>
</choice>
</camel:threads>
</route>
</camel:camelContext>
<!-- XSLT config -->
<bean id="saxonFactory" class="net.sf.saxon.TransformerFactoryImpl"/>
<!-- custom component beans -->
<bean id="persistData" class="com.data.PersistBean"/>
</beans>
You need to turn on asyncConsumer on the JMS endpoint. See the docs at: https://github.com/apache/camel/blob/master/components/camel-jms/src/main/docs/jms-component.adoc

How to pass message from activemq queue to cxf client rest

I am creating a text message and put it in the activemq queue and i display it in the log. Now i need to pass this message to the cxf rs client to use it in the parameter. I am using blueprint to define the camel routes and cxf client.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
default-activation="eager" xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws" xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint/cxf
http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
http://cxf.apache.org/blueprint/jaxrs
http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
http://cxf.apache.org/configuration/security
http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd">
<!-- Beans -->
<bean id="myTransform" class="cxfcamel.MyTransform"/>
<bean id="serviceBean" class="cxfcamel.GreetingService" />
<bean id="rsprocessor" class="cxfcamel.RSProcessor"/>
<!-- Web Services -->
<jaxrs:server id="customerService" address="http://localhost:7171 /customers">
<jaxrs:serviceBeans>
<ref component-id="serviceBean" />
</jaxrs:serviceBeans>
</jaxrs:server>
<cxf:rsClient id="rsClient"
address="http://localhost:7171/customers/entry-point/register/nosJ"
serviceClass="cxfcamel.GreetingService">
</cxf:rsClient>
<!-- Camel Routes -->
<camelContext id="camel"
xmlns="http://camel.apache.org/schema/blueprint">
<route>
<from uri="timer://projectTimer?repeatCount=1" />
<bean ref="myTransform" method="transform" />
<to uri="activemq:queue:LOG.ME" />
</route>
<route>
<from uri="activemq:queue:LOG.ME" />
<to uri="log:ExampleActiveMQRouterBlueprint" />
</route>
<route>
<from uri="activemq:queue:LOG.ME" />
<setHeader headerName="Content-Type">
<constant>application/json</constant>
</setHeader>
<setHeader headerName="CamelHttpMethod">
<constant>PUT</constant>
</setHeader>
<to uri="cxfrs:bean:rsClient" />
</route>
</camelContext>
Can any one help me please?
Thanks
Both routes listen to activemq:queue:LOG.ME . A queue in ActiveMQ will consume the message and any other queue will not receive the message. You need to do 1 of 2 things:
Turn your queue into a topic so that both routes will receive the message. Topic vs Queue
Arrange your routes so only one route is listening to activemq:queue:LOG.ME.
There are two ways to accomplish this:
Turn your cxfrs:bean:rsClient invocation into a cxfrs:http://localhost:7171/customers/entry-point/register/nosJ and append the parameters at the end.
The documentation on this isn't very clear, but you might be able to use setHeader:
<setHeader headerName="CamelCxfRsQueryMap">
expression which returns a map
</setHeader>
This expression can be <bean>, a <groovy> embedded expression, etc.

Retry mechanism using Camel and ActiveMq - Retry Policy gets ignored

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.

Apache Camel: Call route again or dynamic routes

I'm using JBoss Fuse 6.1.0 with Camel 2.10.0.redhat-60024.
The list of routes are already known. For example: #start, #step1, #step2, #step3, #finish.
But I don't know sequence. Or sometimes some route may not be needed. I will know that only at #router route (please, see below code).
For example: #start, #step2, #step1, #step3, #finish. or #start, #step1, #step3, #finish. or etc.
But Camel 2.10.0 doesn't have such thing as dynamicRouter. I decided to do something like that:
<?xml version="1.0" encoding="UTF-8"?>
...
<camelContext id="blueprintContext" trace="true"
xmlns="http://camel.apache.org/schema/blueprint">
<route id="start">
<from uri="..." />
<to uri="vm:router" />
</route>
<route id="router">
<from uri="vm:router" />
<bean ref="stepGenerator" method="nextStep" />
<choice>
<when>
<simple>${header.step} contains 'step1'</simple>
<to uri="vm:step1" />
</when>
<when>
<simple>${header.step} contains 'step2'</simple>
<to uri="vm:step2" />
</when>
<when>
<simple>${header.step} contains 'step3'</simple>
<to uri="vm:step3" />
</when>
<when>
<simple>${header.step} contains 'finish'</simple>
<to uri="vm:finish" />
</when>
</choice>
</route>
<route id="step1">
<from uri="vm:step1" />
<log message="Step 1 started." />
<!-- Some logic -->
<to uri="vm:router" />
</route>
<route id="step2">
<from uri="vm:step2" />
<log message="Step 2 started." />
<!-- Some logic -->
<to uri="vm:router" />
</route>
<route id="step3">
<from uri="vm:step3" />
<log message="Step 3 started." />
<!-- Some logic -->
<to uri="vm:router" />
</route>
<route id="finish">
<from uri="vm:finish" />
<log message="Finished!" />
</route>
</camelContext>
Imagine that we have next sequence: #start, #step1, #step2, #step3, #finish. If you to try to run this will be stopped at #start -> #router-> #step1.
In #step1 <to uri="vm:router" /> not working. If you call route twice it will not work. Why?
How can I solve this situation in Camel 2.10.0?
According to the camel website the dynamic Router pattern was introduced in
Version 2.5. I am sure that will work for you...

RabbitMQ and Camel with Multiple connection factories

I am trying to implement routing solution in which i need to read messages from one queue of rabbit mq and put message on different rabbit mq/different queue.
I was able to make read and write separately from queues but it is not working together.
Here is camel configuration file :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="amqp.spring.camel.component"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<jmxAgent id="agent" createConnector="false" disabled="true" />
<template id="wfcTemplate" />
<template id="routerTemplate" />
<route>
<from uri="spring-amqp:exchange1:queue1:ABCD?type=topic&autodelete=false&durable=true" />
<log message="Message available on a RabbitMQ Queue : ${body}" />
<to uri="spring-amqp:exchange2:queue2:EFGH?type=topic&autodelete=false&durable=true" />
</route>
</camelContext>
<rabbit:connection-factory id="producerConnectionFactory" connection-factory="producerConnectionFactory" />
<rabbit:template id="routerTemplate" connection-factory="producerConnectionFactory" message-converter="messageConverter" exchange="exchange2" />
<rabbit:admin connection-factory="producerConnectionFactory" />
<bean id="producerConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<property name="host" value="10.0.10.100"/>
<property name="port" value="5672"/>
<property name="username" value="shailesh"/>
<property name="password" value="shailesh"/>
<property name="virtualHost" value="vh1"/>
</bean>
<rabbit:connection-factory id="consumerConnectionFactory" connection-factory="consumerConnectionFactory"/>
<rabbit:template id="wfcTemplate" connection-factory="consumerConnectionFactory" message-converter="messageConverter" exchange="exchange1" />
<rabbit:admin connection-factory="consumerConnectionFactory"/>
<bean id="consumerConnectionFactory" class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<property name="host" value="10.0.10.101"/>
<property name="port" value="5672"/>
<property name="username" value="shailesh"/>
<property name="password" value="shailesh"/>
<property name="virtualHost" value="vh2"/>
</bean>
<!-- converters -->
<bean id="jsonMessageConverter" class="amqp.spring.converter.XStreamConverter"/>
<bean id="textMessageConverter" class="amqp.spring.converter.StringConverter"/>
<bean id="messageConverter" class="amqp.spring.converter.ContentTypeConverterFactory">
<property name="converters">
<map>
<entry key="application/json" value-ref="jsonMessageConverter"/>
<entry key="application/xml" value-ref="textMessageConverter"/>
</map>
</property>
<property name="fallbackConverter" ref="textMessageConverter"/>
</bean>
</beans>
There error I am getting is as follows :
[pache.camel.spring.Main.main()] SpringCamelContext INFO Total 1 routes, of which 1 is started.
[pache.camel.spring.Main.main()] SpringCamelContext INFO Apache Camel 2.10.3 (CamelContext: camel-1) started in 0.589 seconds
[PConsumer.SpringAMQPExecutor-1] route1 INFO Message available on a RabbitMQ Queue : Hello, world! Fri Feb 08 14:14:33 CST 2013
[l-1) thread #0 - amqp-producer] SpringAMQPProducer ERROR Could not deliver message via AMQP
java.lang.NullPointerException
at amqp.spring.camel.component.SpringAMQPProducer$AMQPProducerTask.run(SpringAMQPProducer.java:150)[camel-spring-amqp-1.4.jar:]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)[:1.7.0_11]
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)[:1.7.0_11]
at java.util.concurrent.FutureTask.run(FutureTask.java:166)[:1.7.0_11]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)[:1.7.0_11]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)[:1.7.0_11]
at java.lang.Thread.run(Thread.java:722)[:1.7.0_11]

Resources