Scala Play - 与BodyParser的Action.async - 异常处理

时间:2016-01-02 10:08:56

标签: scala asynchronous playframework action body-parser

我正在使用Scala和Play进行微服务。它有一个Controller,它使用Action.async构造和自定义主体解析器。这是一个示例代码:

def crud(param: String) = Action.async(SomeCustomBodyParser) { implicit request =>
    try {
      <some code>
    } catch {
      case _ => <Exception Handling logic>
    }
}

此代码的问题是,如果SomeCustomBodyParser中出现异常,则不会在catch块中处理它。我尝试了一些方法,我在外面提取它,然后手动处理它,但异常未正确捕获。 Action.async的代码表明它需要一段代码并将其作为一个单独的上下文执行。我不清楚它究竟是如何运作的。

如何处理异常并吐出更好的异常消息。

3 个答案:

答案 0 :(得分:1)

必须为$sql = "SELECT * from locations"; $query_args = array( ); try { $stmt = $db->prepare($sql); $result = $stmt->execute($query_args); } catch (PDOException $ex) { $response["success"] = 0; $response["message"] = "Database Error2. Please Try Again!"; $response["details"] = $ex; } $result = $stmt->fetchAll(); echo json_encode($result);提供Action.async,这可以通过成功Future[Result]或失败来完成。

任何Result failed都会导致HTTP响应错误。

Future

格式化这种错误的方式可以是cistomized。

答案 1 :(得分:1)

此处的问题是您尝试使用同步错误处理程序来处理异步错误。 try catch只能处理同步错误。 Future[_]本质上是异步的,如果有try catch语句已经执行(并且可能在不同的线程中),它将抛出错误。

相反,在scala中,我们通过使用scalaz中的OptionEither\/等数据结构来明确错误处理。所有这些包装形成Monad。

在大多数异步服务器设置中,你想要的是Future里面有Either(或者来自scalaz的右偏差变体,如\/。)这样,你就可以抽象出异步性和错误处理。由于两个包装器都是monad,您可以使用 Monad Transformers 组合它们。这是一个很深刻的话题,如果您不熟悉它,需要相当多的学习,但这种数据结构的要点如下:

class Task[E, A] {
  def flatMap[U](f: A => Task[E, U]): Task[E, U] = ??? // Use monad transformer here.
}

其中E表示自定义错误的类型 - 您可能会通过sealed trait等代数数据类型来表示它们,其中包含大量case classA是您的值类型

答案 2 :(得分:0)

如果您的BodyParser抛出异常,或由于某些其他原因而失败,那么Action中的任何代码都将无法执行。 async的性质与此无关。

例如,以下代码中的System.exit永远不会运行,因为BodyParser 始终会返回异常。

package controllers

import javax.inject.Inject

import play.api.mvc._

import scala.concurrent.Future

class Application @Inject() extends Controller {

  def crud(param: String) = Action.async(
    parse.error[String](Future.failed(new RuntimeException("oh noes!")))
  ) { req =>
    System.exit(0)
    ???
  }

}

此代码生成此堆栈跟踪:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[RuntimeException: oh noes!]]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:254) ~[play_2.11-2.4.0.jar:2.4.0]
    at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:180) ~[play_2.11-2.4.0.jar:2.4.0]

堆栈跟踪表示有一个DefaultHttpErrorHandler被调用,并且从BodyParser抛出异常。

ScalaErrorHandling的文档包含自定义此内容或编写自己的文档的示例。