【问题标题】:Spring Boot Controller returning a Mono of a scala.concurrent.FutureSpring Boot Controller 返回 scala.concurrent.Future 的 Mono
【发布时间】:2020-07-04 09:36:03
【问题描述】:

我在 Spring Boot 应用程序中运行 Akka 演员系统。我有一组正在运行的 Actor。

从我的 Controller 类中,我调用我的服务类,使用 Actor 询问模式,向 Actor 发送消息并期望得到响应。下面是服务方法代码:

public Mono<Future<SportEventDetailed>> getEventBySportAndLeagueId(Integer sportId, Integer leagueId) {
    final ActorSelection actorSelection = bootstrapAkka.getActorSystem().actorSelection("/user/some/path");
    final ActorMessage message = new ActorMessage()

    final CompletionStage<Future<SportEventDetails>> futureCompletionStage = actorSelection.resolveOne(Duration.ofSeconds(2))
            .thenApplyAsync(actorRef ->
                        Patterns.ask(actorRef, message, 1000)
                        .map(v1 -> (SportEventDetails) v1, ExecutionContext.global())
                )
                .whenCompleteAsync((sportEventDetailsFuture, throwable) -> {
                    // Here sportEventDetailsFuture is of type scala.concurrent.Future
                    sportEventDetailsFuture.onComplete(v1 -> {
                        final SportEventDetails eventDetails = v1.get();
                        log.info("Thread: {} | v1.get - onComplete - SED: {}", Thread.currentThread(), eventDetails);
                        return eventDetails;
                    }, ExecutionContext.global());
                });

    return Mono.fromCompletionStage(futureCompletionStage);
}

虽然控制器代码很简单

@GetMapping(path = "{sportId}/{leagueId}")
public Mono<Future<SportEventDetails>> getEventsBySportAndLeagueId(@PathVariable("sportId") Integer sportId, @PathVariable("leagueId") Integer leagueId) {
    return eventService.getEventBySportAndLeagueId(sportId, leagueId);
}

当客户端调用此端点时,它会得到{"success":true,"failure":false}null(作为字符串)。

我怀疑null 响应的问题是scala.concurrent.Future 在响应发送到客户端之前没有完成 - 但我不明白为什么它不能按时完成,因为我认为 Mono 会等待未来完成

这里的问题是Patterns.ask 返回一个scala.concurrent.Future&lt;SportEventDetails&gt;,我找不到将scala Future 转换为Java CompletableFuture&lt;SportEventDetails&gt;CompletionStage&lt;SportEventDetails&gt; 的方法。

所以,我的问题是:使用 Akka 的 Patterns.ask(...) 模型时,如何将 SportEventDetails 的 json 表示返回给客户端?

【问题讨论】:

    标签: java spring scala akka reactor


    【解决方案1】:

    FutureMonoCompletionStage 是同一概念的三个实现,一个值可能还存在也可能不存在。您将需要一种将它们转换为相同类型的方法,然后是一种“扁平化”嵌套类型的方法。 Mono.fromCompletionStage 是一种将CompletionStage 转换为Mono 的方法。

    最简单的方法是避免获得Future 和完全展平:

    在较新的 Java 版本(2.5.19 或更高版本)中: 有ask 重载采用java.time.Duration 超时,您将获得CompletionStage&lt;SportEventDetail&gt; 的返回值。还有ask 重载需要ActorSelection,这样您就不必先解决,然后再询问解决何时完成:

    CompletionStage<SportEventDetail> futureSportEventDetails = 
      Patterns.ask(selection, message, Duration.ofSeconds(3))
    return Mono.fromCompletionStage(futureSportEventDetails);
    

    在旧版本的 Akka(我认为是 2.4.2 和更高版本)中,您应该能够在 akka.pattern.PatternsCS 中找到类似的签名。

    如果您使用的是更旧的版本并且无法升级,您可能必须提供您自己的从 Future&lt;T&gt;CompletionStage&lt;T&gt;Mono&lt;T&gt; 的转换器方法,该方法在未来注册一个 onComplete 侦听器并完成一个实例目的地类型。

    【讨论】:

      猜你喜欢
      • 2019-09-26
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      • 2012-06-01
      • 1970-01-01
      相关资源
      最近更新 更多