You need to call io.undertow.io.Receiver#pause() to pause the IO. This is so that you don't end up with multiple threads working on the exchange. If you don't want to pause (i.e. you hare happy to have more data keep coming and being processed while your blocking task is running) then you do this by just directly submitting the task to the worker, and not calling dispatch.

This exists to keep Undertow's operation effectively single threaded, even though the exchange moves between threads one thread is always complete before the next one starts. If you do go with the second option of submitting to the worker you will need to come up with your own way of enforcing 'only one thread using the exchange'.

Stuart



On Thu, Mar 29, 2018 at 4:17 AM, Eldad Rudich <eldadru@gmail.com> wrote:
Hi,

In order to read the content of the requests my HttpHandler use receivePartialBytes as follows:

public class AsyncReaderHttpHandler implements HttpHandler {

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {

if (exchange.isInIoThread()) {
exchange.dispatch(this);
return;
}

readRequest(exchange);
}

private void readRequest(HttpServerExchange exchange) {
exchange.getRequestReceiver().receivePartialBytes(new MyCallback());
}

public class MyCallback implements PartialBytesCallback {

@Override
public void handle(HttpServerExchange exchange, byte[] message, boolean last) {
if (exchange.isInIoThread()) {
exchange.dispatch(() -> handleData(exchange, message, last));
} else {
handleData(exchange, message, last);
}
}

private void handleData(HttpServerExchange exchange, byte[] message, boolean last) {
// do some blocking operation with the data
}
}
}
My handler dispatching to worker thread and than calls receivePartialBytes() with a callback.

At first, I thought that the handle() method of the callback will always be called from a worker thread context.
I was surprised to discover that in some cases the callback will be called from I/O thread (why?), so I had to add the second call to dispatch() inside the callback.

After adding the second call to dispatch() my code started to fail with:

java.lang.IllegalStateException: UT000146: HttpServerExchange cannot have both async IO resumed and dispatch() called in the same cycle
at io.undertow.server.HttpServerExchange$ReadDispatchChannel.resumeReads(HttpServerExchange.java:2100)
at io.undertow.io.AsyncReceiverImpl$5$2.handleRequest(AsyncReceiverImpl.java:554)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:332)
at io.undertow.io.AsyncReceiverImpl$5.handleEvent(AsyncReceiverImpl.java:549)
at io.undertow.io.AsyncReceiverImpl$5.handleEvent(AsyncReceiverImpl.java:516)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at io.undertow.channels.DetachableStreamSourceChannel$SetterDelegatingListener.handleEvent(DetachableStreamSourceChannel.java:231)
at io.undertow.channels.DetachableStreamSourceChannel$SetterDelegatingListener.handleEvent(DetachableStreamSourceChannel.java:218)
at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)
at org.xnio.nio.WorkerThread.run(WorkerThread.java:561)


What am I missing here? how can I use the asynchronous receiver and not risking in blocking I/O thread?

I'm using Undertow 1.4.19.Final.

Thanks!

_______________________________________________
undertow-dev mailing list
undertow-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/undertow-dev