簡體   English   中英

使用 JDK8 Streams 和 CompletableFuture 調用 WebService 和 REST API

[英]Call a WebService and a REST API using JDK8 Streams and CompletableFuture

我有一個 SOAP 調用,我需要在 REST 調用中處理 SOAP 調用的結果。 每組調用都基於一批記錄。 我在試圖讓它盡可能異步地使用 JDK8 流運行時完全迷失了。 我怎樣才能做到這一點?

SOAP 致電:

CompletableFuture<Stream<Product>> getProducts(final Set<String> criteria)
{
    return supplyAsync(() -> {
        ...
        return service.findProducts(request);
    }, EXECUTOR_THREAD_POOL);
}

REST 致電:

final CompletableFuture<Stream<Result>> validateProducts(final Stream<Product> products)
{
    return supplyAsync(() -> service
        .submitProducts(products, false)
        .stream(), EXECUTOR_THREAD_POOL);
}

我正在嘗試調用 SOAP 調用,將結果傳遞給 REST 調用,並使用 JDK8 stream 收集結果。 每個 SOAP->REST 調用都是類似於分頁的記錄“集”(或批處理)。 (這現在完全不起作用,只是一個例子)。

@Test
public void should_execute_validations()
{
    final Set<String> samples = generateSamples();

    //Prepare paging...
    final int total = samples.size();
    final int pages = getPages(total);
    log.debug("Items: {} / Pages: {}", total, pages);

    final Stopwatch stopwatch = createStarted();
    final Set<Result> results = range(0, pages)
        .mapToObj(index -> {
            final Set<String> subset = subset(index, samples);
            return getProducts(subset)
                .thenApply(this::validateProducts);
        })
        .flatMap(CompletableFuture::join)
        .collect(toSet());
    log.debug("Executed {} calls in {}", pages, stopwatch.stop());
    assertThat(results, notNullValue());
}

我認為您的示例中有兩種用法不正確: thenApplyjoin

要鏈接第一個調用 (SOAP) 和第二個調用 (REST),您需要使用thenCompose而不是thenApply 這是因為方法“validateProducts”返回可完成的期貨,使用“thenApply”將在您的 stream 映射中創建CompletableFuture<CompletableFuture<Stream<Result>>> 但是您需要的可能是CompletableFuture<Stream<Result>> 使用thenCompose可以解決這個問題,因為它類似於“Optional.flatMap”或“Stream.flatMap”:

.mapToObj(index -> {
    final Set<String> subset = subset(index, samples);
    return getProducts(subset)
        .thenCompose(this::validateProducts);
})

第二個錯誤用法是加入。 使用join阻塞當前線程等待 CompletableFuture 的結果。 在您的情況下,有 N 個可完成的期貨,其中 N 是頁數。 與其一一等待,更好的解決方案是等待所有它們使用CompletableFuture.allOf(...) 此方法返回一個新的 CompletableFuture,它在所有給定的 CompletableFuture 完成時完成。 所以我建議你修改你的 stream 用法並返回一個期貨列表。 然后,等待完成。 最后,檢索結果:

List<CompletableFuture<Stream<Result>>> futures = range(0, pages)
    .mapToObj(index -> {
        final Set<String> subset = subset(index, samples);
        return getProducts(subset).thenCompose(this::validateProducts);
    })
    .collect(Collectors.toList());

CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

for (CompletableFuture<Stream<Result>> cf : futures) {
  // TODO Handle the results and exceptions here
}

您可以在GitHub上看到完整的程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM