我需要定义一个提供上下文信息的Exception
...此信息存储在Map
中。为了避免错误的密钥名称,我已经定义了以下Enumeration
:
object ContextValueName extends Enumeration {
type ContextValueName = Value
val Value1 = Value("Value1")
val Value2 = Value("Value2")
val ValueN = Value("ValueN")
implicit def toString(name: ContextValueName) = name.toString
}
这是Exception
代码:
import ContextValueName._
trait MyException extends RuntimeException {
val errorCode: Int
val contextValues: Map[ContextValueName, Option[String]]
}
object MyException {
def apply(
message: String, _errorCode: Int, _contextValues: Map[ContextValueName, Option[String]]
): MyException = new RuntimeException(message) with MyException {
val errorCode: Int = _errorCode
val contextValues: Map[ContextValueName, Option[String]] = _contextValues.withDefault(_ => None)
}
def unapply(exception: MyException) = {
if (exception eq null) None
else Some((
exception.errorCode,
exception.contextValues
))
}
}
最后,我将处理MyException
类型的异常:
callService("myService").map { result =>
...
}.recover {
case e@MyException(1, contextValues) =>
Logger.debug(s"error invoking myService: ${contextValues(Value1).get}")
case NonFatal(e) =>
Logger.error(s"unhandled error: ${e.getMessage}")
}
问题在于,即使抛出的异常与case
类似,也永远不会执行第一个MyException(1, Map(Value1 -> "too busy"))
语句,并且执行总是落在最后的case
语句中。我错过了什么吗?
答案 0 :(得分:0)
也许你可以使用Try,这对Scala来说应该更自然。
Try {
callService("myService")
} match {
case Success(s) => // something you do when you succeed
case Failure(ex) => ex match {
case ex@MyException(1, contextValues) =>
Logger.debug(s"error invoking myService: ${contextValues(Value1).get}")
case NonFatal(ex) =>
Logger.error(s"unhandled error: ${ex.getMessage}")
}
}
答案 1 :(得分:0)
小安慰,但FWIW,IWFM。
object Test extends App {
import util._
val res = Try (throw MyException("help", 1, Map(Value1 -> Option("bad")))) recover {
case e@MyException(1, vals) => vals
}
Console println res
import concurrent._
import duration.Duration._
import ExecutionContext.Implicits._
val f = Future (throw MyException("help", 1, Map(Value1 -> Option("bad")))) recover {
case e@MyException(1, vals) => vals
}
Console println Await.result(f, Inf)
}