回调驱动的Java/Scala未来
短版: 如何创建在回调触发时完成的回调驱动的Java/Scala未来,java,scala,playframework-2.0,akka,nonblocking,Java,Scala,Playframework 2.0,Akka,Nonblocking,短版: 如何创建在回调触发时完成的承诺 长版本: 我正在开发一个处理第三方SOAP服务的应用程序。来自用户的请求同时委托给多个SOAP服务,聚合结果并发送回用户 系统需要具有可扩展性,并应允许多个并发用户。由于每个用户请求最终会触发大约10个web服务调用,并且每个调用会阻塞大约1秒,因此系统需要设计为非阻塞I/O 我正在为这个系统使用ApacheCXFinPlayFramework(Java)。我已经成功地生成了异步WS-Client代理并启用了异步传输。我无法弄清楚的是,当我委托给多个Web
承诺
长版本:
我正在开发一个处理第三方SOAP服务的应用程序。来自用户的请求同时委托给多个SOAP服务,聚合结果并发送回用户
系统需要具有可扩展性,并应允许多个并发用户。由于每个用户请求最终会触发大约10个web服务调用,并且每个调用会阻塞大约1秒,因此系统需要设计为非阻塞I/O
我正在为这个系统使用ApacheCXFinPlayFramework(Java)。我已经成功地生成了异步WS-Client代理并启用了异步传输。我无法弄清楚的是,当我委托给多个Web服务代理,结果将作为回调获得时,如何返回Future to Play的线程
选项1:使用异步方法调用返回Java Future
如本线程所述,我们无法将Java未来转换为Scala未来。从未来获取结果的唯一方法是执行Future.get()
,这会阻止调用方。由于CXF生成的代理返回Java Future,因此排除了此选项
选项2:使用Scala Future
由于CXF生成代理接口,我不确定是否有任何方法可以干预并返回Scala Future(AFAIK Akka使用Scala Future)而不是Java Future
选项3:使用回调方法
CXF生成的返回Java Future的异步方法还接受一个callback对象,我认为当结果准备好时,该对象将提供一个回调。要使用这种方法,我需要返回一个Future,它将等待我收到回调
我认为选项3是最有希望的,尽管我不知道如何在收到回电后返回承诺。我可能有一个线程在中等待,而(true)
则在这两者之间等待,直到结果可用。同样,我不知道如何进入wait
而不阻塞线程
简而言之,我正在尝试构建一个系统,该系统正在进行大量soapweb服务调用,其中每个调用都会阻塞相当长的时间。在大量并发web服务调用的情况下,系统可能很容易耗尽线程。我正在寻找一种基于非阻塞I/O的解决方案,它可以同时允许许多正在进行的web服务调用。选项3看起来不错:)首先要导入两个
import scala.concurrent.{Await, Promise}
import scala.concurrent.duration.Duration
为了说明这一点,这里有一个模拟的CXF API,它接受回调:
def fetch(url: String, callback: String => Unit) = {
callback(s"results for $url")
}
val promise = Promise[String]
fetch("http://corp/api", result => promise.success(result))
创建承诺,使用承诺作为回调调用API:
def fetch(url: String, callback: String => Unit) = {
callback(s"results for $url")
}
val promise = Promise[String]
fetch("http://corp/api", result => promise.success(result))
然后你可以将promise.future
这是future
的一个实例带到你的Play应用程序中
要测试它,可以执行以下操作:
Await.result(promise.future, Duration.Inf)
这将阻止等待结果,此时您应该在控制台中看到“results for”。感谢示例代码,尽管我使用的是Play Java。我想我遗漏的一点是,
承诺
正是实现这一目标的关键。对于Play Java,它是Play.libs.F.retainablepromise
。因此,我可以返回一个ReceivablePromise
的实例,并传递javax.xml.ws.AsyncHandler
的句柄,该句柄中嵌入了promise对象,以便回调对象可以通过success()
调用委托到promise中。我想我理解了Future和Promise now之间的区别,我过去认为它们非常相似。我使用Promise
实现了异步工作。感谢@bjfletchers以4票的优势结束了这个问题,即使我有一个非常精确的简短问题。