I used a static method supplyAsync() to get a CompletableFuture, and call its whenComplete() method to deal with the result and exception.
whenComplete() accepts a BiConsumer as parameter, and BiConsumer's second parameter is a Throwable. But I found that I can't throw a checked exception in supply() method. If I did, Idea will show a tip “Unhandled exception: java.lang.exception”.
public static void main(String[] args) {
Integer i = 0;
// unhandled exception
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> CompletableTest.getInt(i), executorService);
future.whenComplete((res, e) ->
{
System.out.println("res is " + res);
System.out.println("e is " + e);
});
}
public static Integer getInt(Integer i) throws Exception {
Thread.sleep(3000);
return i + 1;
}
I'm confused, whenComplete() can deal with checked exception, but I can't throw it.
Is it possible to throw a checked exception within CompletableFuture?
Related
I implemented my own Runnable.run(), it tells me to catch InterruptedException. Then I added it,
private final CountDownLatch start = new CountDownLatch(1);
private final int eCount = ...;
public void run(){
for(int e = 0;e<eCount;++e){
new Thread(new Runnable()
{
#Override
public void run() throws InterruptedException{
start.await(); //
}
}).start();
}
But compile error is now:
Exception InterruptedException is not compatible with throws clause in Runnable.run()Java(67109266)
What does it mean by "not compatible with throws clause". How to fix this issue?
The interface Runnable exposes this method:
public abstract void run();
This method throws nothing (only unchecked exceptions).
The message you get means you can't throw checked exceptions (such as InterruptedException) inside this method cause otherwise, it doesn't match the run() signature.
Generally speaking, if you #Override a method of an interface / abstract class, it is necessary that you respect the signature that is imposed by it and this includes the throws list (you can not throw an exception that is declared if you wish, but you can't throw an exception that is not declared).
About how to fix, you can wrap your checked exception inside an unchecked exception:
#Override
public void run() {
try {
start.await();
} catch (InterruptedException e) { //<-- catch the checked exception
throw new RuntimeException("Interrupted", e); //<-- wrap it into an unchecked exception (you can also create your own, which I suggest, instead of using the generic RuntimeException)
}
}
I have an async function which does a particular task, sample code below,
#Async
public CompletableFuture<Boolean> foo(String value) throws Exception {
// do task
LOGGER.info("Processing completed");
return CompletableFuture.completedFuture(true);
}
Whenever any runtime exception occurs the caller function is not informed and the application runs without any errors/exceptions. This is dangerous because we will be under the false assumption that the processing is successful.
How to avoid this and make the method report error whenever any exception occurs?
To overcome this you need to add an exception try/catch block and set the exception in the completable future instance
#Async
public CompletableFuture<Boolean> foo(String value) {
CompletableFuture completableFuture = new CompletableFuture();
try{
// do task
LOGGER.info("Processing completed");
completableFuture.complete(true);
} catch(Exception e) {
completableFuture.completeExceptionally(e);
}
return completableFuture;
}
On the caller side,
CompletableFuture<Boolean> foo = service.foo(value);
foo.whenComplete((res, ex) -> {
if (ex == null) {
// success flow ...
} else {
// handle exception ...
ex.printStackTrace();
LOGGER.error("ERROR ----> " + ex.getMessage());
}
});
You can handle exceptions on the caller side using exceptionally method from CompletableFuture
CompletableFuture<Boolean> foo = service.foo(value)
.exceptionally(ex-> /* some action */ false);
I am somewhat new to Java 8 and am trying to throw a an exception within an lambda expression as following: if subQty is less than min or greater than max, in this case, my unit test calculated min/max to be 182 and 255, and I am submitting a subQty of 10, therefore it should raise an exception and fail this unit test. However, I am keep getting the green light why is that?
public void verifyingIndividualSubmissionValueLimits(String alias, double min, double max)
// ... some code here ...
// Get local stock price
CompletableFuture<Double> localPriceFuture = instrumentRequester.getMidPrice(instId);
// Calculate the min and max quantity
localPriceFuture.thenAcceptBoth(dollarFxRateFuture,
(localPrice, fxRate) -> {
double minLocalValue = min * fxRate;
double maxLocalValue = max * fxRate;
long minQuantity = Math.round(minLocalValue / localPrice);
long maxQuantity = Math.round(maxLocalValue / localPrice);
if (subQty < minQuantity || subQty > maxQuantity) {
log.debug("We should throw an exception because subQty is {}", subQty);
throw new SubmissionValidationException(String.format("Quantity: %s, is not within %s and %s", subQty, minQuantity, maxQuantity));
}
}
);
}
You throws exception in different thread. You are creating a thread that calculate min, max rate and throws an exception but exception occurs in thread so you can not see any exception in main thread (in this case verifyingIndividualSubmissionValueLimits). You can read callback and async threads here https://www.callicoder.com/java-8-completablefuture-tutorial/
You can only throw exception from inside the lambda only if the #FunctionInterface it represent is throwing exception, Otherwise you will have to handle it inside the lambda only, for example this can be achieved creating your own FunctionalInterface -
public class Test {
public void foo(Fun f) throws Exception {
f.apply();
}
#FunctionalInterface
private interface Fun{
void apply() throws Exception;
}
public static void main(String[] args) throws Exception {
Test test = new Test();
test.foo(() -> {
throw new Exception();
});
}
}
In your case you are using CompletableFuture thenAcceptBoth function which use BiConsumer function interface which does not throw any exception, so it's not possible to throw it from there.
#FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
....
}
These are compile time restrictions and valid even if it's not in a separate thread.
I have the below code
import java.util.function.BiConsumer;
public class ExceptionHandlingLambda {
public static void main(String[] args) {
int [] someNumbers = { 1, 2, 3, 4 };
int key = 2;
process(someNumbers, key, (v,k) -> {
try{
System.out.println(v/k);
}
catch(ArithmeticException e){
//handle exception
}
});
}
private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : someNumbers) {
//can put a try catch here but this is generic and we don't know what exception we are catching.
consumer.accept(i, key);
}
}
}
I am trying to handle some exception in a lambda. From above I have handled an exception within a lambda.
I think it makes my lambda look kind of messy.
I could also handle the exception in the process method but it would be generic and we wouldn't know what exception we are handling for.
Any other better way to handle this in lambda to have cleaner code? Any suggestions would be much appreciated.
After the suggestion from some great and kind minds I have an answer. Hope this helps someone.
process(someNumbers, key, wrapperLambda((v, k) -> System.out.println(v / k)));
//with method reference
process(someNumbers, key, ExceptionHandlingLambda::wrapperLambda);
A wrapper function for lambda which accepts a lambda and return a lambda with a try catch which makes it much cleaner.
private static BiConsumer<Integer, Integer> wrapperLambda(BiConsumer<Integer, Integer> consumer) {
//creating a new lambda and return.
// return (v,k) -> System.out.println(v+k); this would replace the lambda with addition lambda (v+k)
return (v, k) -> {
try {
consumer.accept(v, k); //execute whatever is passed in.
}
catch (ArithmeticException e) {
System.out.println("Exception caught in wrapper lambda");
}
};
}
Apply try catch in your process method and pass an additional argument to the method i.e. the exception class for which you want to handle the exception.
Process method would look like
private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer, Class<E> clazz) {
for (int i : someNumbers) {
try{
consumer.accept(i, key);
} catch(Exception ex) {
try {
E exCast = clazz.cast(ex);
System.err.println(
"Exception occured : " + exCast.getMessage());
} catch (ClassCastException ccEx) {
throw ex;
}
}
}
}
This way your lambda would not look messy and you can decide which exception to be handled at the time of calling.
I have been using catch and now I have to use throw.
This is what I 've been given and I can't figure out what's missing so that it will work.
public static void main(String args[]){
Exception_Tester et = new Exception_Tester();
int x1;
int x2;
x1=5;
x2=0;
et.printResults(x1,x2);
}
static void printResults(int a, int b) throws ArithmeticException {
System.out.println("Add: "+(a+b));
System.out.println("Sub: "+(a-b));
System.out.println("Mul: "+(a*b));
System.out.println("Div: "+(a/b));
}
try surrounding the (a/b) in a try statement.
then, in the catch, just throw the exception.
Your printResults method declares that it maight throw an exception of a type ArithmeticException. In order for that to happen something needs to go wrong inside the method, for instance if your b param would be zero an exception would be thrown. If you want to throw exception explicitly you need to use throw statement like this in your method
throw new ArithmeticException();
Before you catch an exception. Your code must throw an exception first. Sometimes there are runtime exceptions, which code itself throws. But sometimes you need a custom Exception to be thrown when some condition gets true. For that you use this throw keyword and throw an exception for your code to Catch it.
Here is a sample
public Object pop() {
Object obj;
if (size == 0) {
throw new EmptyStackException();
}
obj = objectAt(size - 1);
setObjectAt(size - 1, null);
size--;
return obj;
}
It would throw the Exception customly and then you can catch it.
Although if the stack is zero. It might not throw that exception. So you yourself make the code throw that exception for yourself and then handle it somewhere. For that you'll use try { } catch { }.
For more on that: http://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html
Create a custome exception class and throw the exception from wherever you think it can occur.
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
For instance in the division operation in your method. You can use it like..
static void printResults(int a, int b){
if(b == 0 ) {
throw new MyException("Division by Zero");
} else {
System.out.println("Div: "+(a/b));
}
}