Отдельная обработка исключений CompletableFuture

Я понимаю, что хотел бы, чтобы пользователям нашего API не приходилось обрабатывать исключения. Или, может быть, более ясно, я хотел бы убедиться, что исключение всегда регистрируется, но только потребитель будет знать, как справиться с успехом. Я хочу, чтобы клиент также мог обрабатывать исключение, если он этого хочет. Нет действительного File, который я мог бы вернуть им.

Примечание: FileDownload – это Supplier<File>.

@Override
public CompletableFuture<File> processDownload( final FileDownload fileDownload ) {
    Objects.requireNonNull( fileDownload );
    fileDownload.setDirectory( getTmpDirectoryPath() );
    CompletableFuture<File> future = CompletableFuture.supplyAsync( fileDownload, executorService );
    future... throwable -> {
        if ( throwable != null ) {
            logError( throwable );
        }
        ...
        return null; // client won't receive file.
    } );
    return future;

}

Я действительно не понимаю, что такое CompletionStage. Мне использовать exception или handle? Я возвращаю исходное будущее или будущее, которое они возвращают?


person xenoterracide    schedule 04.05.2016    source источник
comment
Что вы хотите, чтобы результат вашего будущего был, если будет выбрано исключение? Должен ли потребитель по-прежнему получать исключение, или вы хотите, чтобы он не знал о том, что произошло?   -  person Jeffrey    schedule 04.05.2016
comment
@Джеффри, я ожидаю, что они получат исключение, справятся с ним и сами, если захотят. Я не ожидаю, что они получат файл   -  person xenoterracide    schedule 04.05.2016


Ответы (1)


Предполагая, что вы не хотите влиять на результат вашего CompletableFuture, вы захотите использовать CompletableFuture::whenComplete:

future = future.whenComplete((t, ex) -> {
  if (ex != null) {
    logException(ex);
  }
});

Теперь, когда потребитель вашего API попытается вызвать future.get(), он получит исключение, но ему необязательно что-либо делать с ним.


Однако, если вы хотите, чтобы ваш потребитель не знал об исключении (возвращать null при сбое fileDownload), вы можете использовать либо CompletableFuture::handle или CompletableFuture::exceptionally:

future = future.handle((t, ex) -> {
  if (ex != null) {
    logException(ex);
    return null;
  } else {
    return t;
  }
});

or

future = future.exceptionally(ex -> {
  logException(ex);
  return null;
});
person Jeffrey    schedule 04.05.2016
comment
Это намного проще. Потребитель, не осведомленный об исключениях, может быть просто связан с помощью future.thenAccept. Ключевым моментом здесь является то, что потребитель никогда не вызывается в исключительном случае, поэтому ему не нужно обрабатывать ни исключение, ни значение null. Суть в том, что не используйте get() - person Holger; 04.05.2016