Keith
Keith

Reputation: 528

How can I shutdown a standalone Apache Camel application in an automated way?

I'm trying to use Apache Camel to download and route files from an FTP server. However, files are only added to the FTP server once in a long while so having the program running continuously seems a bit overzealous. Instead, I would rather have a cronjob that runs weekly and processes any new files that have been added to the server.

Is there any way to get Camel to automatically shutdown once it no longer has any new files to process?

My current main function looks like this:

public static void main (String[] args) throws Exception {
    org.apache.camel.spring.Main main = new org.apache.camel.spring.Main ();
    main.setApplicationContextUri ("applicationContext.xml");
    main.enableHangupSupport ();
    main.run (args);
}

And the interesting part of the applicationContext.xml is:

<camelContext>
    <route>
        <from uri="ftp://ftp.example.com/remoteDir?username=user&amp;password=pass"/>
        <to uri="file:../ftp_data?tempPrefix=."/>
    </route>
</camelContext>

Upvotes: 7

Views: 8806

Answers (3)

Valtoni Boaventura
Valtoni Boaventura

Reputation: 1607

Completing Claus answer, this code run in a only once fashioned way Main:

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.main.Main;

public class MyMainRouter extends RouteBuilder {

  static Main main;

  @Override
  public void configure() throws Exception {
    from("timer:foo?delay=5s")
        .log("Hello camel, main world after 5 seconds!")
        .process(processor -> main.completed());
  }

  public static void main(String[] args) throws Exception {
    main = new Main();
    main.addRouteBuilder(new MyMainRouter());
    main.run();
  }

}

After 5 seconds, the code will run only once, because we will call a processor that will call completed() method, wich internally have CountDownLatch stopping a route pattern from another thread.

Upvotes: 2

Alessandro Da Rugna
Alessandro Da Rugna

Reputation: 4695

Adding this example that may be useful to others without digging all the examples in the link.

Define a bean/processor that will launch a separate thread. This new thread will call stop() on the active CamelContext.

public class ShutdownBean {

    private final static Logger log = LoggerFactory.getLogger(ShutdownBean.class);

    public void process(Exchange exchange) throws Exception {
        final CamelContext camelContext = exchange.getContext();

        Thread shutdownThread = new Thread(() -> {
            Thread.currentThread().setName("ShutdownThread");
            try {
                camelContext.stop();
            } catch (Exception e) {
                log.error("Errore during shutdown", e);
            }
        });

        shutdownThread.start();
    }
}

In your application context define this route and call it when you need to shutdown Camel.

<bean id="shutdownBean"
      class="your.package.ShutdownBean" />

<camelContext>

    <route id="ShutdownRoute">
        <from uri="direct:shutdown" />
        <log message="Shutdown..." />
        <to uri="bean:shutdownBean" />
    </route>

</camelContext>

Note: enableHangupSupport() is deprecated on newer Camel versions: is enabled by default now, so no longer need to call this method.

Upvotes: 6

Claus Ibsen
Claus Ibsen

Reputation: 55535

See this FAQ how to stop a route from a route: http://camel.apache.org/how-can-i-stop-a-route-from-a-route.html.

Then you can enable the option: sendEmptyMessageWhenIdle=true, and then in the route do a message filter, or content based route, and detect the empty message, and then stop the route and then after that CamelContext.

Though I also think this question has been discussed before, so you can maybe find other SO questions or google etc. As there is also alternative ways of doing this.

Upvotes: 4

Related Questions