[undertow-dev] receiveFullBytes callbacks never called

Oliver Dain oliver at analyticspot.com
Thu May 12 14:13:11 EDT 2016


Done: https://issues.jboss.org/browse/UNDERTOW-710

On Thu, May 12, 2016 at 5:21 AM Stuart Douglas <sdouglas at redhat.com> wrote:

> This sounds like a bug, can you file a JIRA? I am traveling at the
> moment but I will investigate when I get back.
>
> Stuart
>
> On Wed, May 11, 2016 at 10:54 AM, Oliver Dain <oliver at analyticspot.com>
> wrote:
> > I'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:
> >
> > public static CompletableFuture<ByteSource>
> > getCompleteBody(HttpServerExchange exchange) {
> >   log.debug("In getCompleteBody.");
> >   CompletableFuture<ByteSource> finalResult = new CompletableFuture<>();
> >   try {
> >     log.debug("Calling receiveFullBytes.");
> >     exchange.getRequestReceiver().receiveFullBytes(
> >         // Success case.
> >         (HttpServerExchange excng, byte[] bytes) -> {
> >           log.debug("getFullBytes completed with success.");
> >           finalResult.complete(ByteSource.wrap(bytes));
> >         },
> >
> >         // Error case
> >         (HttpServerExchange exchng, IOException t) -> {
> >           log.warn("getFullBytes completed with an error:", t);
> >           finalResult.completeExceptionally(t);
> >         }
> >     );
> >   } catch (Throwable t) {
> >     log.warn("receiveFullBytes threw an exception:", t);
> >     finalResult.completeExceptionally(t);
> >   }
> >
> >   return finalResult;
> > }
> >
> > I'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
> > "log.debug("Calling receiveFullBytes.")" line does get called and that
> the
> > neither of the log lines in either callback is ever called. The full test
> > looks like this:
> >
> > @Test
> > public void getCompleteBodyCompletesWithExceptionOnBodyFailure() throws
> > Exception {
> >   AtomicBoolean futureRedeemedWithError = new AtomicBoolean(false);
> >   CountDownLatch waitForInputToFail = new CountDownLatch(1);
> >
> >   HttpHandler handler = new HttpHandler() {
> >     @Override
> >     public void handleRequest(HttpServerExchange exchange) throws
> Exception
> > {
> >       log.info("Handler called.");
> >       exchange.dispatch();
> >       log.info("Calling getCompleteBody");
> >       UndertowUtils.getCompleteBody(exchange).exceptionally((Throwable
> t) ->
> > {
> >         log.debug("As expected, received an exception:", t);
> >         futureRedeemedWithError.set(true);
> >         waitForInputToFail.countDown();
> >         return null;
> >       });
> >     }
> >   };
> >   UndertowTestUtils.RunningServer server =
> > UndertowTestUtils.startUndertowOnFreePort(handler);
> >
> >   // A Body() implementation that will return a few chunks of data but
> the
> > fail
> >   Body failingRequestBody = new Body() {
> >     private AtomicInteger readCalls = new AtomicInteger(0);
> >     @Override
> >     public long getContentLength() {
> >       return 1000;
> >     }
> >
> >     @Override
> >     public long read(ByteBuffer buffer) throws IOException {
> >       if (readCalls.getAndIncrement() < 2) {
> >         byte[] toSend = "some data".getBytes(Charsets.UTF_8);
> >         buffer.put(toSend);
> >         return toSend.length;
> >       } else {
> >         throw new RuntimeException("Fake error on sending data.");
> >       }
> >     }
> >
> >     @Override
> >     public void close() throws IOException {
> >     }
> >   };
> >
> >   // A body generator using the above, busted Body.
> >   BodyGenerator failingBodyGenerator = new BodyGenerator() {
> >     @Override
> >     public Body createBody() throws IOException {
> >       return failingRequestBody;
> >     }
> >   };
> >
> >   // This will start sending data so our handler gets invoked but it will
> > then fail partway through.
> >   SimpleAsyncHttpClient client = new SimpleAsyncHttpClient.Builder()
> >       .setUrl(String.format("http://localhost:%s", server.getPort()))
> >       .build();
> >
> >   client.post(failingBodyGenerator);
> >
> >
> >   // Test hangs here forever
> >   waitForInputToFail.await();
> >
> >   assertThat(futureRedeemedWithError.get()).isTrue();
> > }
> >
> >
> > This feels like a bug. I'd expect the contract of "receiveFullBytes" to
> be
> > that either the success or failure handler gets called exactly once. Is
> this
> > a bug? If not, what am I doing wrong?
> >
> > Thanks,
> >
> > Oliver
> >
> > --
> > CTO, Analytic Spot
> > 44 West Broadway #222
> > Eugene, OR 97401
> > analyticspot.com • 425-296-6556
> > www.linkedin.com/in/oliverdain
> >
> > _______________________________________________
> > undertow-dev mailing list
> > undertow-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/undertow-dev
>
-- 
CTO, Analytic Spot
44 West Broadway #222
Eugene, OR 97401
analyticspot.com • 425-296-6556
www.linkedin.com/in/oliverdain
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/undertow-dev/attachments/20160512/96d1ebab/attachment.html 


More information about the undertow-dev mailing list