需要帮助处理reactivemongo中的IllegalArgumentException

时间:2015-11-11 17:11:24

标签: scala reactivemongo

以下代码尝试使用Reactivemongo通过ID获取文档。但是,我不知道如何处理ID错误时抛出的IllegalArgumentException! 试过下面的代码,但编译器对case _ => Future.successful(None)不满意,它说:found scala.concurrent.Future[None.type] required Option[SomeModel]。还尝试case _ => None但没有成功。

def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={
    this.get( BSONDocument("_id" ->  BSONObjectID(id)) ).map {
      res => Future.successful(res)
    }.recover {
      case _ => Future.successful(None)
    }
  }

def get(query: BSONDocument)(implicit ec: ExecutionContext): Future[Option[SomeModel]]= {
    collection.find(query).one[SomeModel](ReadPreference.Primary)
  }

2 个答案:

答案 0 :(得分:1)

您感到困惑recoverrecoverWith

这两个函数都期望PartialFunction接受Throwable并且两个函数都返回Future[U],但

  • recover的{​​{1}}应返回PartialFunction
  • U应返回recoverWith

在您的情况下,您可以使用Future[U]

recover

更新:您可以修改get(BSONDocument("_id" -> BSONObjectID(id))) .recover { case _ => None } // you don't need map(res => Future.successful(res) 以返回失败的get,而不是投放Future。可能的方法是使用IllegalArgumentException及其Try

recover

更新

当我做的时候它起作用了

import scala.util.Try

def get(query: BSONDocument)(implicit ec: ExecutionContext): Future[Option[SomeModel]] = 
  Try(collection.find(query).one[SomeModel](ReadPreference.Primary))
    .recover{ case t => Future.failed(t) }.get

答案 1 :(得分:1)

我理解你的问题,

  

...我不知道如何处理ID错误时抛出的IllegalArgumentException!

我认为,更好的解决方案是

def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={

    //Try to parse bson id from string. This method return Try[BSONObjectId] and we can simple `match` them
    BSONObjectId.parse(id) match {

       // valid bson id 
      case Success(bsonId) => this.get( BSONDocument("_id" -> bsonId) )

      //We catch IllegalArgumentException and just return None
      case Failure(ex) => Future[Option[SomeModel]](None)
    }
}

在你的代码中,Scala尝试在调用get方法之前从字符串解析BSONObjectId,如果字符串id无效,则BSON在当前线程中抛出异常(不在方法{{1}的Future结果中}})。这就是get无法执行的原因。方法recover {case _ => Future.successful(None)}recover仅在recoverWith存储某些异常时执行。例如,此代码也可以使用:

Future

但是此变体很复杂(再创建一个def getById(id: String)(implicit ec: ExecutionContext): Future[Option[SomeModel]]={ //create Future, that will be store exception (if id is invalid) or valid BSON id. //method flatMap because this.get return Future type. Future(BSONObjectId(id)).flatMap{ bsonId => //this executes only if string id is valid bson. this.get( BSONDocument("_id" -> bsonId) ) }.recover{ //this will be execute only if string id is invalid bson. // the best practice to catch non-fatal Throwables via class scala.util.control.NonFatal case NonFatal(e) => None } } Future,使用flatMap控件进行恢复。我更倾向于使用NonFatal方法的第一个变体(如果没有额外的期货和控制,它会变得更容易)。