How to pass message from activemq queue to cxf client rest - osgi

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.

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

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...

Need help setting variable in Camel

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"/>

Having trouble using data from a header in a camel route

In my camel route I am attempting to set a custom header and set the value of that header to data contained in the body. This header is later used in a SQL query, but it is not working correctly. I get an exception and it appears that the SQL query never gets the value of my header. Here is my camel route:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext trace="false" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxf:bean:soapEndpoint"/>
<log message="${body}"/>
<setHeader headerName="accountNumber">
<simple>${body}</simple>
</setHeader>
<log message="The header value is ${header.accountNumber}" />
<to uri="sql:select account_name from hz_cust_accounts where account_number=:#accountNumber"/>
</route>
</camelContext>
<!-- this is the JDBC data source -->
<bean id="OracleDS" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#myserver:1558:mydb" />
<property name="username" value="someuser" />
<property name="password" value="somepass" />
</bean>
<!-- configure the Camel SQL component to use the JDBC data source -->
<bean id="sql" class="org.apache.camel.component.sql.SqlComponent">
<property name="dataSource" ref="OracleDS" />
</bean>
<cxf:cxfEndpoint id="soapEndpoint" address="http://localhost:10001/erpsoap"
serviceClass="apps.vci.camel.erptest.ERPSoapImpl"
wsdlURL="META-INF/wsdl/GetHzCustDetailsService.wsdl"
endpointName="s:getHzCustDetailsPort"
serviceName="s:getHzCustDetailsService"
xmlns:s="http://apps.vci.camel.erptest" />
</beans>
When the data travels through the route this is the error I get:
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [select account_name from hz_cust_accounts where account_number=?]; SQL state [99999]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type
It's like the SQL component doesn't get the value that's in the header. I do log the value after I set it and I do see that it's set correctly because I get this back in my log:
[ qtp665755841-45] route1 INFO The header value is 4089699
Anyone have any idea why this might be happening to me?
Thanks
Force the header accountNumber to be an Integer:
<setHeader headerName="accountNumber">
<simple>${bodyAs(Integer)}</simple>
</setHeader>
There are a few types which have a shorthand notation, so we can use String instead of java.lang.String. These are: byte[], String, Integer, Long. All other types must use their FQN name, e.g. org.w3c.dom.Document (Camel documentation).

Dynamically selecting a RabbitMq queue in Exchange using spring integration

From producer I have to send message to an RabbitMQ Exchange. this message will contain specific attribute, for example , queue name, based on this attribute, I have to dynamically decide the queue to send this message.[queue to bind from exchange, to send this particular message].
is there any way to intercept the message arriving to a RabbitMQ Exchange, using spring integration, At present , I have the following spring integration config file.
I don't know to how to create a bean to get Exchange Messages and route the message to smsQueue, emailQueue etc., queues.
thanks for you suggestions and replies.
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration/amqp
http://www.springframework.org/schema/integration/amqp/spring-integration-amqp.xsd
">
<context:annotation-config></context:annotation-config>
<context:component-scan base-package="com.rabbit"></context:component-scan>
<rabbit:connection-factory id="connectionFactory"
host="localhost" username="guest" password="guest" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:template id="exchnageTemplate"
connection-factory="connectionFactory" exchange="COMMUNICATION-EXCHANGE" />
<rabbit:queue id="smsQueue" auto-delete="true" durable="false" />
<rabbit:queue id="emailQueue" auto-delete="true" durable="false" />
<rabbit:queue id="dvbQueue" auto-delete="true" durable="false" />
<rabbit:queue id="pbxQueue" auto-delete="true" durable="false" />
<rabbit:queue id="medsensorQueue" auto-delete="true"
durable="false" />
<int:gateway id="gateway" service-interface="com.rabbit.mq.ProducerGatewayInterface"
default-request-channel="producerChannel" />
<int:channel id="producerChannel" />
<int:channel id="errorChannel" />
<bean id="communicationInterface" class="com.rabbit.mq.CommunicationInterface" />
<amqp:outbound-channel-adapter channel="producerChannel"
amqp-template="exchnageTemplate" exchange-name="COMMUNICATION-EXCHANGE">
<int:service-activator input-channel="input"
ref="communicationInterface" method="optimalRoutingOfMessage" />
</amqp:outbound-channel-adapter>
With RabbitMQ (AMQP) you don't send to queues, you send to exchanges with a routing key, and bindings determine which queue(s) get the message.
<rabbit:direct-exchange name="si.test.exchange">
<rabbit:bindings>
<rabbit:binding queue="si_test_queue" key="si.test.binding" />
</rabbit:bindings>
</rabbit:direct-exchange>
<int-amqp:outbound-channel-adapter
channel="toRabbit" amqp-template="amqpTemplate" exchange-name="si.test.exchange"
routing-key="si.test.binding" />
Instead of routing-key you can use routing-key-expression with something like headers['foo'] or #someBean.determineRoutingKeyFor(payload).

Resources