[undertow-dev] Sending response asynchronously to IO or worker thread

Stuart Douglas sdouglas at redhat.com
Sun Aug 17 19:42:58 EDT 2014


>
> This handler is implemented incorrectly because exchange will end right
> after handleRequest method is called.
>
> In order to fix this we can use dispatching (only implementation of
> handleRequest method is shown):
>
>      public void handleRequest(final HttpServerExchange exchange) throws
> Exception {
>          if (exchange.isInIoThread()) {
>              exchange.dispatch(new Runnable() {
>                  public void run() {
>                      new Timer().schedule(new TimerTask() {
>                          public void run() {
>                              Connectors.executeRootHandler(new
> HttpHandler() {
>                                  public void
> handleRequest(HttpServerExchange exchange) throws Exception {
>
> exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
>
> exchange.getResponseSender().send("Returned in 5 seconds");
>                                  }
>                              }, exchange);
>                          }
>                      }, 5000);
>                  }
>              });
>          }
>      }
>
> Please pay attention that the requirement here is not to use dumb
> blocking in the work thread (like Thread.sleep(5000)) but rely on
> asynchronous event handling instead.
>
> I would appreciate if someone can answer the following questions:
>

You don't need the isInIoThread() check, otherwise this handler will do 
nothing if an earlier handler dispatched (e.g. a security handler that 
needed to do a blocking LDAP lookup).

>   * Are there any pitfalls with the working dispatch/executeRootHandler
>     solution mentioned above?

No, this is the correct way to do it. Undertow's exchange is not thread 
safe (as making it thread safe seriously degrades performance by an 
order of magnitude). Instead multi-threading is implemented by having a 
safe hand off point (the dispatch() method), which basically allows a 
thread to hand off to another thread when it is done, so only one thread 
'owns' the exchange at a time.

You can just call the dispatch() method with no arguments to stop the 
exchange ending, but if your async task finished before the call stack 
returns then you will have two threads active in the exchange, which 
will cause all kinds of potential problems (this is not going to happen 
with a 5000ms delay, but with a 1ms delay it will).

>   * Is there a simpler and more elegant way to achieve the same?

I assume you are not actually dealing with timers and this was just an 
example, but if you do want to schedule a task (like a timeout for 
instance) you can schedule it using

exchange.getIoThread().executeAfter(), which will run the timed task in 
the IO thread.

Stuart

>
> --
> Vladimir Tsukur
> Software Architect, Design Engineer and Scrum Master
>
> _______________________________________________
> undertow-dev mailing list
> undertow-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/undertow-dev


More information about the undertow-dev mailing list