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