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.