2014-09-10 82 views
0

我需要定義一個提供上下文信息的Exception ...並且此信息存儲在Map中。爲了避免錯鍵的名字,我已經定義了以下EnumerationScala:異常模式匹配

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 [email protected](1, contextValues) => 
    Logger.debug(s"error invoking myService: ${contextValues(Value1).get}") 
    case NonFatal(e) => 
    Logger.error(s"unhandled error: ${e.getMessage}") 
} 

問題是,即使拋出的異常像一樣,第一個case語句也不會執行,執行總是落在最後的case聲明中。我錯過了什麼嗎?

+0

不相關(我希望),但隱式調用toString是一個不必要的重載。也許把它稱爲'在反引號中串'。 – 2014-09-11 00:57:18

回答

0

也許你可以使用Try,這對Scala來說應該會更自然。

Try { 
    callService("myService") 
} match { 
    case Success(s) => // something you do when you succeed 
    case Failure(ex) => ex match { 
    case [email protected](1, contextValues) => 
     Logger.debug(s"error invoking myService: ${contextValues(Value1).get}") 
    case NonFatal(ex) => 
     Logger.error(s"unhandled error: ${ex.getMessage}") 
    } 
} 
+0

通常爲'case failure(MyException(1,vs))'。 – 2014-09-11 00:58:52

0

小安慰,但FWIW,IWFM。

object Test extends App { 
    import util._ 
    val res = Try (throw MyException("help", 1, Map(Value1 -> Option("bad")))) recover { 
     case [email protected](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 [email protected](1, vals) => vals 
    } 
    Console println Await.result(f, Inf) 
}