繁体   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