title: Vertx HTTPClient with CompletableFuture block the callback Thread
body: <p>I am facing a very weird problem.</p>
  
  <p>I am working on Vert.x and from handler I am calling REST APIs using <code>HttpClientRequest</code> of Vert.x. Now I am having a <code>CompletableFuture</code> which I am completing in the response handler of the <code>HttpClientRequest</code>. Later, I am using <code>CompletableFuture.get()</code>. But whenever <code>get()</code> method is called, the main thread is blocked (as expected), but it remains blocked forever. I am not seeing the callback happen on my response Handler and it is stuck for forever. </p>
  
  <p>Here is code:</p>
  
  <pre><code>import io.vertx.core.http.HttpClientRequest;
  import io.vertx.core.http.HttpMethod;
  import io.vertx.core.json.Json;
  import io.vertx.core.json.JsonObject;
  import java.util.concurrent.CompletableFuture;
  import io.vertx.core.http.HttpClient;
  
  CompletableFuture&lt;JsonObject&gt; comp = new CompletableFuture&lt;JsonObject&gt;();   
  HttpClient httpClient = new HttpClient(); //This object initialized and set the endpoit, port and domain name.
  HttpClientRequest request = httpClient.request(HttpMethod.POST, requestURI, response -&gt; {
          response.bodyHandler(body -&gt; {
              //do some process
              comp.complete(new JsonObject(body);
          });
      }).exceptionHandler(e -&gt; {
          //log the error
          comp.completeExceptionally(e);
      });
  
  request.end();
  //after some process
  comp.get();  // here main thread is stuck forever.
  </code></pre>
  
  <p>My API gives 200 response, I saw in it Wireshark and also If I do <code>comp.thenAccept()</code> the callback is executed and it gives my result. </p>
  
  <p>Why is this happening and what is the solution?</p>
  
  <p>Note: I know that it is not recommendation to use <code>Completable.get()</code> method but in my use-case, I have to use it. </p>
  
  <p>Here is sample code which is giving me issue:</p>
  
  <pre><code>package io.vertx.starter;
  
  import io.vertx.core.AbstractVerticle;
  import io.vertx.core.Future;
  import io.vertx.core.http.*;
  import io.vertx.ext.web.Router;
  import io.vertx.ext.web.RoutingContext;
  
  import java.util.concurrent.CompletableFuture;
  
  public class SampleVerticle extends AbstractVerticle {
  
    public void start ( Future startFuture ) throws Exception {
      Future&lt;Void&gt; future = Future.future ();
      HttpServer server = vertx.createHttpServer ();
  
      Router router = Router.router (vertx);
      router.get ("/sample").handler (this::sampeHandler);
      router.get ("/testcompletableblocking").handler (this::testCompBlocking);
      router.get ("/testcompletablenonblocking").handler (this::testCompNonBlocking);
  
      server.requestHandler (router::accept) // &lt;5&gt;
        .listen (8080, ar -&gt; { // &lt;6&gt;
          if (ar.succeeded ()) {
            System.out.println ("Server started");
            future.complete ();
          } else {
            System.out.println ("Server is not started");
            future.fail (ar.cause ());
          }
        });
    }
  
    private void sampeHandler ( RoutingContext context ) {
      try {
        Thread.sleep (1000);
      } catch (Exception e) {
      }
      String response = "Hello...";
      context.response ().setStatusCode (200).putHeader ("content-type", "text/html").end (response);
    }
  
    private void testCompBlocking ( RoutingContext context ) {
  
      System.out.println ("Calling testCompBlocking....");
      HttpClientOptions clientOptions = new HttpClientOptions ().setDefaultHost ("localhost").setDefaultPort (8080).setSsl (false).setKeepAlive (true);
      HttpClient client = vertx.createHttpClient (clientOptions);
  
      String requestURI = "/sample";
      CompletableFuture&lt;String&gt; comp = new CompletableFuture&lt;&gt; ();
      HttpClientRequest request = client.request (HttpMethod.GET, requestURI, response -&gt; {
  
        response.bodyHandler (body -&gt; {
          String kmsResponse = new String (body.getBytes ());
          System.out.println ("kmsResponse-" + kmsResponse);
          comp.complete (kmsResponse);
        });
      }).exceptionHandler (e -&gt; {
        e.printStackTrace ();
        comp.completeExceptionally (e);
      });
      request.end ();
  
      String result = "Not Success";
      try {
        result = comp.get ();
      } catch (Exception e) {
        System.out.println ("Exception in getting from Completable..." + e.getMessage ());
        e.printStackTrace ();
      }
      context.response ().setStatusCode (200);
      context.response ().putHeader ("content-type", "text/html");
      context.response ().end (result);
      System.out.println ("end testCompBlocking....");
    }
  
    private void testCompNonBlocking ( RoutingContext context ) {
  
      System.out.println ("Calling testCompNonBlocking....");
      HttpClientOptions clientOptions = new HttpClientOptions ().setDefaultHost ("localhost").setDefaultPort (8080).setKeepAlive (false);
      HttpClient client = vertx.createHttpClient (clientOptions);
  
      String requestURI = "/sample";
      CompletableFuture&lt;String&gt; comp = new CompletableFuture&lt;&gt; ();
      HttpClientRequest request = client.request (HttpMethod.GET, requestURI, response -&gt; {
  
        response.bodyHandler (body -&gt; {
          String kmsResponse = new String (body.getBytes ());
          System.out.println ("kmsResponse-" + kmsResponse);
          comp.complete (kmsResponse);
        });
      }).exceptionHandler (e -&gt; {
        e.printStackTrace ();
        comp.completeExceptionally (e);
      });
      request.end ();
  
      String result = "Not Blocking, please see result at Console";
      try {
        comp.thenAccept (apiResult -&gt; System.out.println ("apiResult from CompletableFuture - " + apiResult));
      } catch (Exception e) {
        System.out.println ("Exception in getting from Completable..." + e.getMessage ());
        e.printStackTrace ();
      }
      context.response ().setStatusCode (200);
      context.response ().putHeader ("content-type", "text/html");
      context.response ().end (result);
      System.out.println ("end testCompNonBlocking....");
    }
  
  }
  </code></pre>
  
  <p>Call <code>localhost:8080/testcompletableblocking</code>, response is not sent and current thread is blocked forever.</p>