我有一个web服务,我从scala异步调用。我想匹配并处理一些特定的故障代码,这些代码可以由recover
块中的webservice返回。
错误作为SoapFault
实例返回,该实例包含在一个额外的异常中,所以基本上我需要匹配所有异常
SoapFault
SoapFault
消息符合我的要求到目前为止,我有这个工作但很麻烦:
call map { result =>
// handle success
} recover {
case e: Exception if e.getCause != null && e.getCause.isInstanceOf[SoapFault] && e.getCause.asInstanceOf[SoapFault].getMessage == "INVALID_INPUT" => {
// handle error
}
case e: Exception if e.getCause != null && e.getCause.isInstanceOf[SoapFault] && e.getCause.asInstanceOf[SoapFault].getMessage == "SERVER_BUSY" => {
// handle error
}
}
如何以更少的重复更好地完成这项工作?
答案 0 :(得分:4)
您可以创建自己的Extractor Object。像(未经测试)的东西:
object FaultWithMessage {
def apply(message: String) = new Object() {
def unapply(t: Throwable): Boolean = t match {
case e: Exception if e.getCause != null &&
e.getCause.isInstanceOf[SoapFault] &&
e.getCause.asInstanceOf[SoapFault].getMessage == message => true
case _ => false
}
}
... recover {
case FaultWithMessage("INVALID_INPUT")() =>
//handle that one
case FaultWithMessage("SERVER_BUSY")() =>
//handle that one
...
}
答案 1 :(得分:1)
recover
块处理在Future
执行期间(即内部)抛出的错误。正如我从你的问题中所理解的那样,虽然你收到了一个有关某些错误信号的回复,但它并没有抛出任何异常,因为请求本身是成功的。这意味着您需要使用flatMap
处理您的案例,如下所示:
val response = call flatMap {
case SoapFault(error) => Future.failure(error)
// successful response
}
在这种情况下,您的回复会失败,所以现在您可以使用recover
块来处理错误,但这也不是必需的,因为您可以从{}内部的错误响应中恢复{1}}函数,因为它也会返回flatMap
。
<强>更新强>
与提议的Future
一样,您可以使用具有相同名称的提取器,即:
lmm
然后在块中解构它:
object SoapFault {
def unapply(sf: SoapFault): Option[(Option[String], String)] =
Option((Option(sg.getCause), sf.getMessage))
}
答案 2 :(得分:0)
我创建了自己的提取器对象,类似于lmm's answer,但它提取错误字符串(而不是在提取器对象中检查它),以便我可以匹配case表达式中的特定字符串。 / p>
萃取器:
object SoapFaultMessage {
def unapply(t: Throwable): Option[String] = {
if (t.getCause != null && t.getCause.isInstanceOf[SoapFault]) {
Some(t.getCause.asInstanceOf[SoapFault].getMessage)
} else {
None
}
}
}
用法:
.. recover {
case SoapFaultMessage(msg) if msg == "INVALID_INPUT" => {
//handle
}
}