Ok, I guess that was a little long.  Let's try this:

Given this simple route:

from("seda:experiment")
    .toD("http://localhost:8090/sleep?delay=${body}";)  // an endpoint that 
sleeps for 10*delay seconds
    .process("MyProcessor");

How do I asynchronously call "seda:experiment" from another route?

I no longer even care to get a return (Exchange) from the route; 
"seda:experiment" can do all of the processing.

I just need to be able to call it and forget it.

I can't figure out what simple thing I'm missing, but none of the 
ProducerTemplate async*() calls are working - not even a simple asyncSendBody() 
- when I call "seda:experiment" in a loop, even when I'm not waiting for a 
return.

Instead of multiple sleep threads being started, each iteration waits for the 
previous sleep delay to finish.

Thanks for any help figuring out where my brain cramp is...

> On 08/28/2020 2:36 PM Ron Cecchini <roncecch...@comcast.net> wrote:
> 
>  
> Hi, guys.  I've been following the "async" docs and examples and the few code 
> snippets I could find online, but I'm still having trouble doing something 
> that I would think is very common.
> 
> My use case is basically this:
> 
> 1. I have a small route (call it "experiment") that hits an HTTP endpoint and 
> returns the integer value returned by that endpoint.
> 
> 2. I need to asynchronously call this "experiment" route from within a loop, 
> or from a barrage of JMS messages, etc.
> 
> ----------
> 
> To test this, I created a small separate service sitting on port 8090 with 
> endpoint "/experiment?i=<value>".
> 
> The endpoint just calculates a delay, sleeps, and returns the delay:
> 
>     @GetMapping(value = "/experiment")
>     public Integer sedaExperiment (@RequestParam(name = "i", required = true) 
> Integer ival) throws InterruptedException
>     {
>         log.info(String.format("sedaExperiment: ival: %d", ival));
>         delay = 10 + ival*10;
>         log.info(String.format("sedaExperiment: %d - sleeping %d seconds...", 
> ival, delay));
>         Thread.sleep(delay * 1000L);
>         log.info(String.format("sedaExperiment: %d - returning: %d", ival, 
> delay));
>         return delay;
>     }
> 
> ----------
> 
> In my calling app, my "experiment" route is simple enough:
> 
>         from("seda:experiment")
>             .routeId("seda-experiment")
>             .setHeader("val", simple("${body}"))
>             .log(LoggingLevel.INFO, "Experiment: ${header.val}")
>             .toD("http://localhost:8090/experiment?i=${header.val}";)
>             .log(LoggingLevel.INFO, "Experiment: ${header.val} - results: 
> ${body}");
> 
> And here's where I call it in a loop:
> 
>         from("timer:experiment?repeatCount=1")
>             .routeId("timer-experiment")
>             .process(new Processor() {
>                 public void process(Exchange e) throws Exception {
>                     ProducerTemplate prod = 
> e.getContext().createProducerTemplate();
>                     MyCallback callback = new MyCallback();
>                     for ( int i = 1; i <= 3; i++ ) {
>                         log.info(String.format("*** i = %d", i));
> //                        prod.asyncSendBody("seda:experiment", i, callback);
> //                        prod.asyncRequestBody("seda:experiment", i, 
> callback);
> //                        prod.asyncCallbackSendBody("seda:experiment", i, 
> callback);
>                         prod.asyncCallbackRequestBody("seda:experiment", i, 
> callback);
> //                        
> prod.asyncCallbackSendBody("http://localhost:8090/experiment?i="+i, null, 
> callback);
>                     }
>                 }
>             });
> 
> where 'callback' is:
> 
>     private static class MyCallback extends SynchronizationAdapter {
>         @Override
>         public void onComplete(Exchange exchange) {
>             Integer result = exchange.getIn().getBody(Integer.class);
>             log.info(String.format("ASYNC: Experiment: %d - results: %d", 99, 
> result));
>         }
>     }
> 
> -------------------------
> 
> What ends up happening is that the "seda:experiment" route is called 
> sequentially, with each call waiting for the service's endpoint's delay to 
> finish.  Obviously not async...
> 
> Besides asyncCallbackRequestBody(), you can see I experimented with other 
> async calls.  Nothing worked as desired.
> 
> The closest thing that worked was not calling my "seda:experiment" route but 
> calling the endpoint directly:
> 
> asyncCallbackSendBody("http://localhost:8090/experiment?i="+i, null, 
> callback);
> 
> This *did* kick off 3 simultaneous threads on the service side.  However, the 
> results don't seem to be in the callback ('result' is null, not 20, 30, 40).  
> But even if I could get the result in the callback, I'd *really* rather be 
> able to call my route because the (real) route contains extra processing that 
> I don't want to try replicating in the callback.
> 
> -------------------------
> 
> So what am I doing wrong?  I know this must be something people do ALL THE 
> TIME...
> 
> As for the callback stuff, if I could call "seda:experiment" asynchronously, 
> I wouldn't even need any of the "Callback" versions of any of the async*() 
> calls.  The route does everything I need.  I just can't call it properly...
> 
> As always, thank you for any help.

Reply via email to