I realize that I'd like the consumers of our API to not have to handle an exception. Or perhaps more clearly I'd like to ensure that the exception is always logged, but only the consumer will know how to handle success. I want the client to be able to handle the exception as well if they want, There is no valid File
that I could return to them.
Note: FileDownload
is a 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;
}
I don't really understand the CompletionStage
stuff. Do I use exception
or handle
? do I return the original future or the future they return?
The CompletableFuture. join() method is similar to the get method, but it throws an unchecked exception in case the Future does not complete normally.
The CompletableFuture. get() method is blocking. It waits until the Future is completed and returns the result after its completion.
completeExceptionally() is an instance method of the CompletableFuture which is used to complete the future with the given exception. The subsequent calls to methods where we can retrieve results like get() and join() throwing the given exception.
It returns a new CompletableFuture object when all of the specified CompletableFutures are complete. If any of the specified CompletableFutures are complete with an exception, the resulting CompletableFuture does as well, with a CompletionException as the cause.
Assuming that you do not want to affect the result of your CompletableFuture
, you'll want to use CompletableFuture::whenComplete
:
future = future.whenComplete((t, ex) -> {
if (ex != null) {
logException(ex);
}
});
Now when the consumer of your API tries to call future.get()
, they will get an exception, but they don't necessarily need to do anything with it.
However, if you want to keep your consumer ignorant of the exception (return null
when the fileDownload
fails), you can use either CompletableFuture::handle
or 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;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With