如何在Play Framework中暂停请求?

时间:2014-04-13 09:05:37

标签: java asynchronous playframework-2.2 continuations

我正在玩Play Framework(v2.2.2),我正在试图弄清楚如何暂停HTTP请求。我正在尝试在用户之间创建握手,这意味着,我希望用户A能够触发请求并等待用户B“连接”。一旦用户B连接,用户A的请求应返回一些信息(信息无关紧要;现在让我们说一些JSON)。

在我工作的另一个应用程序中,我使用continuation来实质上暂停和重放HTTP请求,所以我有这样的东西......

@Override
public JsonResponse doGet(HttpServletRequest request, HttpServletResponse response) {

  Continuation reqContinuation = ContinuationSupport.getContinuation(request);
  if (reqContinuation.isInitial()) {
    ...
    reqContinuation.addContinuationListener(new ContinuationListener() {
      public void onTimeout(Continuation c) {...}
      public void onComplete(Continuation c) {...}
    });
    ...
    reqContinuation.suspend();
    return null;
  }
  else {
    // check results and return JsonResponse with data
  }
}

...在某些时候,用户B将连接并且继续将在不同的servlet中恢复/完成。现在,我正在试图弄清楚如何在Play中执行此操作。我已经建立了自己的路线......

GET    /test        controllers.TestApp.test()

......我有我的行动......

public static Promise<Result> test() {

  Promise<JsonResponse> promise = Promise.promise(new Function0<JsonResponse>() {
      public JsonResponse apply() {
        // what do I do now...?
        // I need to wait for user B to connect
      }
  });

  return promise.map(new Function<JsonResponse, Result>() {
      public Result apply(JsonResponse json) {
        return ok(json);
      }
  });
}

我很难理解如何构建我的承诺。基本上,我需要告诉用户A“嘿,你在等待用户B,所以这是一个承诺,用户B最终将连接到你,否则我会告诉你什么时候你不必再等了”

如何暂停请求以便我可以返回用户B连接的承诺?如何等待用户B连接?

1 个答案:

答案 0 :(得分:2)

您需要创建一个可以在以后兑换的Promise。奇怪的是,Play / Java库(F.java)似乎没有公开这个API,所以你必须进入Scala Promise class

为自己创建一个小型Scala帮助程序类PromiseUtility.scala

import scala.concurrent.Promise

object PromiseUtility {
  def newPromise[T]() = Promise[T]()
}

然后你可以在控制器中做这样的事情(注意,我不完全理解你的用例,所以这只是如何使用这些Promises的大致轮廓):

if (needToWaitForUserB()) {
  // Create an unredeemed Scala Promise
  scala.concurrent.Promise<Json> unredeemed = PromiseUtility.newPromise();

  // Store it somewhere so you can access it later, e.g. a ConcurrentMap keyed by userId
  storeUnredeemed(userId, unredeemed);

  // Wrap as an F.Promise and, when redeemed later on, convert to a Result
  return F.Promise.wrap(unredeemed.future()).map(new Function<Json, Result>() {
    @Override
    public Result apply(Json json) {
      return ok(json);
    }
  });
}

// [..]
// In some other part of the code where user B connects

scala.concurrent.Promise<Json> unredeemed = getUnredeemed(userId);
unredeemed.success(jsonDataForUserB);