2

I was trwing to construct a synchronous route with timeout using Apache Camel, and I couldn't find anything in the framework with resolve it. So I decided to build a process with make it for me.

public class TimeOutProcessor implements Processor {

private String route;
private Integer timeout;

public TimeOutProcessor(String route, Integer timeout) {
    this.route = route;
    this.timeout = timeout;
}


@Override
public void process(Exchange exchange) throws Exception {
    ExecutorService executor = Executors.newSingleThreadExecutor();

    Future<Exchange> future = executor.submit(new Callable<Exchange>() {

        public Exchange call() {
            // Check for field rating

            ProducerTemplate producerTemplate = exchange.getFromEndpoint().getCamelContext().createProducerTemplate();
            return producerTemplate.send(route, exchange);
        }
    });
    try {
        exchange.getIn().setBody(future.get(
                timeout,
                TimeUnit.SECONDS));
    } catch (TimeoutException e) {
        throw new TimeoutException("a timeout problem occurred");
    }
    executor.shutdownNow();
}

And I call this process this way:

.process(new TimeOutProcessor("direct:myRoute",
                Integer.valueOf(this.getContext().resolvePropertyPlaceholders("{{timeout}}")))

I wanna know if my way is the recomended way to do it, if it is not, what is the best way for build a synchronous route with timeout?

Victor Tripeno
  • 144
  • 1
  • 2
  • 11
  • 1
    What is your exact use case? I see no reason to apply a timeout to a direct route in Camel. Why do you need that? – burki Mar 16 '18 at 17:10
  • Because my route needs to communicate with a Database, and this route must to be synchronous, and because a necessity this route need to execute in a specific time. – Victor Tripeno Mar 16 '18 at 17:12
  • 1
    There are some Async APIs on ProducerTemplate you can use to send, and get back a `Future` which you can then get with a timeout. – Claus Ibsen Mar 17 '18 at 10:22
  • But, I need a sync route. Have some way to transform an async route in a sync just for use the timeout? – Victor Tripeno Mar 17 '18 at 10:57
  • 2
    What https://stackoverflow.com/users/406429/claus-ibsen means is you can use a bean with a `ProducerTemplate` that calls the direct route with an async method like `asyncSend` (see [here](http://camel.apache.org/async) for more). That gives you **immediately** a Java `Future`. On this `Future` you can ask for the result with a timeout (see `get` method with timeout in [javadocs](https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Future.html#get%28long,%20java.util.concurrent.TimeUnit%29). You have a sync route and you call it with a timeout. – burki Mar 19 '18 at 09:43
  • Can't you just specify a timeout on your database command? – batwad Mar 19 '18 at 16:14
  • Thank you Ibsen and burki, it works for me. And about put the timeout in my database, I did it, but I need to call more than one time other databases, and I need to have a timeout for the route. – Victor Tripeno Mar 19 '18 at 16:51

1 Answers1

0

I want to thanks the people who answer me.

That is my final code:

public class TimeOutProcessor implements Processor {

private String route;
private Integer timeout;

public TimeOutProcessor(String route, Integer timeout) {
    this.route = route;
    this.timeout = timeout;
}


@Override
public void process(Exchange exchange) throws Exception {
    Future<Exchange> future = null;
    ProducerTemplate producerTemplate = exchange.getFromEndpoint().getCamelContext().createProducerTemplate();
    try {

        future = producerTemplate.asyncSend(route, exchange);
        exchange.getIn().setBody(future.get(
                timeout,
                TimeUnit.SECONDS));
        producerTemplate.stop();
        future.cancel(true);
    } catch (TimeoutException e) {
        producerTemplate.stop();
        future.cancel(true);
        throw new TimeoutException("a timeout problem occurred");
    }

}
}
Victor Tripeno
  • 144
  • 1
  • 2
  • 11