如何在playframework java api中将Observable转换为Promise

时间:2015-10-02 07:53:57

标签: playframework promise reactive-programming rx-java

我使用promises的默认实现如下:

public F.Promise<Result> index() {
   return F.Promise.promise(() -> intensiveComputationSync())
       .map(result -> ok(String.valueOf(result)));
}

但现在我有了rx api:

private Observable<Integer> intensiveComputationObservable() {
   return Observable.create(subscriber -> {
      try {
         subscriber.onNext(intensiveComputationSync());
      } catch (Exception e) {
         subscriber.onError(e);
      }
      subscriber.onCompleted();
   });
}

如何在承诺中使用我的rx api?特别感兴趣的是正确的错误处理。

2 个答案:

答案 0 :(得分:2)

以下是在Play 2.5中执行此操作的方法:

public CompletableFuture<Result> callRPC() {
    Observable<Object> result =  <create observable>
    CompletableFuture<Object>  completableFuture = new CompletableFuture<>();

    result.subscribe((active) ->  completableFuture.complete(active),
            (err) -> completableFuture.completeExceptionally(err));

    return completableFuture.thenApply( i -> ok(Json.toJson(i)));

}

答案 1 :(得分:0)

好像我找到了解决方案。

使用promise包装observable的函数:

   public static <T> F.Promise<T> observableToPromise(Observable<T> obs) {
      scala.concurrent.Promise<T> scalaPromise = scala.concurrent.Promise$.MODULE$.<T>apply();
      obs.subscribe(
          result -> scalaPromise.success(result),
          throwable -> scalaPromise.failure(throwable)
      );
      return F.Promise.wrap(scalaPromise.future());
   }

现在我的行​​动:

   public F.Promise<Result> index() {
      //convert observable to promise then map computation result to F.Promise<Result>
      F.Promise<Result> succeedPromise =
          observableToPromise(
              //computation on another thread
              intensiveComputationObservable().subscribeOn(Schedulers.newThread())
          ).map(result -> ok(String.valueOf(result)));

      //if exception while computation thrown, we returns another status
      return succeedPromise
          .recoverWith(throwable -> F.Promise.pure(internalServerError("error")));
   }