使用Java的Play框架中的链承诺

时间:2015-04-14 00:31:10

标签: java playframework reactive-programming

我有一个控制器操作,我需要调用第三方Web服务。

我的问题是我没有打电话给一个网络服务。我需要链接4到5个Web服务。我调用的每个Web服务都返回一个我需要处理的JSON对象,并根据一些逻辑决定调用另一个Web服务(来自4个Web服务)或者向调用者返回响应。这就是我想要做的事情:

 public static Promise<Result> accounts(){
    return WS.url("url1").get().map(response1 -> {
        JsonNode mynode = response1.asJson();

        if (mynode.get("status").asInt()==200){
            Promise<JsonNode> jsonPromise = WS.url("url2").get().map(response2->{
                    return response2.asJson();
            });
        }

        return ok(mynode);
        }); 
}

现在,从文档中,我认为我需要的是链接每个Web服务调用都是承诺的承诺。但我不知道该怎么做?

谢谢

2 个答案:

答案 0 :(得分:7)

他们称之为 活性成分 ,就像这样做 - &gt;

public static Promise<Result> reactiveCombo() {
    Promise<WSResponse> promise1 = WS.url("url1").get();
    Promise<WSResponse> promise2 = WS.url("url2").get();
    Promise<WSResponse> promise3 = WS.url("url3").get();

    return promise1.flatMap(response1 -> {
        final JsonNode json1 = response1.asJson();
        if (!json1.has("someField")) {
            return Promise.promise(() -> badRequest());
        }
        return promise2.flatMap(response2 -> {
            final JsonNode json2 = response2.asJson();
            if (json1.get("someField").asText().equals(json2.get("someField").asText())) {
                return Promise.promise(() -> badRequest());
            }
            return promise3.map(response3 -> {
                final JsonNode json3 = response3.asJson();
                if (json3.get("boolField").asBoolean()) {
                    return badRequest();
                }
                return ok();
            });
        });
    });
}

对于大量的通话,您可以使用Promise.sequence()并获得“广告素材”:

private static Promise<JsonNode> getPromise(String url, Predicate<JsonNode> predicate) {
    return WS.url(url).get().map(response -> {
        JsonNode json = response.asJson();           
        if (predicate.negate().test(json)) {
            throw new Exception("BUMMER!");
        }
        return json;
    });
}

public static Promise<Result> reactiveCombo(List<String> urls) {
    List<Promise<JsonNode>> promises = new ArrayList<Promise<JsonNode>>(urls.size());
    Predicate<String> predURL = p -> p.contains("goodApi");
    Predicate<JsonNode> pred1 = p -> p.has("boolField") && p.get("boolField").asBoolean();
    Predicate<JsonNode> pred2 = p -> p.has("someField");

    urls.forEach(url -> {
        Promise<JsonNode> promise = predURL.test(url) ? getPromise(url, pred1) : getPromise(url, pred2);           
        promises.add(promise);
    });

    return Promise.sequence(promises).map(results -> ok()).recover(t -> badRequest());
}

其他详细信息+ docudrama:

Go Reactive with Java 8 & Play Framework(陈旧但仍然具有教育性)

JavaWS

答案 1 :(得分:4)

您可以使用递归将此结构展平为任意数量的Promise。 首先创建一个类:

public static class ChainedWebService {
    public final Optional<ChainedWebService> next;

    public final WSRequestHolder wsResponsePromise;
    private final F.Predicate<JsonNode> predicate;

    public ChainedWebService(String url, Optional<ChainedWebService> next, F.Predicate<JsonNode> predicate) {
        this.next = next;
        this.wsResponsePromise = WS.url(url);
        this.predicate = predicate;
    }

    public F.Promise<Result> processChain() {
        return wsResponsePromise.get().flatMap(new F.Function<WSResponse, F.Promise<Result>>() {
            @Override
            public F.Promise<Result> apply(WSResponse wsResponse) throws Throwable {
                if (!predicate.test(wsResponse.asJson())) {
                    return F.Promise.pure(badRequest());
                }

                if (!next.isPresent()) {
                    return F.Promise.pure(ok());
                }

                return next.get().processChain();
            }
        });
    }
}

然后使用它:

public static F.Promise<Result> reactiveCombo() {
    ChainedWebService chainedWebService3 = new ChainedWebService(
            "url3",
            Optional.<ChainedWebService>empty(),
            jsonNode -> jsonNode.get("boolField").asBoolean()
    );

    ChainedWebService chainedWebService2 = new ChainedWebService(
            "url2",
            Optional.of(chainedWebService3),
            jsonNode -> jsonNode.get("someField").asText().equals(jsonNode.get("someField").asText()));

    ChainedWebService chainedWebService1 = new ChainedWebService(
            "url1",
            Optional.of(chainedWebService2),
            jsonNode -> jsonNode.has("someField")
    );

    return chainedWebService1.processChain();
}

您可以实施一些基本构建器,以使构建过程更合理。

希望有所帮助!