by Rajasekar Elango

Better Exception Handling in Java 8 Streams Using Vavr

In this post, I will provide tips for better exception handling in Java 8 streams using the Functional Java library Vavr.

The problem

To illustrate with an example, let’s say we want to print the day of the week for a given stream of date strings in the format MM/dd/YYYY.

Initial solution

Let’s start with an initial solution, as seen below, and iteratively improve on it.

This will output

Huh, if a date string is invalid, this fails at the first DateTimeParseException without continuing with valid dates.

Java 8 Optional to the rescue

We can refactor parseDate to return Optional<LocalDate> to make it discard invalids and continue processing valid dates.

This will skip errors and converts all the valid dates.

WEDNESDAY Text '01-01-2015' could not be parsed at index 2 THURSDAY Text 'not a date' could not be parsed at index 0 FRIDAY

This is a great improvement, but the exception has to be handled within the parseDate method and can’t be passed back to the main method to deal with it. We can’t make the parseDate method throw a checked exception as the Streams API doesn’t play well with methods that throw exceptions.

A better solution with Vavr’s Try Monad

Vavr is a functional library for Java 8+. We will use the Try object from Vavr, which can be either an instance of Success or Failure. Basically Try is a monadic container type which represents a computation that may either result in an exception, or return a successfully computed value. Here is the modified code using Try:

The output is

WEDNESDAY Failed due to Text '01-01-2015' could not be parsed at index 2 THURSDAYFailed due to Text 'not a date' could not be parsed at index 0 FRIDAY

Now the exception is passed back to main to deal with it. Try also has APIs to implement recovery logic or return a default value in case of error.

To demonstrate this, let’s say we also want to support MM-dd-YYYY as an alternate string format for dates. The below example shows how we can easily implement recovery logic.

The output shows that now the date 01-01-2015 is also successfully converted.

WEDNESDAY THURSDAY THURSDAY Failed due to Text 'not a date' could not be parsed at index 0 FRIDAY

So Try Monad can be used to elegantly deal with exceptions and fail fast on errors.

Update on 12/03/2018:

The code examples are updated to use Doculet.

Originally published at http://erajasekar.com/posts/better-exception-handling-java8-streams-using-javaslang/.