Как сохранить результат Vert.x WebClient и вернуть его в метод - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть метод, который используется в моем проекте Java Vert.x, который вызывает другую службу, используя WebClient.Я хочу сохранить результат этого вызова в JsonObject и вернуть его.Я предполагаю, что мне нужно использовать фьючерсы для этого, но когда я запускаю GetItemsService.retrieveItems, кроме моего сообщения «печать будущего ниже», все, что я вижу в консоли, это Future{unresolved}.

Как я могусохранить результат из моего GetItemsManager.getItems вызова веб-клиента в переменной?

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);
    }
}

ОБНОВЛЕНИЕ

Согласно ответу Петра, я 'я пытался обновить мой код следующим образом:

   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);
    }
  }

Я все еще не могу присвоить результат вызова переменной (f).

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Надеюсь, это поможет, я попытался добавить полезные комментарии к вашему коду.

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
    }
}

// Вариант 2, если вы хотитевыполнить какой-то другой асинхронный метод

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;
    }
}
0 голосов
/ 21 ноября 2018

Попробуйте что-то вроде

public class GetItemsService {
    public void retrieveItems(Vertx vertx, RoutingContext routingContext) {
        Future<JsonObject> future = Future.future();
        new GetLocationsManager().getItems(future, vertx, routingContext);
        future.setHandler(h ->{
            routingContext.response().end(h.result().encode());
        });
    }
}
...