Reuse consumer to fetch extra content from the same endpoint - apache-camel

I have an Apache Camel route which purpose is to fetch xml-documents and files linked in the document.
<route id="route-ftp">
<from uri="ftp://foo#server:21/data?password=xxx&include=.*.xml"/>
<to uri="myBean"/>
</route>
When it reaches myBean I want to parse the file and use the same ftp settings to fetch the files listed in the xml-file.
Or perhaps fetch them all at the same time using xpath.
<root>
<article>
<headline>Headline</headline>
<image src="images/cat.jpg"/>
</article>
</root>
The filenames is taken from the above xml image tag and src attribute.
I then want to deliver the original file together with my images in a package.
I can't find the right approach to my problem.

I would probably do it this way.
Depending on how your file is structured, I would consume it as you have done. I would then split the body per row (assuming each row contains a filename). The split is done using the splitter EIP. Now each body contains the file name.
I would then use Camel's dynamicTo to enrich the route with the file using the ftp parameters. You can save the ftp parameters are properties so that they are always the same.
In this way, you fetch the list, iterate over the list and fetch the file for every row in the list.

Related

Filtering the list of files based on the value obtained from another file (Apache Camel File component)

I need to create a file filter (to pick files from a folder) based on the content received from another file.
I set up a route like this:
File1 Url -> pollEnrich(File2 Url with filter, aggregationStrategy) -> log
But the issue is that in pollEnrich, the value obtained from File1 is not available. Hence I am not able to create a filter based on which I have to pick the files from Folder2.
I tried both the filer option in the URL as well as the programmatic filter (by extending GenericFileFilter class). Any suggestions are very much appreciated.
Recall the fact from content-enricher,
pollEnrich only accept one message as response
The pollEnrich will collect single file when call with file component. Thus, you should use file component with fileName option inside pollEnrich to collect single file and use while loop to call pollEnrich multiple time.

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.

How to use Camel's Exchange setProperty in content enrich()?

I have a camel route that splits and aggregates according to some ids. When an id is retrieved, a call is made to another endpoint to retrieve the project information according to this id. After retrieving the project information i had to enrich it by calling multiple enrich() methods on it. In the first enrich method i have to do some xpath processing wherein ill be able to retrieve a primaryOrgId value that i will set as a property in the exchange, dont worry about the xpath processing, i had that sorted out but my problem is when I set the property (primaryOrgId) inside the 1st enrich. The property value doesn't get persisted when the route goes to the 2nd enrich part. When I log the primaryOrgId value, the original value of "testValue" (this was set in the direct:createSomeIds route) is the one getting displayed instead of "changeTheValueHere" which was set in the 1st enrich part.
I am using Camel 2.15 based on Fuse 6.2.1.
I went to the camel site and read this part from http://camel.apache.org/content-enricher.html . I'm not sure I understood how to implement... "For that you must set the filename in the
endpoint URI" .. this text was talking about the header, i'm thinking its also applicable to the properties in the exchange.
pollEnrich or enrich does not access any data from the current
Exchange which means when polling it cannot use any of the existing
headers you may have set on the Exchange. For example you cannot set a
filename in the Exchange.FILE_NAME header and use pollEnrich to
consume only that file. For that you must set the filename in the
endpoint URI.
Here is my code:
from("direct:createSomeIds")
.routeId("createSomeIds")
.process(new IdCreatorProcessor()
.setProperty("primaryOrgId").constant("testValue")
.split(xpath("/TempProjects/TempProject/Code/text()").namespaces(ns) , new IdStrategy())
.to("direct:splitRouteById")
.end();
from("direct:splitRouteById")
.routeId("splitRouteById")
.to("direct:getProjectByID")
.to("xquery:template/AllProjectToSingleProject.xq") //xquery template
.convertBodyTo(Project.class)
.enrich("direct:getAdditionalInfo", new ProjectStrategy(ProjectStrategy.AggregatorType.AdditionalInfo))
.enrich("direct:getSecondaryInfo", new ProjectStrategy(ProjectStrategy.AggregatorType.SecondaryInfo))
.end();
from("direct:getAdditionalInfo")
//some xpath stuff here
.setProperty("primaryOrgId").constant("changeTheValueHere")
.end();
from("direct:getSecondaryInfo")
.log("Value of primaryOrgId = " + "${exchangeProperty.primaryOrgId}")
.end();
If you can provide some code example, that would be helpful.
If you read a bit further down you will see that it's recommended that you instead use RecipientList with an AggregationStrategy.
.recipientList("direct:getAdditionalInfo", "direct:getSecondaryInfo")
.aggregationStrategy(new ProjectStrategy())
The setting of filename in your endpoint URI would only be applicable if you were to access some file on an FTP or some other file area.
Edit:
I now see that you need the property from the first enrichment in your second enrichment. However, if you're not modifying the message body in the first enrich then I don't actually see the need for it at all.
If you are in fact modifying the body then you can still use the RecipientList but instead you use two separate ones calling only one endpoint in each.

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.

Apache Camel Copying Files from multiple source folders to multiple destination folders

I am new to camel and we are building an EDI engine and our requirement is to read the files from multiple folders then second step is to parse the message type and the receiver id and based on that the messages need to be routed to different folders.
The source, message type, receiver id and destination cannot be hardcoded in camel instead it should be read from the database and the routes need to be built dynamically.
Please let me know what should be the strategy that we need to follow.
Thanks,
Jayadeep
As I understand from your comments, you can read from multiple folders by adding routes dynamically but are facing issue when trying to decide on where to send the messages as the destination , headers etc is being read from database.
Here's how I would do it.
Get the file --> Enrich it with database call and get the receiever id etc --> Use Xpath and get the receiver id etc and set them in propertyor header --> Use XSLT and remove the values that you enriched for database call so now you have the original message ---> Now use router and look at properties/headers to decide the <camel:to> path

Resources