How to save Vert.x WebClient result and return it in method

aCarella :

I have a method that is used in my Java Vert.x project which calls another service using WebClient. I want to save the result of that call in a JsonObject and return it. I'm assuming that I need to use futures for this, but when I run GetItemsService.retrieveItems, aside from my "print future below" message all I see in the console is Future{unresolved}.

How can I save the result from my GetItemsManager.getItems web client call in a variable?

public class GetItemsManager {
    public Future<JsonObject> getItems(Future<JsonObject> future, Vertx vertx, RoutingContext routingContext) {
        WebClient webClient = WebClient.create(vertx);
        HttpServerResponse response = routingContext.response();
        JsonObject data = new JsonObject();
        response.setChunked(true);
        response.putHeader("content-type", "text/plain");
        response.putHeader("Access-Control-Allow-Origin", "*");
        webClient.post(80, Constants.API_URL, "/items")
            .as(BodyCodec.jsonArray())
            .putHeader("Accept", "application/json")
            .putHeader("Content-Type", "application/json")
            .putHeader("ugws7", Constants.SERVICES_URL)
            .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
                if (ar.succeeded()) {
                    HttpResponse<JsonArray> result = ar.result();
                    JsonArray body = result.body();
                    data.put("data", body.getJsonObject(0));
                    future.complete(data);
                } else {
                    future.fail(new JsonObject().put("error", ar.cause().getMessage()).encode());
                }
            });
            return future;
    }
}

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GetItemsManager().getItems(future, vertx, routingContext);
        String jsonObject = future.toString();
        System.out.println("print future below");
        System.out.println(jsonObject);
    }
}

UPDATE

As per Peter's answer, I've tried to update my code with the following:

   public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GeItemsManager().getItems(future, vertx, routingContext);
        String jsonObject;
        Future<JsonObject> f = future.setHandler(handler -> {
            handler.result();
        });
        System.out.println("Print future below");
        System.out.println(f);
    }
  }

I still cannot assign the result of the call to a variable (f).

taygetos :

I hope this helps i tried to add useful comments to your code.

GetItemsManager

public class GetItemsManager {
public Future<JsonObject> getItems(Vertx vertx, RoutingContext routingContext) {
    //Note1: you can create the future here, no need to pass as a parameter
    Future<JsonObject> future = Future.future(); 
    ...
    webClient.post(80, Constants.API_URL, "/items")
        ...
        .sendJsonObject(new JsonObject().put("mutator", "*"), ar -> {
            if (ar.succeeded()) {
                ...
                future.complete(data);
            } else {
                future.fail(new JsonObject().put("error", ar.cause().getMessage()).encode());
            }
        });
        return future;
}
}

GetItemsService

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        new GetLocationsManager().getItems(vertx, routingContext) // returns Future<JsonObject>
            .setHandler(handler -> {
                //Note2: this codeblock is executed when your future is completed (or failed)
                if(handler.succeeded()){
                    //Note3: handler.result() contains the result from the getItems call (future.complete(data))
                    JsonObject items = handler.result();
                    doSomethingWithTheItems(items);
                    String itemsEncodedToString = items.encode();
                    // serve the response
                    routingContext.response().end(itemsEncodedToString);
                }else{
                    // serve error response
                    routingContext.response().end("something terrible happened" + handler.cause());
                }
        });
    }

    public void doSomethingWithTheItems(JsonObject items){
        // do something here with your items
    }
}

// Option 2 if you want to execute some other async method

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        new GetLocationsManager().getItems(vertx, routingContext);
            .compose(this::doSomethingAsyncWithTheItems)
            .setHandler(handler -> {
                if(handler.succeeded()){
                    //Note4: handler.result() contains the result from the doSomethingAsyncWithTheItems call (future.complete(...))
                    JsonObject didSomethingWithTheItems = handler.result();
                    routingContext.response().end(didSomethingWithTheItems.encode());
                }else{
                    // serve error response
                    routingContext.response().end("something terrible happened");
                }
        });
    }

    public Future<JsonObject> doSomethingAsyncWithTheItems(JsonObject items){
        Future<JsonObject> future = Future.future(); 
        otherAsyncCallThatReturnsAFuture.setHandler(handler -> {
            if(handler.succeeded()){
                future.complete(...)
            }else{
                future.fail(...)
            }
        })
        return future;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=128555&siteId=1