Camel, variables in SQL-Component - apache-camel

I have a blueprint in which i'm trying to write stuff to SQL (camel sql). I can't seem to extract the variables that I want to use:
<to id="myid" uri="sql:insert into RESTORE_DATA (feedFrom, queueId) values ('${headers.RESTORE_MESSAGEID}', '${headers.RESTORE_DEST}')?dataSource=myDataSource"/>
The variables from the header can't be resolved. I can see the real values if i use a log:
<log message="dest = ${headers.RESTORE_DEST}" loggingLevel="INFO"/>
What syntax should I use? Why do these variables start with '$' ?

Read the documentation, which shows you need to use syntax :#${header.xxx}: https://github.com/apache/camel/blob/master/components/camel-sql/src/main/docs/sql-component.adoc
eg
<to id="myid" uri="sql:insert into RESTORE_DATA (feedFrom, queueId) values (':#${headers.RESTORE_MESSAGEID}', ':#${headers.RESTORE_DEST}')?dataSource=myDataSource"/>
Also the title of this question is misleading

Related

jboss fuse xquery custom functions

We have existing xqueries which we want to re use in our new JBoss fuse integration applications. As part of that I am trying to use XQuery component of JBoss Fuse 6.3. My question is how to pass arguments to my XQuery Function. This is my camel context
<camelContext id="dataConsumer-context" xmlns="http://camel.apache.org/schema/blueprint">
<propertyPlaceholder id="properties" location="classpath:sql.properties"/>
<route id="consumer-route">
<from id="_from1" uri="activemq:queue:house"/>
<log id="inputMessage" message="Got ${body}"/>
<to id="_to1" uri="xquery:myXquery.xquery"/>
<log id="transformedMessgae" message="Got ${body}"/>
<to id="_to2" uri="sql:{{sql.insertIntoMessage}}"/>
<log id="_log2" message="Message is inserted into DB"/>
</route>
</camelContext>
In myXquery.xquery this is the function I have
declare function xf:myPayments($pmtAddInp1 as element(ns0:PmtAddInp),
$header as element(*), $PaymentConstants as element(*)) as element() { }
declare variable $pmtAddInp1 as element(ns0:PmtAddInp) external;
declare variable $header as element(*) external;
declare variable $PaymentConstants as element(*) external;
xf:myPayments($pmtAddInp1,$header,$PaymentConstants)
I really appreciate if anybody can answer my question.
Everything in the Camel Exchange is visible to your XQuery. For example, you can put the desired arguments as headers within your Camel Route, then within your XQuery you define them as declare variable $in.headers.myArgumentKey as xs:string external; and they will be available for your functions to use directly as a variable called $in.headers.myArgumentKey
In addition to Gerry's answer:
body passes to XQuery component as root element.
Let say I have inbound body as
<Auth>
<userName>JohnDoe</userName>
<userPassword>abcd1234</userPassword>
</Auth>
then I can have XQuery to transform it and it may look like:
declare variable $in.headers.referenceId as xs:string external;
declare function transformRequest($requestBody as element()) as element() {
<newRequest>
<RqUID>{$in.headers.referenceId}</ser:RqUID>
<UserPrincipal>{$requestBody/userName/text()}</UserPrincipal>
<UserCredentials>{$requestBody/userPassword/text()}</UserCredentials>
</newRequest>
};
let $request := /*[1]
return buildNewRequest($request)
As you can see let $request := /*[1] sets internal variable $request to the root element of the message body.
PS. $in.headers.referenceId is a variable I can set into headers in Camel Route before calling my XQuery

Apache Camel - JSONPath expressions to fetch multiple values

In a camel route need to read values from an incoming json data through rest client. Using JsonPath to parse and get the values from it.
The expression used to fetch the json data works for one value and not for the other.
The JSON data incoming form the rest client:
[{"var1": 10,"var2": 20}]
JSONPath expression used inside the camel route:
<setHeader headerName="data1">
<jsonpath suppressExceptions="true">$[0].var1</jsonpath>
</setHeader>
<log message="value1 : ${header.data1}" />
<setHeader headerName="data2">
<jsonpath suppressExceptions="true">$[0].var2</jsonpath>
</setHeader>
<log message="valu2 : ${header.data2}" />
Can see the value getting logged in the first logger, but the second logger is 'null' and camel throws an 'NullPointerException'.
Question:
Can some one guide me if this is the right json path expression to get the values. If not do guide me to a solution.
Have checked the expressions working and returning values using various online tools available for json path.

Apache Camel - from netty to file

I'm using the netty component for socket communication between two systems, request and
response.
This is the route
<from uri="netty:tcp://localhost:61616?encoder=#encoder"/>
<to uri="netty:tcp://localhost:61618?decoder=#decoder"/>
<log message="Receive ${body}">
<to uri="file://data?fileName=data2&charset=utf-8"/>
Everything, works fine, the data I send is buffer type, as well as the response received. I can see this data as String using the log ${body}, but there's nothing in the file where is suppossed to store this data.
I'm guessing that camel uses a converter (from buffer to string) for logging the body as plain text, but why is not saving something in the file, using a default converter for this????
I appreciate any comments of how to resolve this. Thank you !!!
Since your paylaod is ByteBuffer you need to explicitly convert to either String or byte[]
<from uri="netty:tcp://localhost:61616?encoder=#encoder"/>
<to uri="netty:tcp://localhost:61618?decoder=#decoder"/>
<convertBodyTo type="byte[]"/>
<log message="Receive ${body}">
<to uri="file://data?fileName=data2&charset=utf-8"/>
You can even use type="java.lang.String"
Please refer to the link http://camel.apache.org/type-converter.html
Hope it helps...

How to split existing collection in Camel

I have a producer which sends a Set<Status>. I want to split the Set so downstream components have to process single Status objects. My route looks like this:
public Set<Status> loadStatus() { ... }
from("direct:start").
split().
to("mock:end");
ProducerTemplate template = context.createProducerTemplate();
template.sendBody("direct:start", loadStatuses());
How is this achieved?
the Camel Splitter documentation describes how a Collection, Iterator or Array can be used...
A common use case is to split a Collection, Iterator or Array from the
message. In the sample below we simply use an Expression to identify
the value to split.
from("direct:splitUsingBody").split(body()).to("mock:result");
from("direct:splitUsingHeader").split(header("foo")).to("mock:result");
In Spring XML you can use the Simple language to identify the value to
split.
<split>
<simple>${body}</simple>
<to uri="mock:result"/>
</split>
<split>
<simple>${header.foo}</simple>
<to uri="mock:result"/>
</split>
Turns out the docs are a bit unclear: none of the examples explicitly mention having a body that's a Java collection. The solution is to split the body without any expression. In that case, Camel will use it's internal conversion engine to return an Iterator from a Set. The final route is:
from("direct:start").
split(body()).
to("mock:end");
Found a reference in the Camel JDBC samples documentation:
from("direct:hello")
// here we split the data from the testdb into new messages one by one
// so the mock endpoint will receive a message per row in the table
.to("jdbc:testdb").split(body()).to("mock:result");

How to call setter method on ${body} in a Camel route?

I have tried to set a property on the body of a Java bean constituting the message in transit through a Camel route. I have tried various approaches e.g.
<route>
...
..
<transform>
<simple>${body.label} = ${property.label}</simple>
</transform>
...
..
</route>
in this particular case the ${body} is a Java bean with a setLabel(String label) method and the ${property.label} is set by other means in another route. In this example the result is not the desired (and I understand why), i.e. after the transform the body of the message is replaced with the ${body.label} = ${property.label} string.
My current work-around is to manually code a transformer as a Spring bean and set the label property of the Java bean in code but I like to find out if there is a simpler/smarter way to achieve this, preferably in XML DSL which is what I use?
Regards, Ola
I'm not sure if it's possible with simple, but you could do it using groovy:
<setBody>
<groovy>request.body.label = exchange.getProperty('label')
return request.body
</groovy>
</setBody>
Maybe it can help someone in the future:
As I know You can use standard Java approach with settters anf getters in body:
.split(body())
.setBody(simple("${body.setLogin('TEST')}"))
.end()
It works inside <split></split>. Maybe inside another blocks.

Resources