Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Catching Exceptions in Scala (Part 1)

DZone's Guide to

Catching Exceptions in Scala (Part 1)

While Java and Scala are both JVM languages, they have vastly different means of catching exceptions. Let's see how to separate out fatal exceptions to the JVM in Scala.

· Java Zone ·
Free Resource

How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.

Hey, folks! I hope everyone is enjoying their coding days (or nights, whichever you prefer). If you are here, then you are probably looking for a better or cleaner way to make your Scala code robust and readable altogether.

Recently, I have been going through some Scala code written by a majority of Java developers who would like to learn Scala and are fairly new to the language. I hope this blog helps them as well and that they learn something from it.

We're going to take a brief look at the ways of dealing with exceptions in our Scala applications in a pair of blogs. This blog lets you use your existing knowledge of Java in Scala programs with a bit of a twist — it's not really big on the functional way that we follow, but the next blog would be more focused on the functional aspect of Scala to achieve the same results.

So here, we'll examine some common practices that we used to follow from the conventional world of Java and then we'll see how we do the same thing in Scala — and the benefits we get from this new way.

Suppose there is a piece of code in our application that could generate an exception. We don’t want it to affect the behavior of our application adversely, so the obvious choice for us to handle it in Java is to wrap this piece of code in a try-catch block.

The Scala code depicting this way of handling exceptions in our application would be something like this:

try {
    info("Calling method that could generate the exception")
    riskyCodeInvoked("Exception Expected in certain cases")
} catch {
    case ex: Exception =>
        error("Exception occurred and successfully caught", ex)
        handlerMethod(ex) // used to handle the exceptions
}


The above code looks all right and functions well, too, doesn't it? So is there anything wrong with this code snippet? Actually, there is one problem, which is not apparent while just looking at our dry run.

The above code would also catch any critical or fatal exception, such as VirtualMachineError which includes OutOfMemoryError and other fatal errors.

These fatal errors should be passed to the JVM directly. These exceptions are handled by the JVM at a low level and are mostly recovered by restarting the JVM. Handling these errors in your code could lead to an infinite loop where the same error could occur again and again, as the JVM is not recovering from it.

This is a very common problem and must always be avoided in code. Fortunately, Scala provides a rather simple way to avoid this issue. We can do it like this:

try {
    info("Calling method that could generate the exception")
    riskyCodeInvoked("Exception Expected in certain cases")
} catch {
    case NonFatal(ex) =>
        ex match {
            case ex:ArithmeticException => error("Arithmetic exception",ex)
            case _ => error("some other exception", ex)
    }
}


Now, this modified code would only be handling all non-fatal exceptions. In case some fatal exception occurs, it will be passed directly to and caught by the JVM.

Although the above approach is good enough to use in your application, when there is a large number of lines in your code and you simply cannot write all that logic in one single method, you should try to divide your logic into many small private methods and compose them in such a way that it does not reduce the readability of your code.

Writing several methods with a try-catch block, like we used to do in traditional Java code, would simply be polluting your programs with boilerplate code. Wouldn’t it be nice if you could create a pipeline with your code and every method in the pipeline would simply be responsible for either returning a valid result or an exception? This would allow you to handle the exception only once and at the level when you first called the composed method.

We'll see how to create such a composition of methods in my next article. So stay tuned, and let’s keep coding the best that we can.

How do you break a Monolith into Microservices at Scale? This ebook shows strategies and techniques for building scalable and resilient microservices.

Topics:
scala ,exception handling ,java ,jvm ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}