I'm writing a Play 2.3 application using SecureSocial(master version). I've created a LoginUser that represents a User Data in my system.
/**
* Class representing a User in the system.
* @constructor Create a new LoginUser instance from a BasicProfile object.
* @param profile represents the BasicProfile object associated with the user.
*/
case class LoginUser(val profile: BasicProfile)
Now I'm trying to implement the UserService[T] trait (of SecureSocial)but i'm having trouble.
/**
* Class tha handle all the request for read/write user data in/from the database.
*/
class InMemoryUserService extends UserService[LoginUser] {
private var tokens = Map[String, MailToken]()
/**
* Finds a user by provider id and user id.
* @param providerId - the user provider id.
* @param userId - the user user id.
* @return an optional user
*/
def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
future onComplete {
case Success(Some(x)) => return x.profile
case _ => None
}
}
The find method return a Future[Option[BasicProfile]] object, but the compiler tell me that the code is incorrect. Here the output of the compiler:
[error] /Users/alberto/git/recommendation-system/app/security/UserService.scala:68: type mismatch;
[error] found : securesocial.core.BasicProfile
[error] required: scala.concurrent.Future[Option[securesocial.core.BasicProfile]]
[error] case Success(Some(x)) => return x.profile
What's wrong?? How can i solve my problem??
You should not register a callback on your Future
via onComplete
. Instead, you want to map
the content to change the type:
def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
future map {
case Some(x) => Some(x.profile)
case None => None
}
}
This should make the compile happy :) Note that the return type of onComplete
is Unit
, while by using map
I can apply any change to the content of the Future
.
A less verbose version that map
s both the Future
and the Option
:
def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
val future: Future[Option[LoginUser]] = UserServiceLogin.find(Json.obj("providerId" -> providerId, "userId" -> userId)).one
future.map(_.map(_.profile)
}