Hi,

During project development I came across to know about Scala’s advance exception handling techniques which I would discuss here.

There are many ways in Scala to handle exceptions. The very first which comes into mind is try catch and finally.


 def catchException = {
 try {
 1 / 0
 } catch {
 case ex: Exception => println("got an arthimatic excpetion")
 } finally {
 println("finally block executed")
 }
 }

Scala provides advance control structure to handle exceptions like Try Either.

1 – Using Try


 def handleException = {
 Try {
 10 / 2
 } match {
 case Success(result) => result
 case Failure(excepton) => excepton
 }
 }
 }

2 – Using Either

def handleException:Either[Int,Throwable] = {
try {
Left(10 / 2)
} catch {
case ex: Exception => Right(ex)
}
}

Now Most advance exception handling mechanism is encapsulated in scala.util.control.Exception class

First of all we need to import scala.util.control.Exception._   and we can execute our logic as below.

There is a method allCatch which is member of Exception class.

scala> allCatch.opt(1.toInt)
res10: Option[Int] = Some(1)

scala> allCatch.opt("a".toInt)
res11: Option[Int] = None

It would hide the exception from you and gives you None otherwise Some(Int)

if you want to get the actual exception then you should use


scala> allCatch.toTry("a".toInt)
res13: Any = Failure(java.lang.NumberFormatException: For input string: "a")

Same way Either can be used


scala> allCatch.either("a".toInt)
res14: scala.util.Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "a")

In case if we are interested to catch specific exceptions then we can also derive custom control structure from Exception class by using it’s Catching method. Below are the rules

1 – Define the sequence of your exceptions


  val exceptions = Seq(classOf[ArithmeticException],classOf[NullPointerException]) 

2 – Perform Option or Either operation.

 catching(exceptions:_*).opt {
 1/0
 } 

catching(exceptions:_*).either {
 1/0
 }

We can create control structure to specify exceptions which are expected to occur and inject computational body as below.

 scala> def catchSpecificExceptions[A](exceptions: Class[_]*)(body: => A) =
        catching(exceptions: _*).either(body).fold({t:Throwable => t match {
          case ex if (exceptions contains ex.getClass) => println("Gotta Exception [" + ex + "]") //log exception
          Left(ex)
          case ex:Exception => println("Gotta Exception [" + ex + "]") //log exception
          Left(ex)
        }}, data => Right(data))

catchSpecificExceptions: [A](exceptions: Class[_]*)(body: => A)Product with Serializable with scala.util.Either[Throwable,A]

 

We can also customized to format our messages with type of exception by creating a Map of exception and messages.

Now do your operation inside catchSpecificExceptions as below, Enjoy !!!!!


scala> catchSpecificExceptions(classOf[ArithmeticException]) {
         val list = List(1, 2, 3)
         (list map (_ + 1) sum) / 2
        }
res3: Product with Serializable with scala.util.Either[Throwable,Int] = Right(4)

 scala>  catchSpecificExceptions(classOf[ArithmeticException]) {
          val list = List(1, 2, 3)
         (list map (_ + 1) sum) / 0
       }
Gotta Exception [java.lang.ArithmeticException: / by zero]
res4: Product with Serializable with scala.util.Either[Throwable,Int] = Left(java.lang.ArithmeticException: / by zero)

Thanks !!!

Advertisements