Java中的Play Framework 2.5中的动作组合和异步

时间:2016-08-22 12:02:15

标签: java asynchronous playframework

我想创建一个可以与@With注释样式一起使用的动作。此操作需要进行RPC调用,因此如果我正确理解了文档,我应该以异步方式将其放入。

这是我到目前为止所做的事情:

public class GetUserIdAction extends play.mvc.Action.Simple {

  @Override
  public CompletionStage<Result> call(Http.Context context) {
    String token = "";

    if (StringUtils.isEmpty(token)) {
      return delegate.call(context);
    }

    CompletionStage<Http.Context> promiseOfUpdatedContext = CompletableFuture.supplyAsync(() -> setUserIdForToken(context, token));

    return promiseOfUpdatedContext.thenApply(ctx -> delegate.call(ctx));
  }

  private Http.Context setUserIdForToken(Http.Context context, String token) {
    context.args.put("user_id", authenticationManager.getUserIdForToken(token));
    // The AuthenticationManager is issuing an RPC call and thus may take some time to complete.
    return context;
  }
}

撇开token始终为空并且未设置authenticationManager的事实,这只是一个快速无意义的示例,我的IDE在thenApply部分抱怨。根据我的理解,它期待CompletionStage<Result>并获得更像CompletionStage<CompletionStage<Result>>的内容。

有什么方法可以解决它?因此,我想要的是在上下文中放置一些信息,然后继续delegate.call链。

或者我可能尝试做一些愚蠢的事情,而且合成的动作已经异步了?

1 个答案:

答案 0 :(得分:1)

您有CompletionStage<Something>并希望以CompletionStage<Result>结尾。最简单的方法是使用thenCompose

这是一个示例,只有一个小的改动:我有一个CompletableFuture来获取令牌,然后我将它添加到HttpContext

@Override
public CompletionStage<Result> call(final Http.Context context) {
    final String token = "";

    if (StringUtils.isEmpty(token)) {
        return delegate.call(context);
    }

    return CompletableFuture.supplyAsync(() -> {
        // do something to fetch that token
        return "your_new_token";
    }).thenCompose(tokenReceived -> {
        context.args.put("user_id", tokenReceived);
        return delegate.call(context);
    });
}