Why the http client example doesn't work like that

106 views
Skip to first unread message

Alexander Lehmann

unread,
Oct 20, 2016, 6:04:34 PM10/20/16
to vert.x
Continuing the question from here https://groups.google.com/d/msg/vertx-dev/p-NRTEnqDQE/hiMWMgxzBQAJ

The result of an async operation is not available when the operation is started, only later in the handler, which is called when the operation is finished. This is a bit counter-intuitive, since the flow of the program is different than it looks in the source code and the variable definitions are available.

HttpClientOptions options = new HttpClientOptions().setKeepAlive(false);
options
.setLogActivity(true);
options
.setDefaultHost("delvmpllbbab10");

options
.setDefaultPort(7003);
HttpClient client = vertx.createHttpClient(options);
String[] resp = {null};

client
.request(HttpMethod.GET, "/rcsservices/homePage", response -> {
   response
.handler(buffer -> {
   
System.out.println("Received a part of the response body: " + buffer);
   resp
[0] = buffer.toString();
 
}
);
}).putHeader("content-type", "application/json").end(Json.encodePrettily(resp[0]));

System.out.println(resp[0]);


The handler lambda is executed much later than the code creating the request and the code after the method call, at this point the resp value is still null.

(btw, this also means that using it in the .end() method just creates a JSON null string)

If you consider of the execution of the different parts as thread-flows (for the lack of a better name, which isn't quite correct since it is not different threads, everything in the same context is executed in a single thread), the thread that creates the request continues with the code after the method immediately and the lambda is only a constant value at that point, it is run as another "thread" later.
Message has been deleted

Jez P

unread,
Oct 21, 2016, 3:04:58 AM10/21/16
to vert.x
You can't set http request headers after you get the response, the request is being processed then (this isn't just a vert.x thing by the way). If you want to do this, you should make one request to retrieve the value you want to write in the request header, and when you get the result of that you make a second request to actually get the body you want. My question is: why would you want to do that? The first request actually gets you the body anyway, so why do you want to write the header?

On Friday, October 21, 2016 at 7:55:19 AM UTC+1, Yogesh Kumar wrote:
 
  Thanks Alex,

  For giving Your costly time, I got your point. But I how can I overcome of this problem. Need to make a sync call or make a new thread.
  For more information providing the whole code of class.


public class FirstVerticle extends AbstractVerticle {
    private Map<Integer, DataBean> products = new LinkedHashMap<>();
    private final static String USER_AGENT = "Mozilla/5.0";
    @Override
    public void start(Future<Void> fut) {
        System.out.println("[FirstVerticle] Starting in " + Thread.currentThread().getName());
        createSomeData();
        VertxOptions options = new VertxOptions();
        options.setMaxEventLoopExecuteTime(Long.MAX_VALUE);
        vertx = Vertx.vertx(options);

        vertx.deployVerticle(new SecondVerticle());

        Router router = Router.router(vertx);
        vertx.deployVerticle(new RestApi());


        router.route("/").handler(routingContext -> {
            HttpServerResponse response = routingContext.response();
            response
                    .putHeader("content-type", "text/html")
                    .end("<h1>Hi , Demo is on Progress : Yogesh Kumar</h1>");
        });

        // Serve static resources from the /assets directory
        router.get("/httpData/new").handler(this::getData);

        vertx
                .createHttpServer()
                .requestHandler(router::accept)
                .listen(
                        // Retrieve the port from the configuration,
                        // default to 8080.
                        config().getInteger("http.port", 9901),
                        result -> {
                            if (result.succeeded()) {
                                fut.complete();
                            } else {
                                fut.fail(result.cause());
                            }
                        }
                );
    }

   private void getData(RoutingContext routingContext) {
        //String url = "http://delvmpllbbab10:7003/rcsservices/homePage";
        HttpServerResponse serverResponse = routingContext.response();
        System.out.println("inside new method");
        try {
            Future<HttpClientOptions >HttpClientOptions options = new HttpClientOptions().setKeepAlive(false);

            options.setLogActivity(true);
            options.setDefaultHost("delvmpllbbab10");
            options.setDefaultPort(7003);
            HttpClient client = vertx.createHttpClient(options);
             String[] resp = {null};
            AtomicBoolean bodyEndHandlerHit = new AtomicBoolean();

            client.request(HttpMethod.GET, "/rcsservices/homePage", response -> {
                response.handler(buffer -> {
                    System.out.println("Received a part of the response body: " + buffer);
                    resp[0] = buffer.toString();
                });
                bodyEndHandlerHit.set(true);

            }).putHeader("content-type", "application/json").end(Json.encodePrettily(resp[0]));
            System.out.println(resp[0]);
          
           }catch (Exception e){
            e.printStackTrace();
        }
   }
}



Thanks In Advance.
Yogesh Kumar

Yogesh Kumar

unread,
Oct 21, 2016, 3:10:43 AM10/21/16
to vert.x
  Thanks Alex,

  For giving Your costly time, I got your point. But I how can I overcome of this problem. Need to make a sync call or make a new thread.
  For more information providing the whole code of class.

public class FirstVerticle extends AbstractVerticle {
   
    private final static String USER_AGENT = "Mozilla/5.0";
    @Override
    public void start(Future<Void> fut) {
        System.out.println("[FirstVerticle] Starting in " + Thread.currentThread().getName());
       
       
            Future<HttpClientOptions >HttpClientOptions options = new HttpClientOptions().setKeepAlive(false);

            options.setLogActivity(true);
            options.setDefaultHost("delvmpllbbab10");
            options.setDefaultPort(7003);
            HttpClient client = vertx.createHttpClient(options);
            String[] resp = {null};
            client.request(HttpMethod.GET, "/rcsservices/homePage", response -> {
                response.handler(buffer -> {
                    System.out.println("Received a part of the response body: " + buffer);
                    resp[0] = buffer.toString();
                });
            }).putHeader("content-type", "application/json").end(Json.encodePrettily(resp[0]));
            System.out.println(resp[0]);
          

        }catch (Exception e){
            e.printStackTrace();
        }
   }
}

Thanks In Advance
Yogesh Kumar

On Friday, October 21, 2016 at 3:34:34 AM UTC+5:30, Alexander Lehmann wrote:

Yogesh Kumar

unread,
Oct 21, 2016, 3:25:18 AM10/21/16
to vert.x

  Hi Jez,

 Thanks a lot for your quick reply.

   Actually I do this code with help of Vert.x Docx and with help of you guys, I am not too much aware(i.e. I am a new on vertx) about it. Actually I just know that If I am putting  header     ".putHeader("content-type", "application/json").end(Json.encodePrettily(resp[0]));" like this , It will send my response on browser. Is there any other way to send response back with the  same request, So please guide me for that.

 Thanks & regards,
Yogesh

Jez P

unread,
Oct 21, 2016, 3:30:09 AM10/21/16
to vert.x
Please see my message above. Http doesn't say "you can get part of the body then set a header to tell the server you're already calling what the body you're going to send it is", and that's what you're trying to do.

If you wanted to do that, it's two requests, one to determine the content type you should send and then a second after the first completes to use that in the header. So in your handler, you could set a body handler, and in the body handler extract the header value, and use that to start a new request (still in the body handler code). To overcome the callback-hell style result you could either use rxJava or something like vertx-when (or if in Java use vertx-sync to make your code appear synchronous even though under the hood it would be asynchronous). 

Alexander Lehmann

unread,
Oct 22, 2016, 9:56:02 AM10/22/16
to vert.x
I think I can about guess what you are trying to do with your code, however "fixing" it without knowing what is it supposed to do exactly is difficult.

Could you maybe post a complete project of the test you are trying to do (either as unit test or with a runnable main that creates the server) on Github preferably?

Checking the program based on code snippets is quite difficult since it is not always clear what the whole program is supposed to do (plus its more easily readable on Github and it supports diffs).

Another possibility would be that you implement the same program with a "normal" java api like apache HC and tomcat and post that so we can base a vert.x version on that.


bye, Alexander

Yogesh Kumar

unread,
Oct 24, 2016, 1:28:43 AM10/24/16
to vert.x

    Thanks A lot Alex and Jez.

  After went through the deeply vert.x doc , able to understand what you were trying to explain me.
  Now code is working fine, with the help EndHandler problem resolved out as i got it in one of Blog post.

  Due to this Group and member's here like you I am able to implement VERT.X from zero level to till progress .
  Thanks a lot for giving your costly time.

   Thanks ,
   Yogesh Kumar.
Reply all
Reply to author
Forward
0 new messages