Camel rename file after Timer - apache-camel

In Camel, is there any way to rename a file after a set period of time, using the Timer component and a Spring configuration, if the file already exists?
Is it only achievable by having a Timer route that calls a Java method that will rename the file?
So, I have a socket I want to pull data from. The data flows all day, every day. Because of that, I do not just want to keep routing the data into one specific file.
So my thought process led me to just rename the existing file after X period of time and let the Netty route create a new file since it wouldn't exist anymore after the renaming.
I have a route similar to:
<route customId="true" id="socketToFileRoute">
<from uri="netty4:tcp://localhost:9999?clientMode=true&textline=true" />
<transform>
<simple>${in.body}\n</simple>
</transform>
<to uri="file://data?fileName=socketData.txt&charset=utf-8&fileExist=Append"/>
</route>
Is there a way to set up a Timer route along the lines of the following?:
<route customId="true" id="dataFileRenamer">
<from uri="timer://renameFile?fixedRate=true&period=50"/>
<to uri="file://data/socketData.txt?rename the file created in the previous route" />
</route>

You don't need a timer or anything complex, you should just use toD (Dynamic To endpoint):
<route customId="true" id="socketToFileRoute">
<from uri="netty4:tcp://localhost:9999?clientMode=true&textline=true" />
<transform>
<simple>${in.body}\n</simple>
</transform>
<toD uri="file://data?fileName=socketData-${date:now:yyyyMMddHHmmss}.txt&charset=utf-8&fileExist=Append"/>
</route>
This will resolve the endpoint dynamically for each message, resulting in a new file being generated each second, or whatever period you want to use.

You cannot rename the file, at least not that I am aware of. You could via the timer node enrich your route by reading content of the existing file using the .enrich() syntax and then create a new file with a new timestamp. A rough example:
.from("timer://renameFile?fixedRate=true&period=50")
.enrich("file://pathtofile?fileName=<filename>")
.to("file://pathtofile?fileName=${file:name.noext}-${date:now:yyyyMMdd-HHmmss}.${file:ext}");
Something along those lines. Off course this means you generate a new file for every period. If you really want to rename, then I guess you would have to create a processor class and use the standard java API to see if you can consume and rename it.

Related

Camel blueprint update cfg file property value

We have a route with a scheduler of every 30 seconds, which reads a value from a cfg property file. If the property key value is "Y" then we have certain procedures to perform. If the property key value is 'N' then we have to skip the process.
We have an admin web application to send value to camel route thru tcp communication.
My question is while receiving value from the external application we have to update the cfg file value in a camel route, we are receiving the value in camel route but updating the cfg property file we got struck.
I created a test router for reference
<route id="test-route-timer">
<from uri="timer:foo?period=5s" />
<setProperty propertyName="callInterfaceProcedure">
<simple>{{call.interface.procedure}}</simple>
</setProperty>
<log message="${property.callInterfaceProcedure}"/>
<setProperty propertyName="callInterfaceProcedure">
<simple>N</simple>
</setProperty>
</route>
Please advice in this case.
Assuming your cfg holds the problem in key=value format, you can write the data to the file by setting the body.
<setBody>
<simple>callInterfaceProcedure={{call.interface.procedure}}</simple>
</setBody>
and then you can write to the file using file component like
<to uri="file:<path cfg>?filename=myprooperties.cfg&append=true
This will keep on adding new entries to properties. To circumvent this problem, you can load the whole file contents in the memory as map, update values and overwrite the contents of the file.

How to read two pair of files in same directory and send to same camel exchange?

I need to read pair of files with same name but different extension in same directory say for example
1. abc.json
2. abc.signed
above files should be sent same camel exchange, where value from abc.signed is used to validate the abc.json file.
Please advise !!!
Use pollenrich to read both kind of file in a single route and then perform validation within that route.
<pollEnrich timeout="5000"><simple>file://pathto//yourfile?antInclude=*.json&noop=true</simple>
</pollEnrich>
<setHeader headerName="JSON">
<simple>${body}</simple>
</setHeader>
By doing so, you can able to get both json and signed values.

Moving Multiple file from one folder to another based on filename - camel

I have one requirement, where I need to move multiple files present in one folder to another. This should be done based on filename which should be dynamic.
As Far I have tried out pollenrich and file (antInclude) but in both case I got struck.
<route id="readFile" autoStartup="true">
<from uri="timer://timer1?repeatCount=1"/>
<setHeader headerName="xxx">
<simple>1234</simple>
</setHeader>
<pollEnrich timeout="15000">
<simple>file://{{baseDirectory}}?move={{destinationDirectory}}&antInclude=*_${header.xxx}.txt</simple>
</pollEnrich>
</route>
Note: Header value will be dynamic, using javascript will pull that data and set it in header.
Any help on this would most welcome.
Thank you for all your response,
I achieved it by using pollenrich but tweaking something in pollenrich.
Got CamelBatchsize using pollenrich.
Running into a loop using size.
Using the above code used to move the file. I achieved it.
Thanks.

Sql timeout. Camel-context Bean fails for multiple files

I run an automatic route when files are dropped in a folder
<route id ="automatic-route">
<from uri="file:C:/pathToFolder?noop=true"/>
<to uri="bean:automaticBean"/>
<to uri="activemq:STARTFLOW.Q"/>
</route>
I move the file in a subfolder called "done" with java methods in my Bean AutomaticBean.java.
Then I start another route to process the file.
<route id ="process-route">
<from uri="direct:process"/>
<to uri="bean:processBean"/>
</route>
When I move multiple files in the folder they are correctly moved to the subfolder (through my Bean. I use java method to move them). But then the second bean (file processing and SQL queries) has timeoutException because the files are moved and processed at the same time.
For example when I move 5 files 3 of them are correctly processed but then the last ones have a timeoutException. Is it possible to run the second route for each files one by one (schedule them or something like that)? And only start the second route for a file when the previous file is correctly processed?
I tried with noop=false;move=done and I have infinite loop problems and I cannot process the files because they moved. That's why I use noop=true. Furthermore my problem is about the second route (the files are all correctly moved).
Thanks.
One solution can be to poll the /done folder for the new files (which have been processed and moved by your automaticBean). In this case you have to use readLock or doneFileName to check if the file isn't locked by another process.
<route id ="process-route">
<from uri="file:C:/pathToFolder/done?readLock=changed"/>
<to uri="bean:processBean"/>
</route>
Actually adding a delay an set maxMessagePerPoll to 1 did the trick
<route id ="process-route">
<from uri="file:C:/pathToFolder/noop=true&delay=10000&maxMessagesPerPoll=1"/>
<to uri="bean:processBean"/>
</route>

Symbolic link in camel sftp endpoint

I have some problems using a filter attribute in an sftp-endpoint containing few symbolic links. My route looks as follows:
<route id="test1">
<from uri="sftp://myhost/../../my_storage/dir_with_symlinks?username=user&password=mypass&recursive=true&stepwise=false&filter=#MyFileFilter"/>
<to uri="file:/tmp/sftp/myout"/>
</route>
In MyFileFilter.accept(GenericFile<T> file) I get only all linked directories as RemoteFile<T> but the files in it won't be seen.
Obviously, I am missing some part of code. Any idea how could I solve the problem?

Resources