<div dir="ltr">I&#39;ve got a case where I can call receiveFullBytes but neither the success nor the error handler is ever called. My code looks like this:<div><div><pre style="font-family:Menlo;font-size:9pt"><span style="color:#000080;font-weight:bold">public static </span>CompletableFuture&lt;ByteSource&gt; getCompleteBody(HttpServerExchange exchange) {<br>  <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.debug(<span style="color:#008000;font-weight:bold">&quot;In getCompleteBody.&quot;</span>);<br>  CompletableFuture&lt;ByteSource&gt; finalResult = <span style="color:#000080;font-weight:bold">new </span>CompletableFuture&lt;&gt;();<br>  <span style="color:#000080;font-weight:bold">try </span>{<br>    <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.debug(<span style="color:#008000;font-weight:bold">&quot;Calling receiveFullBytes.&quot;</span>);<br>    exchange.getRequestReceiver().receiveFullBytes(<br>        <span style="color:#808080;font-style:italic">// Success case.<br></span><span style="color:#808080;font-style:italic">        </span>(HttpServerExchange excng, <span style="color:#000080;font-weight:bold">byte</span>[] bytes) -&gt; {<br>          <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.debug(<span style="color:#008000;font-weight:bold">&quot;getFullBytes completed with success.&quot;</span>);<br>          finalResult.complete(ByteSource.<span style="font-style:italic">wrap</span>(bytes));<br>        },<br><br>        <span style="color:#808080;font-style:italic">// Error case<br></span><span style="color:#808080;font-style:italic">        </span>(HttpServerExchange exchng, IOException t) -&gt; {<br>          <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.warn(<span style="color:#008000;font-weight:bold">&quot;getFullBytes completed with an error:&quot;</span>, t);<br>          finalResult.completeExceptionally(t);<br>        }<br>    );<br>  } <span style="color:#000080;font-weight:bold">catch </span>(Throwable t) {<br>    <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.warn(<span style="color:#008000;font-weight:bold">&quot;receiveFullBytes threw an exception:&quot;</span>, t);<br>    finalResult.completeExceptionally(t);<br>  }<br><br>  <span style="color:#000080;font-weight:bold">return </span>finalResult;<br>}</pre><pre style="font-family:Menlo;font-size:9pt"><div style="font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:small;line-height:19.5px;white-space:normal">I&#39;ve got a unit test that opens a socket, starts sending data, and then, intentionally throws an exception. The test then ensures that the CompletableFuture above completes with an exception. Except, it never completes.. the test just hangs forever. You can see that the &quot;log.debug(&quot;Calling receiveFullBytes.&quot;)&quot; line does get called and that the neither of the log lines in either callback is ever called. The full test looks like this:</div><div style="font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:small;line-height:19.5px;white-space:normal"><br></div><div style="font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:small;line-height:19.5px;white-space:normal"><pre style="font-family:Menlo;font-size:9pt"><span style="color:#808000">@Test<br></span><span style="color:#000080;font-weight:bold">public void </span>getCompleteBodyCompletesWithExceptionOnBodyFailure() <span style="color:#000080;font-weight:bold">throws </span>Exception {<br>  AtomicBoolean futureRedeemedWithError = <span style="color:#000080;font-weight:bold">new </span>AtomicBoolean(<span style="color:#000080;font-weight:bold">false</span>);<br>  CountDownLatch waitForInputToFail = <span style="color:#000080;font-weight:bold">new </span>CountDownLatch(<span style="color:#0000ff">1</span>);<br><br>  HttpHandler handler = <span style="color:#000080;font-weight:bold">new </span>HttpHandler() {<br>    <span style="color:#808000">@Override<br></span><span style="color:#808000">    </span><span style="color:#000080;font-weight:bold">public void </span>handleRequest(HttpServerExchange exchange) <span style="color:#000080;font-weight:bold">throws </span>Exception {<br>      <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.info(<span style="color:#008000;font-weight:bold">&quot;Handler called.&quot;</span>);<br>      exchange.dispatch();<br>      <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.info(<span style="color:#008000;font-weight:bold">&quot;Calling getCompleteBody&quot;</span>);<br>      UndertowUtils.<span style="font-style:italic">getCompleteBody</span>(exchange).exceptionally((Throwable t) -&gt; {<br>        <span style="color:#660e7a;font-weight:bold;font-style:italic">log</span>.debug(<span style="color:#008000;font-weight:bold">&quot;As expected, received an exception:&quot;</span>, t);<br>        <span style="color:#660e7a">futureRedeemedWithError</span>.set(<span style="color:#000080;font-weight:bold">true</span>);<br>        <span style="color:#660e7a">waitForInputToFail</span>.countDown();<br>        <span style="color:#000080;font-weight:bold">return null</span>;<br>      });<br>    }<br>  };<br>  UndertowTestUtils.RunningServer server = UndertowTestUtils.<span style="font-style:italic">startUndertowOnFreePort</span>(handler);<br><br>  <span style="color:#808080;font-style:italic">// A Body() implementation that will return a few chunks of data but the fail<br></span><span style="color:#808080;font-style:italic">  </span>Body failingRequestBody = <span style="color:#000080;font-weight:bold">new </span>Body() {<br>    <span style="color:#000080;font-weight:bold">private </span>AtomicInteger <span style="color:#660e7a;font-weight:bold">readCalls </span>= <span style="color:#000080;font-weight:bold">new </span>AtomicInteger(<span style="color:#0000ff">0</span>);<br>    <span style="color:#808000">@Override<br></span><span style="color:#808000">    </span><span style="color:#000080;font-weight:bold">public long </span>getContentLength() {<br>      <span style="color:#000080;font-weight:bold">return </span><span style="color:#0000ff">1000</span>;<br>    }<br><br>    <span style="color:#808000">@Override<br></span><span style="color:#808000">    </span><span style="color:#000080;font-weight:bold">public long </span>read(ByteBuffer buffer) <span style="color:#000080;font-weight:bold">throws </span>IOException {<br>      <span style="color:#000080;font-weight:bold">if </span>(<span style="color:#660e7a;font-weight:bold">readCalls</span>.getAndIncrement() &lt; <span style="color:#0000ff">2</span>) {<br>        <span style="color:#000080;font-weight:bold">byte</span>[] toSend = <span style="color:#008000;font-weight:bold">&quot;some data&quot;</span>.getBytes(Charsets.<span style="color:#660e7a;font-weight:bold;font-style:italic">UTF_8</span>);<br>        buffer.put(toSend);<br>        <span style="color:#000080;font-weight:bold">return </span>toSend.<span style="color:#660e7a;font-weight:bold">length</span>;<br>      } <span style="color:#000080;font-weight:bold">else </span>{<br>        <span style="color:#000080;font-weight:bold">throw new </span>RuntimeException(<span style="color:#008000;font-weight:bold">&quot;Fake error on sending data.&quot;</span>);<br>      }<br>    }<br><br>    <span style="color:#808000">@Override<br></span><span style="color:#808000">    </span><span style="color:#000080;font-weight:bold">public void </span>close() <span style="color:#000080;font-weight:bold">throws </span>IOException {<br>    }<br>  };<br><br>  <span style="color:#808080;font-style:italic">// A body generator using the above, busted Body.<br></span><span style="color:#808080;font-style:italic">  </span>BodyGenerator failingBodyGenerator = <span style="color:#000080;font-weight:bold">new </span>BodyGenerator() {<br>    <span style="color:#808000">@Override<br></span><span style="color:#808000">    </span><span style="color:#000080;font-weight:bold">public </span>Body createBody() <span style="color:#000080;font-weight:bold">throws </span>IOException {<br>      <span style="color:#000080;font-weight:bold">return </span><span style="color:#660e7a">failingRequestBody</span>;<br>    }<br>  };<br><br>  <span style="color:#808080;font-style:italic">// This will start sending data so our handler gets invoked but it will then fail partway through.<br></span><span style="color:#808080;font-style:italic">  </span>SimpleAsyncHttpClient client = <span style="color:#000080;font-weight:bold">new </span>SimpleAsyncHttpClient.Builder()<br>      .setUrl(String.<span style="font-style:italic">format</span>(<span style="color:#008000;font-weight:bold">&quot;http://localhost:%s&quot;</span>, server.getPort()))<br>      .build();<br><br>  client.post(failingBodyGenerator);</pre><pre style="font-family:Menlo;font-size:9pt"><br>  // Test hangs here forever<br>  waitForInputToFail.await();<br><br>  <span style="font-style:italic">assertThat</span>(futureRedeemedWithError.get()).isTrue();<br>}</pre></div><div style="font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:small;line-height:19.5px;white-space:normal"><br></div><div style="font-family:&#39;Helvetica Neue&#39;,Helvetica,Arial,sans-serif;font-size:small;line-height:19.5px;white-space:normal">This feels like a bug. I&#39;d expect the contract of &quot;receiveFullBytes&quot; to be that either the success or failure handler gets called exactly once. Is this a bug? If not, what am I doing wrong?</div></pre><pre style="font-family:Menlo;font-size:9pt">Thanks,</pre><pre style="font-family:Menlo;font-size:9pt">Oliver</pre></div></div></div><div dir="ltr">-- <br></div><div dir="ltr"><div style="font-size:small"><div style="font-size:13px;line-height:19.5px">CTO, Analytic Spot</div><div style="font-size:13px;line-height:19.5px">44 West Broadway #222</div><div style="font-size:13px;line-height:19.5px">Eugene, OR 97401<br></div><div style="font-size:13px;line-height:19.5px"><a href="http://analyticspot.com/" style="z-index: 0;">analyticspot.com</a> <span style="color:rgb(127,127,127);font-family:&#39;helvetica neue&#39;;font-size:11px;line-height:normal">• </span>425-296-6556</div></div><div style="font-size:small"><span style="line-height:19.5px"><a href="http://www.linkedin.com/in/oliverdain" style="z-index: 0;">www.linkedin.com/in/oliverdain</a></span></div></div>