1

I'm trying to create a webservice which, when called look into a local directory picks up files from there and upload to the ftp server.

I'm able to create a simple route which picks file from local directory and uploads to ftp server below is the code :

<route>
        <from uri="file://D:\\FTPTest?noop=true&amp;delay=2000" />
        <to uri="ftp://user@host.in:21/public_html/EnterpriseProject?password=password123#"/>
        <to uri="bean:myBean?method=test" />
    </route>

But, I want to this file transfer to be called when a particular route is called via restlet webservice is called, I tried with the following code, but it didn't work :

<route>
        <from uri="direct:fileTransferRoute" />
            <to uri="file://D:\\FTPTest?noop=true&amp;delay=2000" />
            <to uri="ftp://user@host.in:21/public_html/EnterpriseProject?password=password123#"/>
        </route>

The above route is called by restlet from following route :

<route>
<from
            uri="restlet:http://0.0.0.0:9080/csitec/{serviceName}?restletMethod=post" />
        <process ref="serviceRouteProcessor" />
        <toD uri="direct:${in.header.nextRoute}" />

    </route>

Here's the code of my serviceRouteProcessor :

public void process(Exchange exchange) throws Exception {
    String body = exchange.getIn().getBody(String.class);
    String serviceName = exchange.getIn().getHeader(Constants.SERVICE_NAME).toString();
    String nextRoute = serviceName+Constants.NEXT_ROUTE_APPENDER;
    exchange.getOut().setHeader(Constants.NEXT_ROUTE, nextRoute);
    exchange.getOut().setBody(body);
}

Please help me and suggest the changes needs to be done to make it work like this.

Siddharth Sachdeva
  • 1,812
  • 1
  • 20
  • 29

2 Answers2

4

You should try the pollEnrich feature of content-enricher

In the example section you can find a example regarding files.

Your route should look something like this(I work only with camel java dsl, so this a bit xml pseudo code):

<route>
    <from uri="direct:fileTransferRoute" />
        <pollEnrich uri="file://D:\\FTPTest?fileName=data.txt....." />
        <to uri="ftp://user@host.in:21/public_html/EnterpriseProject?password=password123#"/>
    </route>
soilworker
  • 1,317
  • 1
  • 15
  • 32
  • I have added your route as example to my answer. – soilworker Nov 24 '16 at 16:53
  • Attribute 'uri' is not allowed to appear in element 'pollEnrich'. Its strange im getting this error. However, its working fine with : file://D:\\FTPTest?noop=true&delay=2000; This is what i was actually looking for thanks a lot – Siddharth Sachdeva Nov 24 '16 at 17:43
  • @Siddharth the error depends on fact that up to camel 2.15 `enrich` and `pollEnrich` syntax was like the answer, from camel 2.16 the syntax changed a bit and works like your comment. – Alessandro Da Rugna Nov 25 '16 at 08:04
2

Edited :

you must understand one thing first , to is producer not consumer <to uri="file://D:\\FTPTest?noop=true&amp;delay=2000" />

What you can do is ,

@Autowired
private CamelContext context;// if you have more than one camel context use @Qualifier and wire by bean id


public void process(Exchange exchange) throws Exception {
    String body = exchange.getIn().getBody(String.class);
    String serviceName = exchange.getIn().getHeader(Constants.SERVICE_NAME).toString();
    context.startRoute(serviceName+Constants.NEXT_ROUTE_APPENDER);// here in nextroute you must give the routeid
}

your route must look like

 <route id = "<value of serviceName+Constants.NEXT_ROUTE_APPENDER>" autoStartup = "false">
                <from uri="file://D:\\FTPTest..." />
                <onCompletion onFailureOnly="true">
                  <choice>
                    <when>
                        <simple>${property.CamelBatchComplete}</simple>
                    <process ref="asyncSelfShutdownProcessor"/>
                    </when>
                  </choice>
                </onCompletion>
                <to uri="ftp://user@host.in:21..."/>
            </route>

And add asyncSelfShutdownProcessor to spring context

@Component
public class AsyncSelfShutdownProcessor implements AsyncProcessor {

    @Autowired
    private CamelContext context

     public boolean process(Exchange exchange, AsyncCallback callback){

          new Thread(() -> context.stopRoute(exchange.getFromRouteId())).start();
     }
}

############################################################################## Old :

OK I understand your need as - you have a route that moves file from file system to ftp server, all you need is this route to get executed only when you trigger from a rest service. I would do it like this ,

*I will make the route autoStartup = "false" and assign as id = "fs-to-ftp" to the route

<route id = "fs-to-ftp" autoStartup = "false">
            <from uri="file://D:\\FTPTest..." />
            <onCompletion onFailureOnly="true">
                <process ref="asyncSelfShutdownProcessor"/>
            </onCompletion>
            <to uri="ftp://user@host.in:21..."/>
        </route>

**Add a self shutdown async process in onComplete to the route "fs-to-ftp". Async Processor

asyncSelfShutdownProcessor= AsyncProcessorConverterHelper.convert(exchange -> {
            new Thread(() -> context.stopRoute("fs-to-ftp")).start();
        });

***Add the camel context dependency to rest service and start the route by id in the rest service context.startRoute("fs-to-ftp")

Sagar
  • 818
  • 1
  • 6
  • 13
  • Thanks for your reply @Sagar , actually I'm calling other routes from restlet with so, how can I call a route with particular id in that ? – Siddharth Sachdeva Nov 24 '16 at 05:59
  • Is there any way in which I can give this in my route and do the file transfer process ? – Siddharth Sachdeva Nov 24 '16 at 06:06
  • Actually if you want use `` then you must read and stream the files to `"direct:fileTransferRoute"` programatically and camel won't pick by itself – Sagar Nov 24 '16 at 07:14
  • May be you should add your restful service code for better understanding of your scenario – Sagar Nov 24 '16 at 07:14
  • I added all the related code, can help me now, please. – Siddharth Sachdeva Nov 24 '16 at 07:23
  • Now, route is not stopping here's the logs : 2016-11-24 13:38:24 INFO [Camel (camel-1) thread #5 - ShutdownTask] DefaultShutdownStrategy:628 - Waiting as there are still 2 inflight and pending exchanges to complete, timeout in 227 seconds. Inflights per route: [fileTransfer = 2] 2016-11-24 13:38:24 DEBUG [Camel (camel-1) thread #5 - ShutdownTask] DefaultShutdownStrategy:757 - There are 1 inflight exchanges: InflightExchange: [exchangeId=ID-dell-52675-1479974705034-0-7, fromRouteId=fileTransfer, routeId=fileTransfer, nodeId=to4, elaps – Siddharth Sachdeva Nov 24 '16 at 08:11
  • do you have more than one file in the folder .. in which case you should use batch consumer – Sagar Nov 24 '16 at 08:12
  • Yeah, it do have more than one file, any reference to implement batch consumer would be really helpful. – Siddharth Sachdeva Nov 24 '16 at 08:15
  • just add &antInclude=* to you from and add condition in onCompletion for property CamelBatchComplete to true – Sagar Nov 24 '16 at 08:16
  • Even in case of single file its not shutting down. Showing there are 1 inflight exchanges – Siddharth Sachdeva Nov 24 '16 at 08:18
  • I'm unable to call other services now. As this one is not shutting down. – Siddharth Sachdeva Nov 24 '16 at 08:20
  • AsyncProcessor is not a class its an interface also im getting syntax error in new thread line. please check bro. – Siddharth Sachdeva Nov 24 '16 at 09:44
  • there's some problem with this line please try in your IDE : new Thread(() -> context.stopRoute(exchange.getFromRouteId())).start(); – Siddharth Sachdeva Nov 24 '16 at 12:29
  • And boolean to return? – Siddharth Sachdeva Nov 24 '16 at 12:29