Split header with tokenize by Spring DSL - apache-camel

It says https://camel.apache.org/components/latest/eips/split-eip.html#_using_tokenizer_from_spring_xml_extensions that you can use the tokenizer expression in the Spring DSL to split bodies or headers using a token.
How can I split header with tokenize (for example I have in the header with name 'split' string "A#B#C" and I need split it by token "#")?
I thought I could do it as follows
<split>
<header>split</header>
<tokenize token="#"/>
<to uri="mock:result"/>
</split>
But when I save this code, I get an error
java.lang.RuntimeException: validation error: cvc-complex-type.2.4.a:
Invalid content was found starting with element 'tokenize'. One of
'{"http://camel.apache.org/schema/spring":aop,
"http://camel.apache.org/schema/spring":aggregate,
"http://camel.apache.org/schema
Camel version 2.25.1

I found a solution, the tokenize language has an option 'headerName' (Name of header to tokenize instead of using the message body) https://camel.apache.org/components/latest/languages/tokenize-language.html.
This works
<split>
<tokenize headerName="split" token="#"/>
<to uri="mock:result"/>
</split>

Related

How to count substring instances in a exchange body

I have a body consisting of something like: OK,OK,NOK,OK,NOK, using Spring DSL.
I want to count the instances of substring 'OK' in the body. I tried StringHelper countChar, but you can only pass it chars.
Is there a way to count substrings in a body without resorting to java beans?
You can use bean to invoke an static method, such org.apache.commons.lang.StringUtils.countMatches to get the number of matches in the body:
from("direct:source")
.bean(StringUtils.class, "countMatches(${body}, OK)")
.to("log:org.orzowei.so.question.q69134695?level=WARN")
.end();
Or using Spring DSL:
<route id="abcRoute" autoStartup="true">
<from uri="direct:source"/>
<bean beanType="org.apache.commons.lang.StringUtils" method="countMatches(${body}, OK)"/>
<to uri="log:org.orzowei.so.question.q69134695?level=WARN"/>
</route>

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>

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

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>

Camel File Endpoint - Getting the file name

I have a camel route:
from("file:///u01/www/images/nonprofits-test?move=.done&preMove=.processing&filter=#nonpFileFilter&minDepth=2&recursive=true")
Later on in the route I need to access the origin file name. How do I get that information? All of the headers contain information in like ${file:name}, but not the actual file name.
Thanks in advance!
The base problem is that simple language is not being evaluated correctly in while running Camel with grails. This is being discussed further on the Camel user list.
there is a header called "CamelFileName" that stores this
see camel-file2 headers section for more details...
If your simple language is not working it would be because you are not using <simple> tag try something like below.
<route id="movedFailedFileForRetry">
<from uri="file:///opt/failed?delete=true" />
<log loggingLevel="INFO" message="Moving failed file ${header.CamelFileName} for retry" />
<choice>
<when>
<simple>${headers.CamelFileName} == 'file1.txt'</simple>
<to uri="file:///opt/input1" />
</when>
<otherwise>
<to uri="file:///opt/input2" />
</otherwise>
</choice>
</route>
Hope it helps!!
${headers.CamelFileName} will provide you with the CamelFileName that is read for processing. We have many other header properties that you can find from the Camel Documentation.

Resources