Объедините CompletionStage в игровом фреймворке в Java - PullRequest
0 голосов
/ 08 июня 2018

Я пытаюсь объединить CompletionStages в игровой среде, а затем вернуть результат, как ok ().Это мои настройки:

AccountDao, который имеет два метода:

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);
}

И затем у меня есть мой контроллер с действием:

public CompletionStage<Result> editAccount() {
    Map<String, String[]> form_values = request().body().asFormUrlEncoded();
    return CompletableFuture.completedFuture(ok());
}

Так что теперь в действиисначала я хочу выполнить getUserByEmail, а затем установить некоторые значения и обновить их методом updateAccount.Как я могу объединить эти два этапа, не блокируя игровой контекст?Я пробовал разные настройки с thenCompose и комбинировать, но я не понимаю ...

Вот одна из моих попыток:

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"));
}

Проблема в том, что я не могу получить доступ к учетной записи (x), потому что я не могу установить это как функцию ... вот так:

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"));
}

Здесь я получаю сообщение об ошибке: целевой тип этого выражения должен быть функциональным интерфейсом, и plays говорит, что я должен включитьоператор return в конце функции!

Я просто не понимаю ... Спасибо за вашу помощь!

@ Marimuthu Madasamy Это точно не то, что я хочу.В вашем awnser я бы обновил аккаунт дважды.На etime в accountDao.updateAccount (account) и в accountDao.saveAccount (account);Я хочу что-то вроде этого:

return accountDao.getUserByEmail("mail").thenCompose(account -> {
       account.setName("NewName");
       accountDao.save(account);
    } .thenApplyAsync(voidInput -> {
        return ok("Account saved");
    }, httpExecutionContext.current()));

В этом случае только один раз обновите учетную запись и верните результат только по httpExecutionContext

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Хорошо, я нашел здесь своего собственного епископа при поддержке Маримуту Мадасами!Благодарю.Я пытаюсь объяснить это.Сначала вот код:

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());
    });
}

Хорошо, сначала я выполняю accountDao.getUserByEmail (), как вы можете видеть в моем awnser вверху, это возвращает CompletionStage и выполняется в контексте выполнения моей базы данных.В следующий раз с thenApply я получаю результат и выполняю следующий асинхронный метод.Я использую thenApply instand thenApplyAsync, поэтому следующий вызов также выполняется с контекстом выполнения базы данных, не устанавливая его явно.После accountDao.updateAccount () я выполняю следующий этап в httpExecutionContext, чтобы воспроизвести результат или выйти исключительно!Я действительно надеюсь, что это понятно и поможет кому-то!

0 голосов
/ 09 июня 2018

Если я правильно понимаю ваш вопрос, вы хотите получить доступ (сохранить?) К учетной записи после updateAccount(account) вызова метода.

Поскольку метод updateAccount возвращает CompletionStage<Void>, при вызове thenApplyAsync на этом этапе тип ввода будет Void, а не Account.Но с помощью следующего кода у вас все равно будет доступ к учетной записи, возвращенной с getUserByEmail, при условии, что updateAccount изменяет учетную запись с помощью вашего текста «update vars in x»:

public CompletionStage<Result> editAccount() {
    return accountDao
            .getUserByEmail(email)
            .thenCompose(account -> accountDao.updateAccount(account)
                    .thenApplyAsync(voidInput -> {
                        // here you still have access to the `account` from `getUserByEmail` method
                        accountDao.saveAccount(account);
                        return ok("Account saved");
                    }, httpExecutionContext.current());
}
...