I have the following code:
public void restart() throws Exception
{
CompletableFuture<?> delayed = new CompletableFuture<>();
ScheduledExecutorService executorService =
Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(() ->
{
try
{
throw new RuntimeException("My exception.");
}
catch(Exception e)
{
delayed.completeExceptionally(e);
}
}, 1000L, 150L, TimeUnit.MILLISECONDS));
delayed.whenCompleteAsync((r, t) -> {
if (t != null)
{
throw new RuntimeException(t);
}
});
}
I'm trying to bubble up the exception which I'll catch in my executorService. But what happens instead is that the exception is thrown in the try block which is caught and CompletableFuture is completedExceptionally. Which then rethrows the exception. I was hoping that this way I'd be able to bubble up the exception.
But unfortunately, that's not what's happening. The delayed throws the exception but it doesn't bubble up. On top of that for some reason, the exception loop starts right after this. Which is try keeps throwing exception and catch keeps catching but of course completableFuture has already been completed so it doesn't come to that.
The question is how can we handle and bubble up the exception?
This worked for me:
In this modified code, we are calling the
get()method on the delayedCompletableFuture, which blocks until theCompletableFutureis completed. If theCompletableFutureis completed exceptionally,get()throws anExecutionExceptionwith the original exception as its cause. We then extract the cause and rethrow it as anException. This way, the exception is bubbled up to therestart()method and can be handled appropriately.But if we want to achieve it without using blocking get call, we can use callback
Consumer<Throwable> callbackand if exeption throws, usecallback.accept(e);like in this snippet: