Vavr library is intended to “turn Java upside down”.
It is a functional library for Java, which brings you great functional core structures and immutable data types. It is the really nice extension for standard Java 8 functional features.
In this article, I want to introduce you Try control sturcture from Vavr library, which helps us to get rid of try-catch blocks in our code.
I assume you know the basics of functional programming and already know lambda expressions from Java 8.
Checked exceptions problem
First of all – let’s focus on checked exceptions in Java. Those exceptions extend
Exception class – like for example
Checked exceptions must be caught in catch statement or rethrowed to caller method.
The fact that compiler forces us to handle checked exceptions makes a lot of developers angry. It leads us to write a lot of boilerplate code with a lot of error-prone try-catch statements.
That’s why checked exceptions do not exist in
Scala. That’s why designers of
Hibernate library replaced checked exceptions with runtime ones.
Sadly, for now, we have to deal with checked exceptions in Java. When you develop web applications, and you make HTTP calls, I’m sure that at some point you’d countered
IOException and you had to handle it.
Can we remove try-catch statements from our code?
Let’s see how Try structure from Vavr can help us with checked exceptions handling…
Introduction to Try
Try control structure is a container for an operation which may be successful or not.
It gives us the ability to write safe code without using try-catch statements.
Result in Try can be either Success or a Failure. What is worth to mention, we can treat unsafe operations and its results as immutable values.
Try value, we can use static method from Vavrs
But because Vavr library is intended to bring us a little bit of flexible Scala syntax, we can import API as static, and we have more elegant:
The result of the above line is
Try container which contains someUnsafeMethod() success result, or failure exception as an inner value.
Let’s Try it
I always learn the most by doing examples, so let’s consider a real case scenario.
Let’s say that we have microservice which process some items. Our goal is to implement a safe method, which makes call to remote storehouse to get additional storehouse data for given item.
We have an contract for fetching stock data:
And the interface client looks like this:
As we can see,
IOException is handled in a try-catch statement. It is handled in an imperative way – we have two blocks either for success case or failure case.
Try to the party:
Great, we’ve replaced try-catch blocks with
Try control structure. 🙂
The code that we’ve created still looks too imperative. We have two instructions here – first fetch ItemStockValue, and then return quantity from it.
Because Try is a container for unsafe operation result, it brings us some methods for the internal value manipulation. We have, for instance, map method for inner success value transformation.
The result of map operation is new Try container, with mapped value inside.
Applying map() transformation to our code:
Try container we’ve made
fetchQuantityFor(Item item) method as pure functional expression.
Exploring, exploring, exploring…
Getting to item example, we can, instead of throwing an unchecked exception, return default value:
We can ask container whether there is success or failure:
We can use all functional programming benefits, by combining and chaining unsafe operations executions:
Got failure after the first unsafe operation? Want to invoke another unsafe operation on failure? No problem:
In case you’ve been looking for finaly clause, do not worry:
To sum up
In this blog post, we’ve learned the concept of Vavr
With this control structure, we can deal with checked (or even unchecked) exceptions in Java more gracefully – by using functional expressions.
Try share with us a lot of methods for function chaining and composing so our exception handling can be reduced to one phase – which is less error-prone and more pleasing to the eye.