Playframework: Type mismatch found scala.concurrent.Future[play.api.mvc.Result] required: play.api.mvc.Result

强颜欢笑 提交于 2020-01-04 04:03:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!