A bit new to Scala (latest), Reactivemongo (latest) and Play framework (2.3.x).
Validating sessions, and on success, loading the user object for it returning it as json. Problem is specific to mapping and futures I guess. The following code won't compile:
def userCheck(token: String) = Action.async {
val futureSession = sessionCollection.find(Json.obj("token" -> token)).one[BSONDocument]
futureSession.map {
case Some(session) => {
userCollection.find(Json.obj("_id" -> session.getAs[String]("userId").get )).one[JsObject].map {
case Some(user) => Ok(JsObject(Seq("user" -> user)))
case None => NotFound( JsObject(Seq("message" -> JsString("not found"))) )
}
}
// NotFound( JsObject(Seq("message" -> JsString("not found"))) )
case None => NotFound( JsObject(Seq("message" -> JsString("not found"))) )
}
}
So, the error message is:
[error] AuthController.scala:186: overloaded method value async with alternatives:
[error] [A](bodyParser: play.api.mvc.BodyParser[A])(block: play.api.mvc.Request[A] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[A] <and>
[error] (block: play.api.mvc.Request[play.api.mvc.AnyContent] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] <and>
[error] (block: => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent]
[error] cannot be applied to (scala.concurrent.Future[Object])
[error] def userCheck(token: String) = Action.async {
If you look at the source code you see a commented line, if I uncomment it, the code compiles. Am I missing to cover some cases?
UPDATE 1:
So, using the tips from the accepted answer, I came up with this:
def userCheck(token: String) = Action.async {
getSession(token).flatMap {
session => {
session match {
case Some(s) => {
getUser( s.getAs[String]("userId").get ).flatMap {
user => {
user match {
case Some(u) => Future.successful( Ok( u ) )
case None => Future.successful( NotFound( JsObject(Seq( "m" -> JsString("User not found")))))
}
}
}
}
case None => Future.successful( NotFound( JsObject(Seq( "m" -> JsString("Session not found")))))
}
}
}
}
def getSession(token: String): Future[Option[BSONDocument]] = {
sessionCollection.find( Json.obj("token" -> token) ).one[BSONDocument]
}
def getUser(id: String): Future[Option[JsObject]] = {
userCollection.find( BSONDocument( "_id" -> BSONObjectID(id) ) ).one[JsObject]
}
...and it does the trick. Feels like refactoring is needed though.