我想创建一个可以与@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
链。
或者我可能尝试做一些愚蠢的事情,而且合成的动作已经异步了?
答案 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);
});
}