Scala:异常模式匹配

时间:2014-09-10 23:16:30

标签: scala

我需要定义一个提供上下文信息的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语句中。我错过了什么吗?

2 个答案:

答案 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)
}