Apache Camel - from netty to file - apache-camel

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

Related

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 Send Nothing To ActiveMQ Queue

I want to send xml files content to queue. Right now I'm using this configuration :
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:H:/test/file"/>
<recipientList>
<xpath resultType="String">/data/destination/text()</xpath>
</recipientList>
</route>
And my xml file content :
<data>
<destination>activemq:queue:queueA</destination>
<content>7500</content>
</data>
This config successfully send a message to queueA, but it has no content(empty message), so what is wrong with this configuration? Or is there any better way to send file content to a queue? Thanks
If the message body is empty then this FAQ may help explain why: http://camel.apache.org/why-is-my-message-body-empty.html
You likely need to enable stream-caching: http://camel.apache.org/stream-caching.html

infinite message delivery loop with activeMQ and Broker Camel Component

I'm using activeMQ 5.9.
I'm trying to implement an interception type route in my activemq.xml, where I check if a particular header equals some value then send it to a different queue, otherwise allow it to continue.
I'm following the info here: http://activemq.apache.org/broker-camel-component.html
My camel.xml file looks like this:
<camelContext id="camel" trace="false" xmlns="http://camel.apache.org/schema/spring">
<route id="routeAboveQueueLimitTest">
<from uri="activemq:queue:do.something"/>
<choice>
<when>
<simple>${header.scope} == 'test'</simple>
<to uri="activemq:queue:test.do.something"/>
</when>
<otherwise>
<to uri="activemq:queue:do.something"/>
</otherwise>
</choice>
</route>
</camelContext>
Then when I put a message on "activemq:queue:do.something" with header called scope = "test" it correctly routes to the "activemq:queue:test.do.something" queue. However, when it doesn't have that header, it puts it back on the "activemq:queue:do.something" queue and processes it again and again and again!
That kind of seems logical, but the above page clearly says that you have to explicitly send it back to the broker component, and the 2nd example on the page shows exactly that.
I realise this could be worked around by sending it to a different queue if it doesn't have the header but that is undesirable at this stage.
I think the intercept pattern would be much better suited for what you are looking.
<intercept>
<when><simple>${header.scope} == 'test'</simple></when>
<to uri="activemq:queue:test.do.something"/>
</intercept>
More info here: http://camel.apache.org/intercept.html
This will allow messages without the scope header set to 'test' to continue, but will redirect messages that do have the test header.
InterceptSendToEndpoint is a better option here...
<interceptSendToEndpoint uri="activemq:queue:do.something">
<when><simple>${header.scope} == 'test'</simple></when>
<to uri="activemq:queue:test.do.something"/>
<stop/>
</interceptSendToEndpoint>

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>

How to set endpoint specific header value in Camel Multicast

I want to set the endpoint specific header value in Multicast component.
XML DSL as below:
<route>
<from uri="direct:testRoute"/>
<multicast strategyRef="MyAggregator" parallelProcessing="true">
<to uri="direct:call1"/> <!-- set the header MY_HEADER = "call_1" -->
<to uri="direct:call2/> <!-- set the header MY_HEADER = "call_2" -->
</multicast>
</route>
Basically in the response aggregation I want to know, to which service request this response belongs to.
I tried by doing this, but its not the correct way (parse exception):
<to uri="direct:call1">
<setHeader headerName="MY_HEADER"><simple>call1</simple></setHeader>
</to>
What I see from reading the documentation is that, multicast will copy the source Exchange and multicast each copy. So its a shallow copy of the Exchange and kind of reference shared between all the multicast recipient.
But here I am looking for specific header value for individual recipient.
How to do this? Any pointers?
You can't do that in the multicast route. But it should be simple in the direct route afterwards.
<route>
<from uri="direct:call1"/>
<setHeader headerName="MY_HEADER"><simple>call1</simple></setHeader>
.. do whatever
</from>
</route>
otherwise, if call1 is used for other things and you cannot know when to put the header once in that route, make a simple prep-route:
<route>
<from uri="direct:prepCall1"/>
<setHeader headerName="MY_HEADER"><simple>call1</simple></setHeader>
<to uri="direct:call1"/>
</from>
</route>
As a third option, even though you cannot place DSL (xml or java) in the multicast list, you can supply an "onPrepareRef" processor bean that adds the headers to your exchange. But one processor will handle all multicast endpoints.
There is a header with the key Exchange.TO_ENDPOINT that you can see which of the 2 endpoints the response is from.

Resources