How to access exchange headers in the xquery? - apache-camel

Can not get values out of exchange headers in a xquery. Getting for example
Caused by: net.sf.saxon.trans.XPathException: Unresolved reference to variable $in.headers.sourceSystem.
It is described here https://camel.apache.org/xquery.html
I'm using camel 2.21.3 running in Spring boot.
<route id="exampleRoute">
<from uri="direct:start" />
<setHeader headerName="sourceSystem">
<constant>PR0</constant>
</setHeader>
<transform>
<xquery>
element item {$in.headers.sourceSystem}
</xquery>
</transform>
<to uri="mock:result"/>
</route>
Expected result would look like
<item>PR0</item>

It is very straightforward but could be mentioned in the documentation.
<transform>
<xquery>
declare variable $in.headers.sourceSystem external;
element item {$in.headers.sourceSystem}
</xquery>
</transform>

Related

Camel blueprint <setHeader headerName="CamelHttpPath" id="_setHeader1"><el>${header.uriPattern}</el></setHeader> waiting for dependencies

I have the following Camel Context.
<camelContext id="_camuatomicservicecontext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="_camuatomicserviceroute1">
<from id="_from1" uri="direct-vm:camuatomicservice">
<description>accepts vm messages directly </description>
</from>
<log id="_log1" message="Camu Atomic Service body = ${body}, header= ${header.uriPattern}"/>
<!-- <to id="_to1" uri="restlet:protocol:localhost:8189/"/> -->
<setHeader headerName="api.key" id="_setHeader1">
<constant>replace later with properties api.key Does not matter for this poc</constant>
</setHeader>
<setHeader headerName="CamelHttpPath" id="_setOutHeader1">
<el>${header.uriPattern}</el>
</setHeader>
<to id="_to1" pattern="InOut" uri="netty4-http:http:localhost:8189/path"/>
<log id="_log2" message="CamuAtomicService Response body ${body}"/>
</route>
</camelContext>
From the documentation I expect the CamelHttpPath header to override the endpoint configuration "/path" such that calling Facade Services can pass the header.uriPattern in and dynamically change the resource they want to access. The bundle worked fine until I added the setHeader for CamelHttpPath and now getting "Waiting for dependencies." I assume I need to install a feature, but Simple EL in other bundles on that server work already so not sure what feature I need to install.
Instead of I used and it worked fine. The choice was farther down in the options.

How can i add the options of a REST call to a header as a parameter?

I am using an ESB to route data between SQL and REST calls. So far this is working fine, however when i want to add options to the REST call. For example:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<propertyPlaceholder id="placeholder"
location="file:${karaf.home}/etc/nl.test.astron.sql.cfg" />
<restConfiguration bindingMode="json" component="servlet">
<endpointProperty key="servletName" value="ASTRONServlet" />
</restConfiguration>
<rest path="/get/astrondata">
<get uri="">
<to pattern="InOut" uri="direct:get" />
</get>
</rest>
<route id="get_to_uri">
<from uri="direct:get"/>
<setHeader headerName="boundRaMin">
<simple>70</simple>
</setHeader>
<setHeader headerName="boundRaMax">
<simple>90</simple>
</setHeader>
<setHeader headerName="boundDecMin">
<simple>0</simple>
</setHeader>
<setHeader headerName="boundDecMax">
<simple>30</simple>
</setHeader>
<to uri="sql:{{sql.getDatabase}}?
outputType=SelectList&
greedy=true&
useIterator=false"/>
</route>
and the SQL code is:
sql.getDatabase=SElECT * FROM dbo.astron_data WHERE :#boundRaMin<ra AND
ra<:#boundRaMax AND :#boundDecMin<dec AND dec<:#boundDecMax
As one can see here, boundRaMin,boundRaMax,boundDecMin,boundDecMax are all set by in the headers, However i want to make these variable depending on the options defined in the rest call. Thus for example the following call:
http://localhost:8080/astron/get/astrondata?boundRaMin=value1&boundRaMax=value2&boundDecMin=value3&boundDecMax=value4
should fill the right values of value1...value4 into the headers. It seems that these query parameters do not get mapped to the headers.
According to camel-sql component, from Camel 2.14 onward you can use Simple expressions. Thus try to modify the property placeholder sql.getDatabase to the following:
sql.getDatabase=SELECT * FROM dbo.astron_data WHERE :${header.boundRaMin} < ra AND
ra < ${header.boundRaMax} AND ${header.boundDecMin} < dec AND dec < ${header.boundDecMax}

apache camel hazelcast getting custom header

I am trying to get the header or property which i set before calling hazelcast but i couldn't able to get the custom header which i set.
<route>
<from uri=""/>
<setHeader headerName="CamelHazelcastObjectId">
<constant>123</constant>
</setHeader>
<setHeader headerName="CamelHazelcastOperationType">
<constant>put</constant>
</setHeader>
<setHeader headerName="test">
<constant>test</constant>
</setHeader>
<setProperty propertyName="test">
<constant>test</constant>
</setProperty>
<to uri="hazelcast:map:testMap"/>
</route>
When i trying to retrieve my custom header or property couldn't able to get that
<route>
<from uri="hazelcast:map:testMap"/>
<log message = "printing:::: ${in.header.test} and ${property[test]}"/>
<to uri=""/>
Please help on this.
The camel-hazelcast component is only for storing the message body, not message headers.

Can we use multiple mutlicast in apache camel?

I have a requirement where i want to use mutlicast in Apache Camel for than single time in a single route. i.e Multicast within a multicast.
<routeContext id="myRoute" xmlns="http://camel.apache.org/schema/spring">
<route id="myRouteId">
<from uri="activemq:queue:{{XXXX.queue}}" />
....
<multicast parallelProcessing="true">
<pipeline>
##everything working fine here
</pipeline>
<pipeline>
<multicast>
<pipeline>
<log message="Inserting in database now"></log>
<transform>
<method ref="insertBean" method="myBatchInsertion"></method>
</transform>
<choice>
<when>
<simple>${in.header.myCount} == ${properties:batch.size} </simple>
<to uri="sql:{{sql.core.insertMyQuery}}?batch=true"></to>
<log message="Inserted rows ${body}"></log>
</when>
</choice>
</pipeline>
</multicast>
</pipeline>
</multicast>
</route>
</routeContext>
Is it possible to do that?
When i am trying to do that, my program is not getting executed successfully.
Is the unsuccessful execution is a result of mulitple multicast?
Can anybody help?
I got the reference from following link:
http://camel.apache.org/multicast.html
Why do you use pipeline? It "is" pipeline by default.
Also all the log and transform and choice statements can be put outside of the multicast. And since you are generating your endpoints dynamically, put the values in a header and use recipientlist for dynamic endpoints. Multicast is for hard-coded endpoints. Here is an example:
<route>
<from uri="direct:a" />
<!-- use comma as a delimiter for String based values -->
<recipientList delimiter=",">
<header>myHeader</header>
</recipientList>
</route>
http://camel.apache.org/recipient-list.html

Apache Camel: Send empty body ws

How can i call a SOAP web service with an empty message body using Apache Camel?
For example, the final endpoint on a route would be the invocation of a method on my proxy that takes 0 arguments.
EDIT:
example xml configuration:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
...
<cxf:cxfEndpoint id="someWS" address="${ws.address}"
serviceClass="com.example.ws.SomeWS"
The problem is that the method 'invoke' on the WS takes 0 arguments, and an exception is thrown stating that 1 argument is being received. Is there a way for me to specify to ignore this received input?
You can set the message body to be null, if the invocation just take 0 argument. null simple expression is added since camel 2.12.3.
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setBody>
<simple>null</simple>
</setBody>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
I also needed to set an empty body to Apache Camel xml and the solution below worked for me.
<setBody id="set-empty-body">
<constant/>
</setBody>
Hope this helps to whoever need it.
The xml configuration will fail if the content of the body is not with the correct type of the class required by the method of your bean. By default, it could be an Object and not a String. When the method recieves the body in an incorrect format, it would process a null value, instead of the body of the route. To solve this problem, you will need to convert the body into the expected class of the method of your bean. For example, if the method's argument of the bean is a String, then you could do something like:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<convertBodyTo type="String"/>
<to uri="cxf:bean:someWS"/>
</route>
For more information about body conversion, you can check the docs: https://camel.apache.org/components/3.14.x/eips/convertBodyTo-eip.html

Resources