Martin GOYOT Martin GOYOT - 11 months ago 67
Java Question

Action composition and async in Play Framework 2.5 in Java

I want to create an action that I can use with the

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 {

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

if (StringUtils.isEmpty(token)) {

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

return promiseOfUpdatedContext.thenApply(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
is always empty and
is not set, this is just a quick meaningless example, my IDE is complaining on the
part. For what I understand, it is expecting a
and gets something more like a

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

Or maybe I'm trying to do something stupid and composed actions are already asynchronous?

Answer Source

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

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

    if (StringUtils.isEmpty(token)) {

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