Getting value map is not a member of Object when doing getOrElse with Future in my Play2 app

I'm trying to do a for comprehension when calling my mongo instance with ReactiveMongo. The method should check if any result is returned, if not return Future(NotFound). But I'm getting an error that I don't understand.

[info] Compiling 8 Scala sources and 1 Java source to /Users/Projects/reco_play/parser/target/scala-2.10/classes...
[error] /Users/Projects/reco_play/parser/app/controllers/Application.scala:94: value map is not a member of Object
[error]           }.getOrElse(Future(NotFound))
[error]                      ^
[error] one error found
[error] (compile:compile) Compilation failed

Imports:

import play.api.mvc._
import play.api.Play.current
import play.api.Logger
import play.modules.reactivemongo.{ReactiveMongoPlugin, MongoController}
import models.{Company}
import reactivemongo.api.collections.default.BSONCollection
import reactivemongo.bson.{BSONObjectID, BSONDocument}
import org.joda.time.DateTime
import scala.concurrent.{Future, ExecutionContext}

Method:

def showEditForm(id: String) = Action {
    implicit request =>
      implicit val reader = Company.CompanyReader
      Async {
        val objectId = new BSONObjectID(id)
        val cursor = collection.find(BSONDocument("_id" -> objectId)).cursor[Company]

        for {
          maybeCompany <- cursor.headOption
          result <- maybeCompany.map { company =>
              Ok(views.html.editForm(Some(id), Company.form.fill(company)))
          }.getOrElse(Future(NotFound))
        } yield result
      }
  }

Answers


Okay, I looked at your example more and you are right it's a different issue than what I originally answered with. First, try changing your for-comp to this:

    for {
      maybeCompany <- cursor.headOption
    } yield {
       maybeCompany.map{company => 
        Ok(views.html.editForm(Some(id), Company.form.fill(company)))
      }.getOrElse(NotFound)
    }

The issue you are seeing had to do with mixing types in your for-comp. You started the for-comp with a Future and then you tried to switch to an Option for the next step. This is an unfortunate feature of for-comps in that whatever type you start with on the first line is the same type you have to continue with throughout the comprehension. This is because you can not flatMap from Future[T] to Option[T] which is what would happen in the for-comp you had. Another way to do it would be as follows:

    for {
      maybeCompany <- cursor.headOption
      result <- Promise.successful(maybeCompany.map { company =>
          Ok(views.html.editForm(Some(id), Company.form.fill(company)))
      }).future
    } yield result.getOrElse(NotFound)

In this approach, on the second step of the for-comp, I'm wrapping the Option result in a successfully completed Future, which is the correct type to use for continuing the comprehension.


Need Your Help

How to achieve some measure of “privilege separation” with Java web-server?

java ssl jetty privileges

I'm trying to be proactive around security on my Jetty web-server boxes -- especial with regards to storing SSL key information although I'd like a generic solution. Apache uses privilege separati...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.