How to read multiple files using camel pollEnrich? - apache-camel

I need to fetch multiple files from a directory using camel pollEnrich. When I searched for this implementation, I found out that camel pollEnrich will pick up only one file at a time. But it was given that we can fetch multiple files by repeating pollEnrich by loop. How can this be correctly implemented?
Sample code for current implementation below:
<camel:route id="fileRoute">
<camel:from uri="jetty:{{file.api.endpoint}}" />
<camel:convertBodyTo type="java.lang.String"/>
<camel:unmarshal ref="json" />
<camel:choice>
<camel:when>
<camel:simple>Condition check for validating the request</camel:simple>
<camel:pollEnrich timeout="5000">
<camel:simple>file:{{file.input.dir}}?preMove={{file.inprogress.dir}}&move={{file.processed.dir}}&filter=#fileFilter</camel:simple>
</camel:pollEnrich>
<!-- Logic -->
</camel:when>
<camel:otherwise>
<!-- Invalid request -->
</camel:otherwise>
</camel:choice>
</camel:route>
I also tried loop doWhile aproach, but it didn't work out for me. My requirement is to get all the files from a directory using camel pollEnrich.
Sample code for loop doWhile approach:
<camel:route id="fileRoute">
<camel:from uri="jetty:{{file.api.endpoint}}" />
<camel:convertBodyTo type="java.lang.String"/>
<camel:unmarshal ref="json" />
<camel:loop doWhile="true">
<camel:simple>Condition check for validating the request</camel:simple>
<camel:pollEnrich timeout="5000">
<camel:simple>file:{{file.input.dir}}?preMove={{file.inprogress.dir}}&move={{file.processed.dir}}&filter=#fileFilter</camel:simple>
</camel:pollEnrich>
<!-- Logic -->
</camel:loop>
</camel:route>

Related

Skip Camel Processor if Previous Processor Failed

I have a camel route that goes through a series of processors which each call some service. If processor 1 fails gracefully, I no longer want to call processors 2-5, but I do want to call consolidateResponse. The same for all the other processors. Is there a best practices way of achieving this without throwing an exception on failures?
<camel:routeContext id="myRouteRouteContext">
<camel:route id="my-route-route">
<camel:from uri="{{camel.uri.myRoute}}" />
<camel:process ref="{{bean.processor.processor1}}" />
<camel:process ref="{{bean.processor.processor21}}" />
<camel:process ref="{{bean.processor.processor3}}" />
<camel:process ref="{{bean.processor.processor4}}" />
<camel:process ref="{{bean.processor.processor5}}" />
<!-- Stringfy response object into a JSon text response -->
<camel:process ref="{{bean.processor.consolidateResponse}}" />
<!-- All catch exception handler -->
<camel:onException>
<camel:exception>java.lang.Exception</camel:exception>
<camel:handled>
<camel:constant>true</camel:constant>
</camel:handled>
<camel:to uri="{{camel.uri.error}}" />
</camel:onException>
</camel:route>
</camel:routeContext>
I think try catch is best solution also it is common programming solution also camel also has stop
https://camel.apache.org/manual/try-catch-finally.html
from("direct:start")
.choice()
.when(body().contains("Hello")).to("mock:hello")
.when(body().contains("Bye")).to("mock:bye").stop()
.otherwise().to("mock:other")
.end()
.to("mock:result");

camel: use header value in multiple routes

Is it possible to set a header in one route and then use it again later in another route in the same context?
For example, I have a route that sets a header as so:
<setHeader headerName="clientId">
<xpath>/Alarm/clientid/text()</xpath>
</setHeader>
The route uses Dead Letter Channel to send the message to an error route in the same context when delivery fails and I would like to use the clientId header I defined above in the message the error route sends, but currently calling the header returns nothing (an empty string I assume).
It should work , I am using camel 2.15.1 ,check the code below , if you run it you should see the header
<bean id="mybean" class="java.lang.Exception" />
<camel:camelContext xmlns="http://camel.apache.org/schema/spring"
trace="false">
<camel:errorHandler id="deadLetterErrorHandler"
type="DeadLetterChannel" deadLetterUri="direct:b">
</camel:errorHandler>
<camel:route>
<camel:from uri="timer:foo?repeatCount=1" />
<camel:setHeader headerName="myheader">
<camel:simple>Sundar</camel:simple>
</camel:setHeader>
<camel:to uri="direct:a" />
</camel:route>
<camel:route errorHandlerRef="deadLetterErrorHandler">
<camel:from uri="direct:a" />
<camel:throwException ref="mybean"></camel:throwException>
</camel:route>
<camel:route>
<camel:from uri="direct:b" />
<camel:log message="${in.header.myheader}"/>
</camel:route>
</camel:camelContext>
It should print a log like below
24 Feb 2016 19:09:47,707 route3 INFO Sundar

Exception handling Camel

I'm trying to pick a file from a directory, split a file and add each splitted lines to activemq. I'm facing a problem with exception handling during this process. Lets say a file in the directory is a binary file (executable), then splitter thows org.apache.camel.RuntimeCamelException and java.nio.charset.MalformedInputException exceptions. If this occurs, then I need to catch these exceptions, nothing should add in activemq and that just particular thread should exit after logging exception. Referred online and wrote the following code but don't know how to stop adding to activemq and quit specific thread.
<route id="msg_producer">
<from uri="input.file.from" />
<doTry>
<split parallelProcessing="true" executorServiceRef="msgProducer"
streaming="true">
<tokenize token="\n"></tokenize>
<to uri="input.activemq.to" />
</split>
<doCatch>
<exception>org.apache.camel.RuntimeCamelException</exception>
<exception>java.nio.charset.MalformedInputException</exception>
<handled> <constant>true</constant></handled>
<setBody>
<simple>${exception.stacktrace}</simple>
</setBody>
<setHeader headerName="CamelFileName">
<simple>${file:onlyname.noext}_error.log</simple>
</setHeader>
</doCatch>
</doTry>
</route>
as #claus Ibsen said to filter the files you can use a filefilter property so that you pick only files based on extension and some standard pattern something like this
<bean id="FileFilter" class="org.apache.camel.component.file.AntPathMatcherGenericFileFilter">
<!-- ? matches one character
* matches zero or more characters
** matches zero or more directories in a path -->
<property name="includes" value="#{databaseProperties.getProperties().getProperty('file.name.pattern')}"/>
<!-- if you wan to exclude specific files say bad in name or .exe files. Use comma to separate multiple excludes -->
<!-- <property name="excludes" value="**/*bad*,**/*.exe"/> -->
</bean>
and your file.name.pattern can be something like this **/contract.csv

Apache Camel - Delay when exception occurs

I have written a camel route that polls a file folder, picks up request, checks for memory consumption on server (in a java file). If its below threshold it drops the request on a JMS queue otherwise it throws an exception and picks it again for processing.
What i need to do is that when exception is thrown i need to delay processing for a configurable amount of time say 15 mins. This will give some time for server to stabilize instead of keeping it polling unnecessarily.
I am using errorHandler mechanism of camel however it doesnt seem to work. Camle keeps on picking up the request without any delay. Please help with this issue.
Below is the bundle context snapshot:
<camel:onException>
<camel:exception>java.lang.Exception</camel:exception>
<camel:redeliveryPolicy backOffMultiplier="500" />
<camel:log message="Default error handler was called"></camel:log>
</camel:onException>
<camel:route>
<!-- Reading from REST url -->
<camel:from uri="<my url>" />
<!-- If else loop -->
<camel:choice>
<camel:when>
<camel:xpath>Some path</camel:xpath>
<!-- Parsing OrderNumber and OrderVersion-->
<camel:log message="Recieved request ${headers.OrderNumber}-${headers.OrderVersion}.xml"/>
<camel:setHeader headerName="OrderNumber">
<xpath>Some path</xpath>
</camel:setHeader>
<camel:setHeader headerName="OrderVersion">
<camel:xpath>Some path</camel:xpath>
</camel:setHeader>
<!-- Request being put in file folder -->
<to
uri="file:data/inbox?fileName=${header.OrderNumber}-${header.OrderVersion}.xml"
pattern="InOut" />
</camel:when>
<!-- For all other requests put on queue -->
<camel:otherwise>
<camel:log message="Request ${headers.OrderNumber}-${headers.OrderVersion}.xml directly sent to queue"/>
<to uri="my queue"
pattern="InOut" />
</camel:otherwise>
</camel:choice>
</camel:route>
<camel:route errorHandlerRef="errorHandler">
<!-- Route to put message from folder to JMS queue if memory consumption is below limit-->
<camel:from uri="file:data/inbox"/>
<camel:process ref="checkMemoryConsumption"/>
<camel:convertBodyTo type="String" />
<camel:log message="Sucessfully processing service order ${headers.OrderNumber}-${headers.OrderVersion}.xml"/>
<to uri="my queue"
pattern="InOut" />
</camel:route>
Did you try redeliveryDelay of redeliveryPolicyProfile?
Below policy profile will retry 3 times with the delay of 1000mS between each try.
<redeliveryPolicyProfile id="myRedeliveryProfile"
maximumRedeliveries="3"
redeliveryDelay="1000" allowRedeliveryWhileStopping="false"
retryAttemptedLogLevel="INFO" />
Read more on here
By making below modification in my bundle context (bundle context displayed above), re-delivery policy kicked in and seems to do the trick.

Not seeing header or property in Camel route

I have the following Camel context XML. I set a header named MediaType. But, when I set a breakpoint in RenamerProcessor I don't see the header (I've also tried using setProperty with the same results. Being very new to Camel, I've found several examples that make it seem like the below should work.
What is wrong?
<camel:route>
<camel:from uri="file://c:/CamelTVInput" />
<camel:setHeader headerName="MediaType">
<camel:constant>T</camel:constant>
</camel:setHeader>
<camel:to uri="file://c:/CamelReadyToRename" />
</camel:route>
<camel:route>
<camel:from uri="file://c:/CamelReadyToRename?move=//c:/CamelBackup" />
<camel:process ref="RenamerProcessor" />
<camel:to uri="file://c:/CamelOutput" />
</camel:route>
You cannot transfer headers using files. eg when you write to a file, then its only the message body that is written as the file content.
But this is component specific if headers is part of the protocol, eg JMS, HTTP support headers.
If you want to keep files then use something else, Camel has some internal components like seda / direct.

Resources