Custom Exception in scala

how can i create custom exceptions in Scala extending Exception class and throw them when exception occurs as well as catch them.

example in java :

class CustomException extends Exception {

  public final static String _FAIL_TO_INSERT = "FAIL_TO_INSERT";

}

final case class CustomException(private val message: String = "", 
                           private val cause: Throwable = None.orNull)
                      extends Exception(message, cause) 

Just try catch:

try {
    throw CustomException("optional")
} catch {
    case c: CustomException =>
          c.printStackTrace
}

class MyException(message: String) extends Exception(message) {

  def this(message: String, cause: Throwable) {
    this(message)
    initCause(cause)
  }

  def this(cause: Throwable) {
    this(Option(cause).map(_.toString).orNull, cause)
  }

  def this() {
    this(null: String)
  }
}

This is almost identical to @Jacek L.'s answer. I just wanted to add some more input on the motive behind this answer.

Why so many constructors?

Throwable is written in kind of a funny way. It has 4 constructors -- ignoring the one with the boolean toggles -- each of them behaves a bit differently with nulls, and these differences could only be maintained with multiple constructors.

It would have been a bit cleaner if Scala would have allowed to call a superclass constructor via super, but it doesn't :(

Why not a case class?

  • Perfectly maintaining the constructors' behavior regarding nulls wouldn't be possible; specifically, both def this() and def this(message: String) will have to set the cause to null, while originally it is set to this.
  • toString will not be overridden.
  • The message and the cause are already publicly available via getMessage and getCause. Adding another reference to these is redundant.
  • equals will be overridden and will behave differently.
    Meaning, new Exception("m") == new Exception("m") // false
    while new CaseException("m") == new CaseException("m") // true

If one desires to access the message and the cause via pattern-matching, one can simply implement the unapply method:

object MyException {
  def unapply(e: MyException): Option[(String,Throwable)] = Some((e.getMessage, e.getCause))
}

You might want to create a sealed trait:

sealed trait MyException {
  // This is called a "self annotation". You can use "self" or "dog" or whatever you want.
  // It requires that those who extend this trait must also extend Throwable, or a subclass of it.
  self: Throwable =>
  val message: String
  val details: JsValue
}

Then you can have as many case classes as you need extending not only Exception, but your new trait.

case class CustomException(message: String) extends Exception(message) with MyException {
  override val details: JsValue = Json.obj("message" -> message, "etc" -> "Anything else")
}

Now, the whole point of using Scala is walking towards a more functional programming style, it will make your app more concurrent, so if you need to use your new custom exception, you might want to try something like this:

  def myExampleMethod(s: Option[String]): Future[Boolean] = Try {
    s match {
      case Some(text) =>
        text.length compareTo 5 match {
          case 1 => true
          case _ => false
        }
      case _ => throw CustomException("Was expecting some text")
    }
  }
  match {
    case Success(bool) => Future.successful(bool)
    case Failure(e) => Future.failed(e)
  }

In order to reflect all the original constructors from Exception I'd implement a custom exception with the following pattern:

class CustomException(msg: String) extends Exception(msg) {
  def this(msg: String, cause: Throwable) = {
    this(msg)
    initCause(cause)
  }

  def this(cause: Throwable) = {
    this(Option(cause).map(_.toString).orNull)
    initCause(cause)
  }

  def this() = {
    this(null: String)
  }
}

This can be also achieved with a trait as mentioned in previous answer. I'd just not create individual classes in this case:

trait SomeException { self: Throwable =>
  def someDetail: SomeDetail
}

then, when throwing:

throw new Exception(...) with SomeException {
  override val someDetail = ...
}

and when matching:

try {
  ...
} catch {
  case ex: Throwable with SomeException =>
    ex.getCause
    ex.getMessage
    ex.someDetail
}

The advantage here is that you are not sticking to any particular constructor of the parent exception.

something more or less like that.


You define your custom exception like this

case class CustomException(s: String)  extends Exception(s)

And you can throw your exception like this:

try{
...
} catch{
case x:Exception => throw new CustomException("whatever")
}