Enjoy quickies with supplyAsync by knowing how to handle exceptions.

PROBLEM:

I have a method: public String getChuckNorrisFact();

This method may also throw an exception, in my case IOException because this method does a service call to get a fact about Chuck Norris from web.

I learned about CompletableFuture and now I am ASYNCING the shit out everywhere.

Here is what I did:


CompletableFuture<String> factFuture = CompletableFuture.supplyAsync(() -> getChuckNorrisFact());

But the compiler tells me to handle or throw the exception, so I do this:

CompletableFuture<String> factFuture2 = CompletableFuture.supplyAsync(() -> {
try {
return getChuckNorrisFact();
} catch (IOException e) {
e.printStackTrace();
}
});

Sadly there is still a compilation error in this. The supplier(lambda expression) in supplyAsync()  needs to return a string but there is no return statement if an exception occurs. So I do this:


CompletableFuture<String> factFuture = CompletableFuture.supplyAsync(() -> {
try {
return getChuckNorrisFact();
} catch (IOException e) {
return e.getMessage();
}
});

Voila! no compilation errors.

But there is still a problem with this code. Sometimes when I run this code I get dirt Exception message instead of Chuck Norris fact.

ಠ_ಠ


Solution:

Solution is simple, create a new object that encapsulates both Exceptions and result. Something like this:


public class ResultExceptionWrapper<T, E extends Exception> {
        T result;
        E exception;
}


Now return your result or exception encapsulated in this object, like this:


CompletableFuture<ResultExceptionWrapper<String, Exception>> factFuture = CompletableFuture.supplyAsync(() -> {
ChuckNorrisFact cnf = new ChuckNorrisFact();
try {
return new ResultExceptionWrapper<String, Exception>(cnf.getChuckNorrisFact(), null);
} catch (IOException e) {
Exception exception = new Exception(e);
return new ResultExceptionWrapper<String, Exception>(exception);
}
});


And to get the result do this:

ResultExceptionWrapper<String, Exception> factResponse = factFuture.get();
if(factResponse.getException()!=null){
                                // you can also create a custom exception and throw from here
System.out.println("Service call failed, no fact fetched.");
}
else{
System.out.println("Here is a Chuck Norris fact: "+factResponse.getResult());
}

This is just a simple way that gets the job done.

Peace.




Comments

Popular posts from this blog

SelfAwarePotato

Converting google/guava ListenableFuture to Java 8 CompletableFuture

A Generic method to convert ResultSetFuture (of Datastax Java driver for Cassandra) to a list of table-row-model(POJO) for any table query