Reputation: 9724
Given the following custom Exception
...
trait ServiceException extends RuntimeException {
val errorCode: Int
}
object ServiceException {
def apply(
message: String, _errorCode: Int
): ServiceException = new RuntimeException(message) with ServiceException {
val errorCode: Int = _errorCode
}
def apply(
message: String, cause: Throwable, _errorCode: Int
): ServiceException = new RuntimeException(message, cause) with ServiceException {
val errorCode: Int = _errorCode
}
}
... and the following method returning a Future
...
myService.doSomethingAndReturnFuture.map {
...
}.recover {
case ServiceException(5) =>
Logger.debug("Error 5")
// this does not work
// case e: ServiceException(5) =>
// Logger.debug(s"Error 5: ${e.getMessage}")
case NonFatal(e) =>
Logger.error("error doing something", e)
}
... how do I get the error message from ServiceException
?
Upvotes: 1
Views: 4552
Reputation: 39577
People like case classes.
This does not exactly align with your givens, but for example:
scala> trait ServiceException { _: RuntimeException => def errorCode: Int }
defined trait ServiceException
scala> case class MyX(errorCode: Int, msg: String, cause: Exception = null) extends RuntimeException(msg, cause) with ServiceException
defined class MyX
scala> def i: Int = throw MyX(42, "Help!")
i: Int
scala> import concurrent._ ; import ExecutionContext.Implicits._
import concurrent._
import ExecutionContext.Implicits._
scala> Future(i) recover { case MyX(code, m, err) => println(m) ; -1 }
res11: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@7d17ee50
scala> Help!
scala> .value
res12: Option[scala.util.Try[Int]] = Some(Success(-1))
Upvotes: 1
Reputation: 5768
You will need an unapply
for your described match to work, which should be defined in the companion object.
object ServiceException {
//... apply methods
def unapply(ex: ServiceException) = Some(ex.errorCode)
}
And then you can match.
recover {
case se@ServiceException(5) => println(s"Error 5: ${se.getMessage}")
case _ => println("Some other error")
}
You could also include the message in the unapply
.
def unapply(ex: ServiceException) = Some((ex.errorCode, ex.getMessage))
and then match like this:
recover {
case ServiceException(5, msg) => println(s"Error 5: $msg")
case _ => println("Some other error")
}
As an alternative you can also do it without the unapply
. Then it could look like:
recover {
case se: ServiceException if se.errorCode == 5 => println(s"Error 5: ${se.getMessage}")
case _ => println("Some other error")
}
Upvotes: 5