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).

That is true, thanks for pointing it out.

I assume you are not actually dealing with timers and this was just an example

Yes, timer was just an example. I am dealing with asynchronous client API that is used from the handler.

Thanks a lot for the answer!

On Mon, Aug 18, 2014 at 2:42 AM, Stuart Douglas <sdouglas@redhat.com> wrote:


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@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/undertow-dev



--
Vladimir Tsukur
Software Architect, Design Engineer and Scrum Master