Playframework 控制器外部的异步WS-calls和Wait()
有没有办法在控制器之外使用await()机制 我不希望让代码在控制器中进行异步调用,而是将代码放在可由多个控制器重用的服务类中。然而,由于该方法受到保护,因此无法在控制器外部调用wait 例如,在控制器中:Playframework 控制器外部的异步WS-calls和Wait(),playframework,Playframework,有没有办法在控制器之外使用await()机制 我不希望让代码在控制器中进行异步调用,而是将代码放在可由多个控制器重用的服务类中。然而,由于该方法受到保护,因此无法在控制器外部调用wait 例如,在控制器中: ServiceClass service = new My ServiceClass(); MyObject myObject= service.getMeAnObject(); render(myObject); 服务级别: public class Servic
ServiceClass service = new My ServiceClass();
MyObject myObject= service.getMeAnObject();
render(myObject);
服务级别:
public class ServiceClass
{
...
public MyObject getMeAnObject()
{
String url = "http://...";
Promise<HttpResponse> promise = url(url).getAsync();
// do something here similar to await in a controller
// that suspends the code waiting for the response
// to be retrieved
HttpResponse response = promise.get();
return buildMyObjectFromResponse(reponse);
}
...
}
公共类服务类
{
...
公共MyObject getMeAnObject()
{
字符串url=”http://...";
Promise Promise=url(url).getAsync();
//在这里执行类似于在控制器中等待的操作
//这将暂停代码等待响应
//取回
HttpResponse response=promise.get();
返回buildMyObjectFromResponse(response);
}
...
}
有没有办法做到这一点
谢谢你的帮助
编辑:我遵照Pere的建议,让服务类实现了控制器,它可以工作,但是,有必要对使用它的控制器进行增强。我发现完成该任务的唯一方法是在调用控制器类中至少调用一次wait method() 但是,我仍然没有验证代码是否实际挂起
编辑2:我从谷歌集团得到的一个建议是,我应该真正尝试在控制器中执行等待操作,因此可能更好的解决方案是让服务返回 承诺并让控制员等待,但是 我没办法这么做,是吗 例如,在控制器中:
ServiceClass service = new My ServiceClass();
Promise<MyObject> promise = service.getMeAnObject();
MyObject myObject = await(promise);
render(myObject);
ServiceClass service = new My ServiceClass();
Promise<MyObject> promise = service.getMeAnObject();
MyObject myObject = await(promise);
render(myObject);
ServiceClass服务=新建我的ServiceClass();
Promise Promise=service.getMeAnObject();
MyObject MyObject=等待(承诺);
渲染(myObject);
服务级别:
public class ServiceClass
{
...
public Promise<MyObject> getMeAnObject()
{
String url = "http://...";
// Somehow Build a Promise<MyObject>
}
...
}
public class ServiceClass
{
public Promise<MyObject> getMeAnObject()
{
String url = "http://...";
return execute(WS.url(url).getAsync());
}
private Promise<MyObject> execute(final Promise<HttpResponse> promise)
{
try
{
final Promise<MyObject> smartFuture = new Promise<MyObject>();
ScheduledThreadPoolExecutor executor = MyAppThreadPools.getServiceThreadPool();
executor.submit(new Runnable()
{
@Override
public void run()
{
try
{
smartFuture.invoke(new MyObject(promise.get()));
}
catch (Throwable e)
{
smartFuture.invokeWithException(e);
}
}
});
return smartFuture;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
公共类服务类
{
...
公共承诺getMeAnObject()
{
字符串url=”http://...";
//以某种方式建立一个承诺
}
...
}
}如您所述,Wait只能从控制器访问
使服务类扩展控制器,在其中创建许多受保护的支持方法,并将其用作控制器的父类
通过这种方式,您可以跨控制器共享实现,同时可以访问所有控制器方法(wait、render等)。到目前为止,我认为这是我发现的最好的方法,除非在Play实例中管理单独的线程池有问题 我已经举例说明了Play在WSAsync.WSAsync请求中的作用 这似乎是有效的 本质上,等待是在控制器内完成的,但是服务类返回我期望服务返回的对象的承诺,这很好,因为我不知道如何在控制器级别检索该对象的细节 在控制器中:
ServiceClass service = new My ServiceClass();
Promise<MyObject> promise = service.getMeAnObject();
MyObject myObject = await(promise);
render(myObject);
ServiceClass service = new My ServiceClass();
Promise<MyObject> promise = service.getMeAnObject();
MyObject myObject = await(promise);
render(myObject);
ServiceClass服务=新建我的ServiceClass();
Promise Promise=service.getMeAnObject();
MyObject MyObject=等待(承诺);
渲染(myObject);
服务级别:
public class ServiceClass
{
...
public Promise<MyObject> getMeAnObject()
{
String url = "http://...";
// Somehow Build a Promise<MyObject>
}
...
}
public class ServiceClass
{
public Promise<MyObject> getMeAnObject()
{
String url = "http://...";
return execute(WS.url(url).getAsync());
}
private Promise<MyObject> execute(final Promise<HttpResponse> promise)
{
try
{
final Promise<MyObject> smartFuture = new Promise<MyObject>();
ScheduledThreadPoolExecutor executor = MyAppThreadPools.getServiceThreadPool();
executor.submit(new Runnable()
{
@Override
public void run()
{
try
{
smartFuture.invoke(new MyObject(promise.get()));
}
catch (Throwable e)
{
smartFuture.invokeWithException(e);
}
}
});
return smartFuture;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
公共类服务类
{
公共承诺getMeAnObject()
{
字符串url=”http://...";
返回execute(WS.url(url.getAsync());
}
私人承诺执行(最终承诺)
{
尝试
{
最终承诺smartFuture=新承诺();
ScheduledThreadPoolExecutor=MyAppThreadPools.getServiceThreadPool();
执行者提交(新的可运行()
{
@凌驾
公开募捐
{
尝试
{
调用(新的MyObject(promise.get());
}
捕获(可丢弃的e)
{
智能未来。调用异常(e);
}
}
});
回归未来;
}
捕获(例外e)
{
抛出新的运行时异常(e);
}
}
}
这似乎解决了我目前的问题
谢谢大家。这可能太晚了,无法帮助您:)但方法是使用Promise.onredeme()方法调用控制器中返回和等待的新Promise
public Promise<Boolean> deauthorise() {
final Promise<Boolean> promise = new Promise<>();
WS.url("https://connect.stripe.com/oauth/deauthorize")
.setParameter("client_secret", play.Play.configuration.getProperty("stripe.secretKey"))
.setParameter("client_id", play.Play.configuration.getProperty("stripe.clientId"))
.setParameter("stripe_user_id", this.stripeUserId)
.postAsync()
.onRedeem(new Action<Promise<HttpResponse>>() {
@Override
public void invoke(Promise<HttpResponse> result) {
HttpResponse response = result.getOrNull();
promise.invoke(response != null && response.success());
}
});
return promise;
}
public Promise deauthorise(){
最终承诺=新承诺();
WS.url(“https://connect.stripe.com/oauth/deauthorize")
.setParameter(“client_secret”,play.play.configuration.getProperty(“stripe.secretKey”))
.setParameter(“client_id”,play.play.configuration.getProperty(“stripe.clientId”))
.setParameter(“stripe\u user\u id”,this.stripeUserId)
.postAsync()
.OnReceive(新操作(){
@凌驾
公共无效调用(承诺结果){
HttpResponse response=result.getOrNull();
promise.invoke(response!=null&&response.success());
}
});
回报承诺;
}
谢谢您的回复。它似乎确实起作用了。然而,在我看来,这并不是最好的解决方案,因为服务类在概念上不是控制器。理想情况下,这种代码中断机制可以在任何地方使用。