How to find CompletableFuture completed execeptionally - java

I am using CompletableFuture and have a question on exception handling.
I have a code like this, if any of validate() or process() method throws an exception then it is handled by the ExceptionHandler. However when I am using the CompletableFuture like this then the exception thrown is wrapped in CompletionException. May I know how can I make sure that my ExceptionHandler is called there instead of getting CompletionException?
CompletableFuture<Response> response = CompletableFuture
.supplyAsync(() -> {
validationService.validate(request);
return myService.process(request, headers);
});

Before calling get() on CompletableFuture call this method isCompletedExceptionally, will return true if it completes with exception
public boolean isCompletedExceptionally()
Returns true if this CompletableFuture completed exceptionally, in any way. Possible causes include cancellation, explicit invocation of completeExceptionally, and abrupt termination of a CompletionStage action.
You can also add exceptional block for the completableFuture, so while executing task if any exception occurs it will execute the exceptionally with exception an input argument
CompletableFuture<String> future = CompletableFuture.supplyAsync(()-> "Success")
.exceptionally(ex->"failed");
In the above example if any exception occurs executing supplyAsync failed will return or else Success is returned

Got it, by calling the following code, it will solve my problem
try {
response.join();
}
catch(CompletionException ex) {
try {
throw ex.getCause();
}
catch(Throwable impossible) {
throw impossible;
}
}

Related

Exception is not being logged/throwed inside of completable future

I just realised that exception inside of whenComplete, in completable future is not being logged/throwed. Can someone explain that? How to properly use whenComplete?
public static void main(String[] args) {
var c = CompletableFuture.runAsync(() -> {
System.out.println("done");
});
c.whenComplete((unused, throwable) -> {
System.out.println((5/0));
throw new RuntimeException("I am throwing an exception");
});
System.out.println("ok");
}
output of this block of code
done
ok
From the docs (emphasis mine)
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
Description copied from interface: CompletionStage
Returns a new CompletionStage with the same result or exception as this stage, that executes the given action when this stage completes.
When this stage is complete, the given action is invoked with the result (or null if none) and the exception (or null if none) of this stage as arguments. The returned stage is completed when the action returns. If the supplied action itself encounters an exception, then the returned stage exceptionally completes with this exception unless this stage also completed exceptionally.
whenComplete returns a new CompletableFuture. CompletableFuture keeps track of what exception (if any) has occurred and expects you to deal with it. By ignoring the return value, you're suppressing the exception.
To wait on the result of the future, or throw if it throws, use join.
c.whenComplete((unused, throwable) -> {
System.out.println((5/0));
throw new RuntimeException("I am throwing an exception");
}).join();

Handling exception using exceptionally on a CompletableFuture

I am handling exceptions occurred during the messageProcessingService.processMessage(messageObject) method call using exceptionally method.
Still, the eclipse is asking me to handle the exception at the method call
messageProcessingService.processMessage(messageObject);
The processMessage method throws CheckedException.
Why does this happen? How can I handle it using exceptionally alone
CompletableFuture.supplyAsync(() ->{
return messageProcessingService.processMessage(messageObject);
}).thenAccept(response ->{
if (response.getStatus().equals("OK")) {
log.debug("Sent Message");
deleteMessage(messageObject);
} else {
log.debug("Cannot send Message");
}
}).exceptionally(ex ->{
throw new MessageNotSendException(ex);
});

How does in ThreadPoolExecutor implemented that submit method swallow exception, but execute -not

As is known ThreadPoolExecutor have 2 methods to push tasks:
submit and execute.
As I understand - main difference the following:
Submit returns Future and if we can observe exeption occured in task after call
future.get();
But if exception occures in task pushed as submit - we will see this exception in console(surely if this exception will not explicitly catch)
I tried to investigate ThreadPoolExecutor code and find how this was implemented.
The thing I noticed, submit method uses execute method inside:
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
But I cannot find place in code where detects should we swallow exception - or not.
Please help to find this logic in code.
Your taskis a a FutureTask.
If you look at the source code (grepcode) of the run method :
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
You see that all Throwable are swallowed here.

How is exception handling done in a Callable

I understand that callable's call can throw the exception to the parent method calling it which is not the case with runnable.
I wonder how because it's a thread method and is the bottommost method of the thread stack.
The point of Callable is to have your exception thrown to your calling thread, for example when you get the result of a Future to which you submitted your callable.
public class CallableClass implements Callable<String> {
...
}
ExecutorService executor = new ScheduledThreadPoolExecutor(5);
Future<Integer> future = executor.submit(callable);
try {
System.out.println(future.get());
} catch (Exception e) {
// do something
}
Callable.call() can't be the bottommost stack frame. It's always called by another method that will then catch the exception. Callable should usually be used to asynchronously compute values and later get them with a Future object. The operation might throw an exception that is later rethrown when you try to get the Future's value.
Runnable is simply supposed to run an operation that doesn't return anything. All exception handling should be done within the Runnable because it's unclear how any exceptions thrown in Runnable.run() should be handled. (The exception from a Callable is usually returned to the caller with the Future)

java concurrent Future task returning null in case of any exception and not propagating it

I am new to java.util.concurrent package and wrote a simple method which fetches some rows from DB. I made sure that my DB call throws back an exception to handle it. But i am not seeing the exception propagating back to me. Instead call to my method is returning null.
Can some one help me in this case? Here is my sample method call
private FutureTask<List<ConditionFact>> getConditionFacts(final Member member) throws Exception {
FutureTask<List<ConditionFact>> task = new FutureTask<List<ConditionFact>>(new Callable<List<ConditionFact>>() {
public List<ConditionFact> call() throws Exception {
return saeFactDao.findConditionFactsByMember(member);
}
});
taskExecutor.execute(task);
return task;
}
I googled and found some pages around it. But don't see any concrete solutions for it. Experts please help....
The taskExecutor is object of org.springframework.core.task.TaskExecutor
The FutureTask will execute in a new thread and, if an exception occurs, will store it in an instance field. It's only when you'll ask the result of the execution that you will get the exception, wrapped inside an ExecutionException:
FutureTask<List<ConditionFact>> task = getConditionFacts(member);
// wait for the task to complete and get the result:
try {
List<ConditionFact> conditionFacts = task.get();
}
catch (ExecutionException e) {
// an exception occurred.
Throwable cause = e.getCause(); // cause is the original exception thrown by the DAO
}

Categories

Resources