CompletableFuture's thenApply() wraps exception into CompletionException within handle() [duplicate] - java

This question already has answers here:
Enforcing desired CompletableFuture behavior
(1 answer)
Surprising behavior of Java 8 CompletableFuture exceptionally method
(2 answers)
Closed 15 days ago.
In the first snippet below, I would expect "ex" in the handle() method to be of type NoSuchElementException. To my surprise, the NoSuchElementException was wrapped in a CompletionException instead at runtime.
CompletableFuture.failedFuture(new NoSuchElementException())
.thenApply(s -> s) // transform the result
.handle((response, ex) -> {
if (ex instanceof NoSuchElementException) {
// translate the exception into another exception
} else {
return response;
}
});
If I remove the call to thenApply() such as below, then ex would be of type NoSuchElementException. I would like to understand what happen in thenApply that led to ex being wrapped inside CompletionException.
CompletableFuture.failedFuture(new NoSuchElementException())
.handle((response, ex) -> {
if (ex instanceof NoSuchElementException) {
// translate the exception into another exception
} else {
return response;
}
});

Related

Why stream don't throw RuntimeException? [duplicate]

This question already has answers here:
Why lambda inside map is not running?
(1 answer)
Why does Java8 Stream generate nothing?
(3 answers)
Closed last year.
Test method always throw RuntimeException. And I can catch the RuntimeException
void test() {
throw new RuntimeException();
}
System.out.println("start");
try {
test();
}
catch(RuntimeException e) {
System.out.println(e);
}
System.out.println("end");
This codes show the below result.
start
java.lang.RuntimeException
end
But, In a stream, I can't catch the RuntimeException.
System.out.println("start");
try {
nums.stream().map((num) -> {
test();
return null;
});
}
catch(RuntimeException e) {
System.out.println(e);
}
System.out.println("end");
This codes show the below result.
start
end
Why I can't catch the RuntimeException in stream.
As it says in the Javadoc of the java.util.stream package (emphasis added):
Intermediate operations return a new stream. They are always lazy; executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream that, when traversed, contains the elements of the initial stream that match the given predicate. Traversal of the pipeline source does not begin until the terminal operation of the pipeline is executed.
map is an intermediate operation, and you don't have a terminal operation. As such, the pipeline source is not traversed.
Change map to forEach (and remove the return):
nums.stream().forEach((num) -> {
test();
});
(I assume also that nums is non-empty).

Java exception explicit casting vs implicit casting [duplicate]

This question already has answers here:
Understanding checked vs unchecked exceptions in Java
(21 answers)
Closed 2 years ago.
Came across this piece of code: -
public <T> T call(final Callable<T> callable) {
try {
return callable.call();
} catch (Exception exception) {
if (exception instanceof RuntimeException) {
throw (RuntimeException) exception; // Line 6
} else {
throw new RuntimeException(exception); // Line 8
}
}
}
What is the need for doing a (RuntimeException) exception at line 6?
What is the difference between the exceptions being thrown at line 6 v/s line 8. Aren't they doing the same thing?
The code there is to transform a checked exception into a unchecked exception. In Java, checked exceptions have to be declared on a method with the throws keyword, while unchecked exceptions don't need to be declared on the method. Exception is the base class for all exceptions while RuntimeException (which is a subclass of Exception) is the base class for all unchecked exceptions.
The code on line 6 is to make the compiler happy. As Exception is a checked exception, by casting it to RuntimeException the compiler won't enforce the exception to be declared on the method with a throws. Line 8 wrapes the checked exception into a unchecked exception.

Why can't checked exceptions in a java stream be thrown at method level?

I've been learning about concurrency and the streams API and came across this. The offerLast()method can throw InterruptedException, so I get that I must handle it. What I don't get is why can't I throw it at the method level by adding throws Exception?. As it is this code does not compile.
static BlockingDeque<Integer> queue = new LinkedBlockingDeque<>();
public static void testing() throws Exception {
IntStream.iterate(1, i -> i+1).limit(5)
.parallel()
.forEach(s -> queue.offerLast(s, 10000, TimeUnit.MILLISECONDS));
}
I know it can be solved by surrounding it in a try/catch, or by creating a wrapper method that handles the error, but I'm still trying to understand why it can't be thrown at the method level.
Because lambda expressions are not always evaluated immediately.
Let's you have this:
public Supplier<String> giveMeASupplier() throws Exception {
return () -> someMethodThatThrowsCheckedException()
}
According to you, the above would work. Right?
Now in another method, I can do this:
Suppler<String> supplier = null;
try {
supplier = giveMeASupplier() // no exception is thrown here.
} catch (Exception ex) {
ex.printStackTrace();
}
if (supplier != null) {
System.out.println(supplier.get()); // this might throw an exception! Yet it's not in a try...catch!
}
Now what do you think would happen if supplier.get() throws an exception? Is there anything to catch it? No. If somehow the catch block a few lines before gets run, then it would be really weird.
The simple answer is that the "method" you're referring to is Consumer.accept, not YourClass.testing.
The lambda s -> queue.offerLast(s, 10000, TimeUnit.MILLISECONDS) is an implementation of java.util.function.Consumer.accept(T), which doesn't declare that it can throw InterruptedException.
And this behavior is not particular to streams, wherever a lambda expression is defined, it must comply with the signature of the abstract method of the functional interface it implements.

Using Java `CompletablyFuture.exceptionally` to optionally continue through exceptions

I have a series of asynchronous tasks chained together using Java CompletableFutures. The code looks something like this:
CompletableFuture<Result> doTasks(final TaskId id) {
return firstTask.workAsync(id)
.thenComposeAsync(__ -> secondTask.workAsync(id))
.thenComposeAsync(__ -> thirdTask.workAsync(id))
.thenApplyAsync(__ -> fourthTask.workAsync(id));
}
However, firstTask.workAsync throws an exception indicating that the work has already been completed, which is OK in this situation, so I would like to just ignore it and continue through the chain.
Of course, I could just wrap that bit in a separate function where I can handle the exception, but is there a way to handle it directly in the CompletableFuture chain and continue to throw all other exceptions?
A co-worker suggested I use CompletableFuture.exceptionally, but all of the examples online that I see are totally useless and just return null, which looks like it would kill the chain. How would I use that in this case?
CompletableFuture.exceptionally can be used to continue when getting an exception in a CompletableFuture. In a nutshell, you need to check the type of the exception, and if it's an exception you want to continue on, you can return a new CompletableFuture, which can be empty since the result is not used down the chain.
CompletableFuture<Result> doTasks(final TaskId id) {
return firstTask.workAsync(id)
.exceptionally(t -> {
// Will continue down the chain if matches
if (t instanceof TotallyOkException) {
return null;
}
// This will throw an ExecutionException. I convert it to a RuntimeException here
// because I don't want to add throws statements up the chain.
throw new RuntimeException(t);
})
.thenComposeAsync(__ -> secondTask.workAsync(id))
.thenComposeAsync(__ -> thirdTask.workAsync(id))
.thenApplyAsync(__ -> fourthTask.workAsync(id));
}
In this case, it will throw all non-TotallyOkException exceptions.
Returning null in your exceptionally function will not, in itself, kill the chain. The only way it will kill the chain is a result of lack of null handling in the downstream function and causing a NullPointerException.
Your exceptionally function can be set up to handle some types of exception and not others. For example:
return firstTask.workAsync(id)
.thenComposeAsync(firstResult -> secondTask.workAsync(id))
.exceptionally(t -> {
if (t instanceof TransientException) {
return getUsingBackupMethod(id);
}
throw new RuntimeException(t);
});
This exceptionally function will (effectively) catch an exception thrown from either of the first two tasks.

How to modify a getMessage for an exception? [duplicate]

This question already has answers here:
How to define custom exception class in Java, the easiest way?
(8 answers)
Closed 8 years ago.
I need to change the return message of the method getMessage() ,
for instance, i have an ArithmeticException, and when I write:
try{c=a/0;}
catch(ArithmeticException excep){System.out.println( excep.getMessage() );}
and I execut this code I have: / by zero.
So, I wanted to change this result by overwriting the getMesage method.
I have created a new class called MyException that inherits from ArithmeticExceprtion and I override the methode getMessage, and after that I have changed the type of the exception in my last code from ArithmeticException to my new name class MyException:
public class MyException extends ArithmeticException{
#override
public String getMessage(){
retun "new code message";}
}
and I have changed the first code, I have wrotten:
try{c=a/0;}
catch(MyException excep){System.out.println( excep.getMessage() );}
and when I have executed this code, I had the same error's message as if I didn't catch the exception:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at main.test.main(Test.java:33)
So, my question is: how can I change the message of the methode getMessage() ?
You have extended the ArithmeticException with a new class called MyException. But the statement c = a / 0; still throws ArithmeticException but never MyException itself, so your catch clause is not reached.
Note that normally you shouldn't catch runtime (unchecked) exceptions like ArithmeticException since it denotes a programming error. Also note that for checked exceptions, the compiler shows an error telling you that the statement would never throw that kind of exception, but in this case, MyException is an unchecked exception so the compiler is fine with it.
In your particular scenario, you cannot change the message of the exception since it will always be an ArithmeticException. But you can always print whatever message you want in the catch clause. Or you can wrap the statement in a method and let that method throw the subclass exception:
public void foo() throws MyException {
try {
c = a / 0;
} catch (ArithmeticException excep) {
// handle excep
throw new MyException();
}
}

Categories

Resources