Home > Net >  CompletableFuture: whenCompleteAsync() does not let me re-throw an Exception
CompletableFuture: whenCompleteAsync() does not let me re-throw an Exception

Time:04-01

I am new to the world of CompletableFuture. I am trying to do some negative tests, in a way that will allow me to throw an exception intentionally. This exception will decide the PASS/FAIL.

Here's the code snippet:

    protected CompletableFuture<Response> executeAsync(@NonNull Supplier<Response> call) {
        return CompletableFuture
                .supplyAsync(call::get)
                .whenCompleteAsync((response, exception) -> {
                    if (exception == null) {
                        try {
                            Helper.throwIfNotExpected(clientProperties.getName(), response, null);
                        } catch (ServiceException e) {
                            throw new ServiceException(null,e.getMessage(),null);
                        }
                    } else {
                        log.error("Async API call failed.", exception);
                    }
                });
    }

This gives me an error saying unhandled exception in catch part. I looked up examples and documentation but could not find much information about Exception handling in supplyAsync/whenCompleteAsync. Thanks in advance.

CodePudding user response:

A good way to work around the shortcoming of CompletableFuture regarding checked exceptions is to delegate to another CompletableFuture instance. For your example it would look like something along the lines of

protected CompletableFuture<Response> executeAsync(Supplier<Response> call) {
    CompletableFuture<Response> delegate = new CompletableFuture<>();

    CompletableFuture
        .supplyAsync(call)
        .whenCompleteAsync((response, exception) -> {
            if (exception == null) {
                try {
                    Helper.throwIfNotExpected(clientProperties.getName(), response, null);
                    delegate.complete(response);
                } catch (ServiceException e) {
                    delegate.completeExceptionally(new ServiceException(null,e.getMessage(),null));
                }
            } else {
                log.error("Async API call failed.", exception);
                delegate.completeExceptionally(exception);
            }
        });

    return delegate;
}
  • Related