[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