<div dir="ltr">You need to call io.undertow.io.Receiver#pause() to pause the IO. This is so that you don&#39;t end up with multiple threads working on the exchange. If you don&#39;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.<div><br></div><div>This exists to keep Undertow&#39;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 &#39;only one thread using the exchange&#39;.</div><div><br></div><div>Stuart</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 29, 2018 at 4:17 AM, Eldad Rudich <span dir="ltr">&lt;<a href="mailto:eldadru@gmail.com" target="_blank">eldadru@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi,<div><br></div><div>In order to read the content of the requests my HttpHandler use receivePartialBytes as follows:</div><div><br></div><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:Consolas;font-size:12pt"><span style="color:rgb(204,120,50)">public class </span>AsyncReaderHttpHandler <span style="color:rgb(204,120,50)">implements </span>HttpHandler {<br><br>  <span style="color:rgb(187,181,41)">@Override<br></span><span style="color:rgb(187,181,41)">  </span><span style="color:rgb(204,120,50)">public void </span><span style="color:rgb(255,198,109)">handleRequest</span>(<wbr>HttpServerExchange exchange) <span style="color:rgb(204,120,50)">throws </span>Exception {<br><br>    <span style="color:rgb(204,120,50)">if </span>(exchange.isInIoThread()) {<br>      exchange.dispatch(<span style="color:rgb(204,120,50)">this</span>)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">      return;<br></span><span style="color:rgb(204,120,50)">    </span>}<br><br>    readRequest(exchange)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">  </span>}<br><br>  <span style="color:rgb(204,120,50)">private void </span><span style="color:rgb(255,198,109)">readRequest</span>(HttpServerExchange exchange) {<br>    exchange.getRequestReceiver().<wbr>receivePartialBytes(<span style="color:rgb(204,120,50)">new </span>MyCallback())<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">  </span>}<br><br>  <span style="color:rgb(204,120,50)">public class </span>MyCallback <span style="color:rgb(204,120,50)">implements </span>PartialBytesCallback {<br><br>    <span style="color:rgb(187,181,41)">@Override<br></span><span style="color:rgb(187,181,41)">    </span><span style="color:rgb(204,120,50)">public void </span><span style="color:rgb(255,198,109)">handle</span>(HttpServerExchange exchange<span style="color:rgb(204,120,50)">, byte</span>[] message<span style="color:rgb(204,120,50)">, boolean </span>last) {<br>      <span style="color:rgb(204,120,50)">if </span>(exchange.isInIoThread()) {<br>        exchange.dispatch(() -&gt; handleData(<span style="color:rgb(179,137,197)">exchange</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(179,137,197)">message</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(179,137,197)">last</span>))<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">      </span>} <span style="color:rgb(204,120,50)">else </span>{<br>        handleData(exchange<span style="color:rgb(204,120,50)">, </span>message<span style="color:rgb(204,120,50)">, </span>last)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">      </span>}<br>    }<br><br>    <span style="color:rgb(204,120,50)">private void </span><span style="color:rgb(255,198,109)">handleData</span>(HttpServerExchange exchange<span style="color:rgb(204,120,50)">, byte</span>[] message<span style="color:rgb(204,120,50)">, boolean </span>last) {<br>      <span style="color:rgb(7,128,11)">// do some blocking operation with the data<br></span><span style="color:rgb(7,128,11)">    </span>}<br>  }<br>}</pre>My handler dispatching to worker thread and than calls receivePartialBytes() with a callback.</div><div><br></div><div>At first, I thought that the handle() method of the callback will always be called from a worker thread context.</div><div>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.</div><div><br></div><div>After adding the second call to dispatch() my code started to fail with:</div><div><br></div><div><div>java.lang.<wbr>IllegalStateException: UT000146: HttpServerExchange cannot have both async IO resumed and dispatch() called in the same cycle</div><div><span style="white-space:pre-wrap">        </span>at io.undertow.server.<wbr>HttpServerExchange$<wbr>ReadDispatchChannel.<wbr>resumeReads(<wbr>HttpServerExchange.java:2100)</div><div><span style="white-space:pre-wrap">        </span>at <a href="http://io.undertow.io">io.undertow.io</a>.<wbr>AsyncReceiverImpl$5$2.<wbr>handleRequest(<wbr>AsyncReceiverImpl.java:554)</div><div><span style="white-space:pre-wrap">        </span>at io.undertow.server.Connectors.<wbr>executeRootHandler(Connectors.<wbr>java:332)</div><div><span style="white-space:pre-wrap">        </span>at <a href="http://io.undertow.io">io.undertow.io</a>.<wbr>AsyncReceiverImpl$5.<wbr>handleEvent(AsyncReceiverImpl.<wbr>java:549)</div><div><span style="white-space:pre-wrap">        </span>at <a href="http://io.undertow.io">io.undertow.io</a>.<wbr>AsyncReceiverImpl$5.<wbr>handleEvent(AsyncReceiverImpl.<wbr>java:516)</div><div><span style="white-space:pre-wrap">        </span>at org.xnio.ChannelListeners.<wbr>invokeChannelListener(<wbr>ChannelListeners.java:92)</div><div><span style="white-space:pre-wrap">        </span>at io.undertow.channels.<wbr>DetachableStreamSourceChannel$<wbr>SetterDelegatingListener.<wbr>handleEvent(<wbr>DetachableStreamSourceChannel.<wbr>java:231)</div><div><span style="white-space:pre-wrap">        </span>at io.undertow.channels.<wbr>DetachableStreamSourceChannel$<wbr>SetterDelegatingListener.<wbr>handleEvent(<wbr>DetachableStreamSourceChannel.<wbr>java:218)</div><div><span style="white-space:pre-wrap">        </span>at org.xnio.ChannelListeners.<wbr>invokeChannelListener(<wbr>ChannelListeners.java:92)</div><div><span style="white-space:pre-wrap">        </span>at org.xnio.conduits.<wbr>ReadReadyHandler$<wbr>ChannelListenerHandler.<wbr>readReady(ReadReadyHandler.<wbr>java:66)</div><div><span style="white-space:pre-wrap">        </span>at org.xnio.nio.NioSocketConduit.<wbr>handleReady(NioSocketConduit.<wbr>java:88)</div><div><span style="white-space:pre-wrap">        </span>at org.xnio.nio.WorkerThread.run(<wbr>WorkerThread.java:561)</div></div><div><br></div><div><br></div><div>What am I missing here? how can I use the asynchronous receiver and not risking in blocking I/O thread?</div><div><br></div><div>I&#39;m using Undertow 1.4.19.Final.</div><div><br></div><div>Thanks!</div></div>
<br>______________________________<wbr>_________________<br>
undertow-dev mailing list<br>
<a href="mailto:undertow-dev@lists.jboss.org">undertow-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/undertow-dev</a><br></blockquote></div><br></div>