在 Play2.5/scala 控制器中处理异常

Handle exception in Play2.5/scala controller

我想在以下代码中捕获异常并重定向到自定义页面。但是,例外情况不是 caught/seen.

def addItemWithParts(item: Item, parts: Seq[String]): Future[Int] = {
  ... // May throw exceptions
}

def handleAddItem = auth.SecuredAction.async { implicit request =>
  itemForm.bindFromRequest.fold(
    formWithErrors => {
      Future.successful(
        Redirect(controllers.www.routes.ItemController.startAddItem()).flashing(
          "error" -> "Bad item add input"
        )
      )
    },
    item => {
      for {
        ue <- usersService.findUserEntryByEmail(request.identity.email)
      } yield ue match {
        case Some(ue) =>
          val itemObj = Item(item.name, item.description, ue.companyId)
          val xx = itemsService.addItemWithParts(itemObj, Seq(item.parts)) <-- want to catch exception thrown by this function
          /*
           * COMMENTED CODE PRINTS EXCEPTION ON CONSOLE, BUT DONT KNOW HOW TO REDIRECT/OK...
          xx onComplete {
            case Success(x) => {
              println("Added ITEM: " + x)
              Redirect(controllers.www.routes.Dashboard.dashboard)
            }
            case Failure(exp) => {
              println("Exception while adding ITEM: " + exp)
              Ok("Got exception: " + exp)
            }
          }
          */
          Redirect(controllers.www.routes.Dashboard.dashboard) // +++
        case None =>
          Ok("Bad")
      }
    }
  )
}

我以为我可以从 onComplete success 而不是在标记为“+++”的行执行 Redirect() 但我收到此编译错误:

type mismatch;
[error]  found   : Unit
[error]  required: play.api.mvc.Result
[error]           case Some(ue) =>
[error]                         ^
[error] one error found

我查看了 play 文档,它讨论了将 onServerError 添加到 ErrorHandler(集中式),但我想知道我在这样做时遗漏了什么。

我还在学习 Scala,非常感谢任何帮助。

onCompletereturns Unit。您只能使用 onComplete.

进行副作用操作

使用 mapflatMap 来组合和构建新的计算。使用 recoverrecoverWith 处理异常,return 处理异常。

这里是你如何做到这一点

val result = 
for {
 ueOpt <- usersService.findUserEntryByEmail(request.identity.email)
 result <- ueOpt match {
            case Some(ue) =>

               val itemObj = Item(item.name, item.description, ue.companyId)
               val foo = itemsService.addItemWithParts(itemObj, Seq(item.parts))

              foo.map { value =>
                Redirect(controllers.www.routes.Dashboard.dashboard)
              }.recover { case th =>
                InternalServerError("bad things happen in life.")
              }

            case None => Future.successful(BadRequest("no item found"))
          }
} yield result

Future 提供了像 mapflatMap 这样的方法来用当前未来的结果构建新的计算。此外,future 还提供 recoverrecoverWith 来在当前 future 抛出异常时构建计算。

def bar: Future[Int] = ???

bar.map { intValue =>
  //doSomething
}.recover {
  case ex: SQLException => //return some value
  case _ => //ignore other exceptions and return default value
}