Reputation: 296
I want to create an action that I can use with the @With
annotation style. This action will need to proceed to an RPC call so if I understood correctly the documentation I should rather put this in an async way.
This is what I tried to do until now:
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;
}
}
Set aside the fact that token
is always empty and authenticationManager
is not set, this is just a quick meaningless example, my IDE is complaining on the thenApply
part. For what I understand, it is expecting a CompletionStage<Result>
and gets something more like a CompletionStage<CompletionStage<Result>>
.
What is a way to deal with it? Cause here all I want is to put some information in the Context and then continue the delegate.call
chain.
Or maybe I'm trying to do something stupid and composed actions are already asynchronous?
Upvotes: 2
Views: 534
Reputation: 12996
You have a CompletionStage<Something>
and want to end with a CompletionStage<Result>
. The easiest way to achieve that is using thenCompose
.
Here is an example, with a small change: I have a CompletableFuture
to get the token and only then I add it to the 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);
});
}
Upvotes: 1