5

I am looking for an example that shows how you write the Response in an undertow HttpHandler asynchronously? The problem is that when HttpServerExchange.endExchange is called the Response is flushed. My sample HttpHandler uses the rx-java library from Scala.

class MyHandler() extends HttpHandler {
  override def handleRequest(exchange: HttpServerExchange) = {
    val observable = Observable.items(List(1, 2, 3)) // simplistic not long running
    observable.map {
      // this is run async
      myList => exchange.getResponseSender.send(myList.toString)
    }
  }
}
sksamuel
  • 16,154
  • 8
  • 60
  • 108
reikje
  • 2,850
  • 2
  • 24
  • 44

1 Answers1

7

If you call the dispatch() method the exchange will not end when the call stack returns, however even that would be racy in this case.

You probably want something like:

exchange.dispatch(SameThreadExecutor.INSTANCE, () -> {
observable.map {
  // this is run async
  myList => exchange.getResponseSender.send(myList.toString)
}}

Basically this will wait till the call stack returns before running the async task, which means that there is no possibility of a race. Because the exchange is not thread safe this approach makes sure only one thread can run at a time.

Stuart Douglas
  • 847
  • 5
  • 4
  • You mean something like this before my code in handleRequest: http://undertow.io/documentation/core/undertow-request-lifecycle.html – reikje Aug 11 '14 at 08:18
  • That doesn't seem to work at least without some additional code around. I see that `Connectors.executeRootHandler()` handles dispatch and it ends `exchange` when not `resumed`. So if observable is not emitted before code reaches `if (!resumed) {exchange.endExchange();}` call fails with `response has already been sent`... – eduard.dudar Jun 09 '16 at 05:31
  • I've replaced dispatching of handler with dispatching on custom runnable that does only `handler.handleRequest(exchange);` and this works but hard to say if I'm missing something important in `exchange` lifecycle. – eduard.dudar Jun 09 '16 at 06:07
  • Link to undertow-request-lifecycle broken, so there are working link: http://undertow.io/undertow-docs/undertow-docs-1.4.0/index.html#undertow-request-lifecyle – Ruslan Oct 16 '17 at 15:52
  • 3
    It seems to me that this needs to be ***clearly*** documented, since the ability to write a response asynchronously is fundamental to using a non-blocking http server – igaz Jan 06 '18 at 18:07
  • @eduard.dudar - no that's not right; if exchange.isResumed() (true with Stuart's code), then the line you referenced is not executed (it's the else with the prior if) see https://github.com/undertow-io/undertow/blob/1.4.12.Final/core/src/main/java/io/undertow/server/Connectors.java#214 – igaz Jan 06 '18 at 18:39