在Play Framework 2.0.1(Scala)应用程序中,我们使用的Web服务客户端库返回java.util.concurrent.Future作为响应。

我们希望将get()包装在j.u.c.Future中,而不是在akka.dispatch.Future调用上阻止Play应用,以便我们可以轻松地使用play框架的AsyncResult处理。

有没有人做过,或者有一个库或示例代码?



更新:我们找到的最接近的东西是这个Google网上论坛讨论:https://groups.google.com/forum/#!topic/play-framework/c4DOOtGF50c


...如果您所拥有的只是一个简单的jucFuture,那么创建一个非阻塞解决方案的最佳方法就是获取jucFuture和一个Promise,并将它们提供给运行轮询循环的某个线程,该线程将通过以下方式完成Promise:未来的结果。


有人对此有示例实现吗?

最佳答案

@Viktor Klang:我们知道j.u.c.Future是可憎的。但这就是我们从暂时必须接受的软件中得到的回报。

到目前为止,这是我们共同努力的目标:

def wrapJavaFutureInAkkaFuture[T](javaFuture: java.util.concurrent.Future[T], maybeTimeout: Option[Duration] = None)(implicit system: ActorSystem): akka.dispatch.Future[T] = {
  val promise = new akka.dispatch.DefaultPromise[T]
  pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeTimeout.map(_.fromNow))
  promise
}


换句话说,创建与Promise对应的单独的Akka Futurej.u.c.Future的写端),启动回调pollJavaFutureUntilDoneOrCancelled以通过轮询“憎恶”来更新Promise,然后返回答应来电者。

那么我们如何根据j.u.c.Future的状态来“轮询”更新Akka Promise?

def pollJavaFutureUntilDoneOrCancelled[T](javaFuture: java.util.concurrent.Future[T], promise: akka.dispatch.Promise[T], maybeDeadline: Option[Deadline] = None)(implicit system: ActorSystem) {
  if (maybeDeadline.exists(_.isOverdue)) javaFuture.cancel(true);

  if (javaFuture.isDone || javaFuture.isCancelled) {
    promise.complete(allCatch either { javaFuture.get })
  } else {
    Play.maybeApplication.foreach { implicit app =>
      system.scheduler.scheduleOnce(50 milliseconds) {
        pollJavaFutureUntilDoneOrCancelled(javaFuture, promise, maybeDeadline)
      }
    }
  }
}


这是对我在问题中引用的Google网上论坛讨论中所暗示的尝试。它使用Akka调度程序每50毫秒进行一次回调,以检查j.u.c.Future是否完成或取消。每当发生这种情况时,它都会以完成状态更新Akka Promise。

@Victor Klang等:

这是最佳做法吗?您知道更好的方法吗?我们在这里缺少应该知道的缺点吗?

多谢您的协助。

关于scala - 如何在Akka Future中包装java.util.concurrent.Future?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11529145/

10-11 22:27
查看更多