问题
I have the following code in my controller in PlayFramework:
def auth = Action.async(parse.json) { request =>
{
val authRequest = request.body.validate[AuthRequest]
authRequest.fold(
errors => Future(BadRequest),
auth => {
credentialsManager.checkEmailPassword(auth.email, auth.password).map {
case Some(credential: Credentials) => {
sessionManager.createSession(credential.authAccountId).map { //Throws an error
case Some(authResponse: AuthResponse) => Ok(Json.toJson(authResponse))
case None => InternalServerError
}
}
case (None) => Unauthorized
}
})
}
}
I get the following error at the line with error comment above:
Type Mismatch:
[error] found : scala.concurrent.Future[play.api.mvc.Result]
[error] required: play.api.mvc.Result
[error] sessionManager.createSession(credential.authAccountId).map {
The createSession call there returns a Future[Option[Object]]
but I can't figure out how to fix this problem.
Any help will be greatly appreciated.
回答1:
Short answer:
Change .map
to .flatMap
in line credentialsManager.checkEmailPassword(auth.email, auth.password).map
and case (None) => Unauthorized
to case None => Future(Unauthorized)
Explanation:
credentialsManager.checkEmailPassword(auth.email, auth.password)
returns a Future[Option[Credentials]]
and mapping on that will always return a Future
and inside it sessionManager.createSession(credential.authAccountId)
also returns a Future
So, final outcome of credentialsManager.checkEmailPassword(auth.email, auth.password)
was Future[Future[something]]
to avoid such situations you can instead flatten
it and then map
it and it can be done in a single step by flatmap
回答2:
Not sure, but this should work:
def auth = Action.async(parse.json) { request =>
{
val authRequest = request.body.validate[AuthRequest]
authRequest.fold(
errors => Future(BadRequest),
auth => {
credentialsManager.checkEmailPassword(auth.email, auth.password).flatMap { //flatMap
case Some(credential: Credentials) => {
sessionManager.createSession(credential.authAccountId).map {
case Some(authResponse: AuthResponse) => Ok(Json.toJson(authResponse))
case None => InternalServerError
}
}
case None => Future(Unauthorized) //Wrap it
}
})
}
}
This is simplification of your code, with some comments. I hope this is enough to grab the idea:
Future(Option("validCredentials")).flatMap {
case Some(credential) => Future("OK")
case None => Future("Unauthorized")
}
//Future[Option[String]].flatMap(Option[String] => Future[String])
//Future[A].flatMap(A => Future[B]) //where A =:= Option[String] and B =:= String
回答3:
Future("Unauthorized") this is not valid please use Future.successful(Ok("OK")) Future.successful(BadRequest(Unauthorized))
来源:https://stackoverflow.com/questions/37784456/playframework-type-mismatch-found-scala-concurrent-futureplay-api-mvc-result