2

I have a requirement of generating a file from webservice and FTP to a location.

Route1:

from("direct:start")
    .routeId("generateFileRoute")
    .setHeader(Exchange.HTTP_METHOD, constant("GET"))
    .setHeader(Exchange.HTTP_URI, simple(URL))
    .setHeader("Authorization", simple(APP_KEY))
    .to(URL)
    .unmarshal(listJacksonDataFormat)
    .marshal(bindyCsvDataFormat)
    .to(fileDirLoc + "?fileName=RMA_OUT_${date:now:MMddyyyy_HHmmss}.csv&noop=true");  

Route 2: FTP Route

from("file://"+header("CamelFileNameProduced"))
    .routeId("ftpRoute")
    .to("sftp://FTP_HOST/DIR?username=???&password=???)

To start the route

Exchange exchange = template.request("direct:start", null);

Object filePathObj = exchange.getIn().getHeader("CamelFileNameProduced");

if (filePathObj != null) { // Makesure Route1 has created the file
    camelContext.startRoute("ftpRoute");     // Start FTP route
    template.send(exchange); // Send exchange from Route1 to Route2
}

The above code worked when I hard-coded the location in FTP route. Can someone please help, how can I pipeline these 2 routes and pass output of Route 1 ("File Name") to Route2 for FTP?

Kenster
  • 23,465
  • 21
  • 80
  • 106
user1637487
  • 241
  • 1
  • 9
  • 17

3 Answers3

2

You cannot pass headers to the file endpoint, it just doesn't work like that. Also, from("file://...") cannot contain dynamic values in its path, i.e. placeholders of any kind, here's a quote from the official Camel documentation:

Camel supports only endpoints configured with a starting directory. So the directoryName must be a directory. If you want to consume a single file only, you can use the fileName option e.g., by setting fileName=thefilename. Also, the starting directory must not contain dynamic expressions with ${} placeholders. Again use the fileName option to specify the dynamic part of the filename.

My suggestion would be to either send to FTP directly, if you are not doing any additional CSV file processing:

from("direct:start")
    .routeId("generateFileRoute")
    .setHeader(Exchange.HTTP_METHOD, constant("GET"))
    .setHeader(Exchange.HTTP_URI, simple(URL))
    .setHeader("Authorization", simple(APP_KEY))
    .to(URL)
    .unmarshal(listJacksonDataFormat)
    .marshal(bindyCsvDataFormat)
    .to("sftp://FTP_HOST/DIR?username=???&password=??&fileName=RMA_OUT_${date:now:MMddyyyy_HHmmss}.csv");

Or to change Route 2 definition from file to direct:

from("direct:ftp-send")
    .routeId("ftpRoute")
    .pollEnrich("file:destination?fileName=${headers.CamelFileNameProduced}")
    .to("sftp://FTP_HOST/DIR?username=???&password=??&fileName=${headers.CamelFileName}")

or to change the definition of Route 2 to pick up only the generated files:

from("file://" + fileDirLoc + "?antInclude=RMA_OUT_*.csv")
    .routeId("ftpRoute")
    .to("sftp://FTP_HOST/DIR?username=???&password=???)
Miloš Milivojević
  • 5,219
  • 3
  • 26
  • 39
  • Thanks a lot for helping me on this. One followup question. Currently I am checking for `filePathObj` and starting `ftp-route`. I would like to do _onCompletion_ of route1. Is this the correct way to do. `exchange.addOnCompletion(new Synchronization() { @Override public void onComplete(Exchange exchange) { camelContext.addRoutes(ftpRouteBuilder); camelContext.startRoute("rmaftpRoute"); template.send("direct:ftp-send", exchange); }` – user1637487 Aug 23 '16 at 14:53
  • Not really - you should add and start your `ftpRouteBuilder` at the same time as you do the `generateFileRoute`. Also, there's no need for onCompletion here - `direct` routes are synchronous, meaning when `template.request` returns your exchange, the route has already finished. But there's no need for so much manual work - you can call `direct:ftp-send` from your first route. Just add `.to("direct:ftp-send")` at the very end. – Miloš Milivojević Aug 23 '16 at 15:51
1

Can't the ftpRoute simply poll fileDirLoc for new files ?

Luca Burgazzoli
  • 1,216
  • 7
  • 9
-1

There is a workaround, you can try to combine them:

from("direct:start")
    .routeId("generateFileRoute")
    .setHeader(Exchange.HTTP_METHOD, constant("GET"))
    .setHeader(Exchange.HTTP_URI, simple(URL))
    .setHeader("Authorization", simple(APP_KEY))
    .to(URL)
    .unmarshal(listJacksonDataFormat)
    .marshal(bindyCsvDataFormat)
    .to(fileUri.getUri())
    .setHeader(Exchange.FILE_NAME, file.getName())
    .to("sftp://FTP_HOST/DIR?username=???&password=???);

Yes, you cannot have dynamic expressions in the file uri but you can generate the uri and filename somewhere else. Say a utility method or something and refer to it here.

Souciance Eqdam Rashti
  • 3,143
  • 3
  • 15
  • 31