mardi 7 mai 2019

Waiting for an http response to return from vertx WebClient using CountDownLatch

I am writing some tests for some rest api, i have a dispatcher that diapctch my rest request to a WebClient from vertx, in some cases i want to wait for the response from the rest api to return before i can continue further with my assertions, the code that dispatch the requests is wrapped inside other classes, so i am not directly making those requests from the tests, i have 2 implementations from my request dispatcher,one for production and one for tests, the tests dispatcher looks like this :

public class TestRequestDispatcher extends AbstractRequestDispatcher {

    @Override
    protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {

        request.getSender()
                .send(request,
                        new ServerRequestCallBack() {

                            @Override
                            public <T> void onSuccess(T response) {
                                requestEventFactory.makeSuccess(request, response).fire();
                            }

                            @Override
                            public void onFailure(FailedResponseBean failedResponse) {
                                requestEventFactory.makeFailed(request, failedResponse).fire();
                            }
                        });
    }
}

this should then call some code that builds a WebClient and call its send method to send the request to the server.

And in order to wait for the response i decided to use the CountDownLatch and modified my code to the following

public class TestRequestDispatcher extends AbstractRequestDispatcher {

    @Override
    protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {

        CountDownLatch requestWait = new CountDownLatch(1);

        request.getSender()
                .send(request,
                        new ServerRequestCallBack() {

                            @Override
                            public <T> void onSuccess(T response) {
                                requestWait.countDown();
                                requestEventFactory.makeSuccess(request, response).fire();
                            }

                            @Override
                            public void onFailure(FailedResponseBean failedResponse) {
                                requestWait.countDown();
                                requestEventFactory.makeFailed(request, failedResponse).fire();
                            }
                        });

        try {
            requestWait.await(20, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

I am using a large timeout here to make sure that the response should return before the timeout is up, so what happens is that i can breakpoint and see the WebCLient.send method being called, and then it pauses at requestWait.wait(...) but the callbacks are never invoked until the CountDownLatch time out is up. while i was expecting the WebClient to send the request and when ever the response is returned it will invoke the callbacks which in return will count down and break the wait before the timwout is up.

Testing with a normal thread things seems to work, i created some runnable class with some sleep period ..less that the CountDownTime latch. like the the following

public class SenderWorker implements Runnable {

    private CountDownLatch countDownLatch;

    public SenderWorker(CountDownLatch countDownLatch) {

        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(5000L);
            countDownLatch.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

then in the dispatcher :

public class TestRequestDispatcher extends AbstractRequestDispatcher {

    @Override
    protected void dispatchRequest(ServerRequest request, ServerRequestEventFactory requestEventFactory) {

        CountDownLatch requestWait = new CountDownLatch(1);
        new Thread(new SenderWorker(requestWait))
                .start();

        try {
            requestWait.await(20, TimeUnit.SECONDS);
            System.out.println("i am here");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

And this works.. it calls the run method..the sleeps, then call the requestWait.wait(..) and after 5 seconds it breaks out of the wait.

I tried to execute the code that calls the WebClient inside an executeBlocking and also tried the runOnContext and even tried to run it inside a thread just like how i did with the SenderWorker but still the same result .. the WebClient is blocked until the timeout is up.

Any idea what i am doing wrong here and how i can make this works.?!

Aucun commentaire:

Enregistrer un commentaire