I try to combine CompletionStages in play framework and then return a Result like ok(). This is my setup:
AccountDao which has two methods:
public CompletionStage<Account> getUserByEmail(String email) {
return supplyAsync(() -> ebeanServer.find(Account.class).setUseCache(true).where().eq(EMAIL, email).findOne(), executionContext).thenApply(account -> {
return account;
});
}
public CompletionStage<Void> updateAccount(Account account) throws OptimisticLockException{
return runAsync(() -> {
ebeanServer.update(account);
}, executionContext);
}
And then i have my controller with the action:
public CompletionStage<Result> editAccount() {
Map<String, String[]> form_values = request().body().asFormUrlEncoded();
return CompletableFuture.completedFuture(ok());
}
So now in the action i want first to execute getUserByEmail and then i want to set some values and Update this with updateAccount method. How can i combine this two stages without blocking play context? I tried different setups with thenCompose and combine but i dont get it ...
Here one of my tries:
public CompletionStage<Result> editAccount() {
Map<String, String[]> form_values = request().body().asFormUrlEncoded();
accountDao.getUserByEmail(session().get("accountEmail")).thenCompose(x -> accountDao.updateAccount(x).thenApplyAsync(account -> {
return ok("Going to save account edits");
}, httpExecutionContext.current()));
return CompletableFuture.completedFuture(ok("Fehler am Ende"));
}
The problem here is, that i cannot access the account (x) from before because i cannot set this as function ... like this:
public CompletionStage<Result> editAccount() {
Map<String, String[]> form_values = request().body().asFormUrlEncoded();
accountDao.getUserByEmail(session().get("accountEmail")).thenCompose(x -> {
//Update vars in x and then save to database
accountDao.updateAccount(x);
}.thenApplyAsync(account -> {
return ok("Going to save account edits");
}, httpExecutionContext.current()));
return CompletableFuture.completedFuture(ok("Fehler am Ende"));
}
Here i get the error: The target type of this expression must be a functional interface and plays says that i have to include the return statement at the end of the function!
I just dont get it ... Thanks for your help!
@Marimuthu Madasamy Thats no exactly what i want. In your awnser i would update the account twice. On etime in accountDao.updateAccount(account) and in accountDao.saveAccount(account); I want something like this:
return accountDao.getUserByEmail("mail").thenCompose(account -> {
account.setName("NewName");
accountDao.save(account);
} .thenApplyAsync(voidInput -> {
return ok("Account saved");
}, httpExecutionContext.current()));
In this case in only update the account once and only return the result on the httpExecutionContext
Ok i found my own awnser here with the support of Marimuthu Madasamy! Thanks. I trie to explain it. First here is the code:
public CompletionStage<Result> editAccount() {
Map<String, String[]> form_values = request().body().asFormUrlEncoded();
return accountDao.getUserByEmail(session().get("accountEmail")).thenApply(account -> {
System.out.println("Async get Account / "+Thread.currentThread());
account.setCompany(form_values.get("company")[0]);
return accountDao.updateAccount(account);
}).thenApplyAsync(account -> {
System.out.println("Async resutl / "+Thread.currentThread());
return ok("Account saved normal");
}, httpExecutionContext.current()).exceptionally(e ->{
System.out.println("Async exception / "+Thread.currentThread());
System.out.println(e.getLocalizedMessage());
return ok(e.getLocalizedMessage());
});
}
Ok at first i execute accountDao.getUserByEmail() as you can see at top in my awnser this returns CompletionStage and is executed in my database execution context. At next with thenApply i get the result and i execute the next Async mehtod. I use thenApply instand of thenApplyAsync so the next call is also executed with the database execution context without setting it explicitly. After the accountDao.updateAccount() i execute the next stage on the httpExecutionContext to replay a result or to quit exceptionally! I really hope it is clear and helps some one!