Apache Camel - JSONPath expressions to fetch multiple values - apache-camel

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.

Related

How to filter jms message in apache camel xml configuration file

I wish to create jms subscriber on a general topic. to avoid unwanted messages i wish to create a filter there. the problem is the syntax is available every where from java code but I can not find how to do same in xml configuration file like blueprint.xml
Java code
String redSelector = "color='red'";
MessageConsumer redConsumer = redSession.createConsumer(queue, redSelector);
Apache camel route
<route id="externalNotificationsDispatchRoute" >
<from uri="activemq:queue:{{vqueue.name}}" />
.. filtering part
<to uri="log:com?level=DEBUG" />
</route>
JMS Message Selector is specified with selector URI parameter.
Blueprint:
<from uri="activemq:queue:{{vqueue.name}}?selector={{vqueue.selector}}" />
Property file:
vqueue.selector=color%3D'red'
Refer JMS component documentation (ActiveMQ component iherits the parameters from the JMS component)
selector
Sets the JMS Selector, which is an SQL 92 predicate that is used to filter messages within the broker. You may have to encode special characters like '=' as %3D.

Camel-http httpclient timeout from exchange headers

I have a http component in my route in which I want to pass timeout value from exchange header's.
http://foo.com?httpClient.soTimeout=5000
How can we do this in Spring DSL.
Is is possible to do something like:
<to uri="http://foo.com?httpClient.soTimeout=${in.headers.timeout}"/>
Unfortunately, no, <to> DSL will create the endpoint and the producer before any exchange is received and for HTTP component SO_TIMEOUT is not a parameter that you can change in runtime (here's a list of what you can change).
That being said, if you are using Camel 2.16+ you can easily do it with Dynamic To endpoint. In your case that would be:
<toD uri="http://foo.com?httpClient.soTimeout=${in.headers.timeout}"/>
Otherwise, you'll have to use the Dynamic Recipient List EIP:
<setHeader headerName="theHeader">
<simple>http://foo.com?httpClient.soTimeout=${in.headers.timeout}</simple>
</setHeader>
<recipientList>
<header>theHeader</header>
</recipientList>

Camel HTTP End point Special Charcter(+) issue

I am having issues hitting an http end point via camel recipientlist(2.14).
<route id="httpexecutor">
<from uri="direct:httpexecutor" />
<process ref="httpPreprocessor" />
<recipientList>
<simple>${property[inputSearchParameter.url]}</simple>
</recipientList>
</route>
When the url has a + sign(in one of the parameters) then its breaking.
I also tried %2B then it is getting converted to space.
There is a JIRA:
https://issues.apache.org/jira/browse/CAMEL-6176
However when i am using RAW its not working and getting the following trace(seems like RAW is passed to the service):
Caused by: java.net.URISyntaxException: Illegal character in query at index 558: http://someurl?facet=true&binary=true&-fq=nm_task_type%3A%28OTM_QUERY+OR+OTM_CLIENT_QUERY%29&facet.query=%7B%21key%3D%22%5B*+TO+NOW-30%5D%22%7Ddt_created%3A%5B*+TO+NOW-30DAY%5D&facet.query=%7B%21key%3D%22%5BNOW-30DAY+TO+NOW-15DAY%5D%22%7Ddt_created%3A%5BNOW-30DAY+TO+NOW-15DAY%5D&facet.query=%7B%21key%3D%22%5BNOW-15DAY+TO+NOW-7DAY%5D%22%7Ddt_created%3A%5BNOW-15DAY+TO+NOW-7DAY%5D&facet.query=%7B%21key%3D%22%5BNOW-7DAY+TO+NOW-1DAY%5D%22%7Ddt_created%3A%5BNOW-7DAY+TO+NOW-1DAY%5D&facet.query=RAW({!key="[NOW-1DAY TO NOW]"}dt_created:[NOW-1DAY TO NOW+1DAY])&q=*%3A*&rows=0
at java.net.URI$Parser.fail(URI.java:2829)
at java.net.URI$Parser.checkChars(URI.java:3002)
at java.net.URI$Parser.parseHierarchical(URI.java:3092)
at java.net.URI$Parser.parse(URI.java:3034)
at java.net.URI.<init>(URI.java:595)
at org.apache.camel.util.URISupport.createURIWithQuery(URISupport.java:334)
at org.apache.camel.util.URISupport.createRemainingURI(URISupport.java:428)
at org.apache.camel.component.http.HttpComponent.createEndpoint(HttpComponent.java:248)
at org.apache.camel.impl.DefaultComponent.createEndpoint(DefaultComponent.java:122)
at org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:525)
... 52 more
Any help appeciated.
I haven't tested this, but can you set header "CamelHttpPath" to your URL before passing to Camel HTTP component and see if it helps:
<setHeader headerName="CamelHttpPath">
<simple>YOUR_URL</simple>
</setHeader>

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");

Apache Camel transform not working

I have this Camel Route:
<route id="externalRestPushRoute">
<from uri="jms:pushProcessedRecordsToExternal" />
<setHeader headerName="PAYLOAD">
<simple>body</simple>
</setHeader>
<marshal ref="jack"></marshal>
<to uri="http://localhost/front/rest/karec/dummy-push"/>
<transform>
<simple>in.header[PAYLOAD]</simple>
</transform>
<to uri="bean:noAuthRecordPersistenceService?method=deliverySuccess" />
</route>
The idea is this:
I want to deliver an object in JSON format to a REST endpoint(all the headers are properly set and the rest endpoint receives the json format)/
To convert the object to JSON format I use marshal and it works.
Now, the response back from the http endpoint is of type java.io.InputStream but I don't care.
What I care is converting the body back to the original object before it was marshaled.
I did save the object in a header before marshaling in a header named PAYLOAD.
Now I want to use transform to get it back into the body of the message.
Well, that does not seem to work. When it get to the last bean it complains that body is still of type java.io.InputStream.
Stores the body on the exchange property instead of a header, that is safer.
<setProperty propertyName="PAYLOAD">
<simple>body</simple>
</setProperty>
<transform>
<simple>${property.PAYLOAD}</simple>
</transform>

Resources