0

I have a loop in my code that generates apache camel flows. However, each of these jobs needs to Poll from an Oracle database, and it leads to a Maximum Number of Sessions per user error. The reason is that these jobs are async, thus cause the app to reach its limit on the number of connections to the database. Therefore, I need a way to wait for the completion of a flow and then fire the next one. I was wondering if there was a way to do that? I tried to use Thread.sleep at the end of each loop, but it did not work.

for (int i=0; i<tasks.size(); i++) {
    DataStore sourceStore = dataStores.get(tasks.get(i));
    DataSource source = sourceStore.getDataSource();
    DefaultRegistry registry = new DefaultRegistry();
    registry.bind(tasks.get(i).getName(), source);
    CamelContext context = new DefaultCamelContext(registry);
    try {
        context.addRoutes(new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from ("direct:start")
                .to("jdbc:" + tasks.get(i).getSourceDataStoreName())
                .split(body())
                // some other job
                ;
                                                }
            });
        } catch (Exception e) {
        e.printStackTrace();
    }
    context.start();                
    ProducerTemplate producerTemplate = context.createProducerTemplate();
    producerTemplate.sendBody("direct:start", sourceStore.getQuery(tasks.get(i)));
    //Thread.sleep(40000); // did not work
}
orezvani
  • 3,595
  • 8
  • 43
  • 57
  • 1
    Do you really want to initialize a new Camel context per task? I guess it would be preferable to use just one Camel context and use [toD(...)](https://camel.apache.org/manual/latest/faq/how-to-use-a-dynamic-uri-in-to.html) instead of `to(...)` to dynamically configure the consumer. [NotifyBuilder](https://github.com/apache/camel/blob/master/core/camel-core-engine/src/main/java/org/apache/camel/builder/NotifyBuilder.java) allows you to get notifications on certain predefined endpoint metrics assertions such as done exchanges and so on. This is often used in testing to avoid sleeps – Roman Vottner Nov 29 '19 at 15:47
  • @RomanVottner I can see that it is possible to use `toD` instead of `to` for a dynamic route. However, this is not helpful here, as the route configuration is in a configuration class `Task`. The route config is not in a message, rather in an Object – orezvani Dec 02 '19 at 11:19
  • There are plenty of ways you could reuse a single route instead of defining a new context per task. I.e. you could use `sendBodyAndHeader(endpoint, body, headerName, headerValue)` to send the configuration alongside as Camel header and then just use `toD("jdbc:${header.HEADER_NAME}")` where `HEADER_NAME` is the name you specified in the `sendBodyAndHeader(...)` method, just to name one possibility. – Roman Vottner Dec 02 '19 at 11:33

1 Answers1

0

I think you should try onCompletion. Accordind to documentation, route after onCompletion() is only invoked when the original route is complete. You can do your job after onCompletion(), for example, you can send somewhere result of your task.

There is my simple onCompletion() example:

context.addRoutes(new RouteBuilder()
{

        @Override
        public void configure() throws Exception
        {

            from("timer://mytimer?repeatCount=2&fixedRate=true&period=3000")
                    .process(exchange -> {
                        System.out.println("Thread will sleep 2s");
                        Thread.sleep(2000);
                    }).onCompletion().process(exchange -> System.out.println("After completion"));
        }
});