Обрабатывать исключение в Play2.5 / контроллере scala

#scala #playframework #playframework-2.5

#scala #playframework #playframework-2.5

Вопрос:

Я хотел бы перехватить исключение и перенаправить на пользовательскую страницу в следующем коде. Однако исключения не перехватываются / не просматриваются.

 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")
      }
    }
  )
}
  

Я думал, что смогу выполнить Redirect() из onComplete success вместо строки с пометкой » «, но я получаю эту ошибку компиляции:

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

Я проверил документацию play, там говорится о добавлении onServerError в ErrorHandler (централизованный), но я хочу знать, чего мне не хватает при выполнении этого таким образом.

Я все еще изучаю Scala, любая помощь высоко ценится.

Комментарии:

1. Используйте map для правильного случая и recover для исключения.

Ответ №1:

onComplete ВОЗВРАТ Unit . Вы можете выполнять только побочные операции, используя onComplete .

Используйте map , flatMap для составления и построения новых вычислений. Используйте recover и recoverWith для обработки исключений и возврата чего-либо в исключениях.

вот как вы можете это сделать

 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 предоставляет такие методы, как map , flatMap для построения новых вычислений с результатом текущего будущего. Также future предоставляет recover и recoverWith для построения вычислений, когда текущее future выдает исключения.

 def bar: Future[Int] = ???

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