2013-10-10 3 views
0

방금 ​​응용 프로그램을 Play 2.2으로 이식하고 SecureSocial의 최신 버전을 사용하도록 일부 코드를 수정했습니다. 케이스 클래스 UserIdIdentityId으로 이름이 변경된 것을 보았습니다. 글쎄, 난 새로운 사용자를 등록 할 수있어 ... 그리고 데이터가 성공적으로 MongoDB에 저장됩니다 :MongoDB- 스칼라 플레이 : 쓰기/읽기 복합 Id

> db.identities.find() 
{ "_id" : ObjectId("5256a6ffe4b000f9ba0b6ce5"), "identityId" : { "userId" : "joey", "providerId" : "userpass" }, "firstName" : "Joey", "lastName" : "Smith", "fullName" : "Joey Smith", "email" : "[email protected]", "authMethod" : { "method" : "userPassword" }, "passwordInfo" : { "hasher" : "bcrypt", "password" : "$2a$10$vDr02XZ5dAHmJHDexbBnROWejhtnYFufPJtHPr8IT.rqsCSAAu5Ju" } } 

을 ...하지만 최대한 빨리 시도로 로그인 - 물론이 데이터를 읽고 의미 MongoDb에서 장난감이 더 이상 작동하지 않습니다. 데이터가 데이터베이스에서 읽히지 않기 때문에 항상 NoSuchElementException이 표시됩니다.

여기 아래에있는 내 전체 코드입니다 :

당신이 볼 수 있듯이, 내가 그렇게 아마도 내가 방법 findfindByEmailAndProvider에서 뭔가를 잘못하고 있어요 ... 복합 키를 사용하고
import com.mongodb.casbah.Imports._ 
import com.novus.salat._ 
import com.novus.salat.annotations._ 
import com.novus.salat.dao._ 
import play.api.Play.current 
import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 
import securesocial.core._ 
import se.radley.plugin.salat._ 
import se.radley.plugin.salat.Binders._ 
import mongodbContext._ 

/** 
* Defines an account identity to be used by [[securesocial.core.SecureSocial]] 
* when signing up or signing in. @see securesocial.core.Identity. 
*/ 
case class AccountIdentity(
    identityId: IdentityId, 
    firstName: String, 
    lastName: String, 
    fullName: String, 
    email: Option[String], 
    avatarUrl: Option[String], 
    authMethod: AuthenticationMethod, 
    oAuth1Info: Option[OAuth1Info] = None, 
    oAuth2Info: Option[OAuth2Info] = None, 
    passwordInfo: Option[PasswordInfo] = None 
) extends Identity 

/** 
* Provides database access and serialization for [[AccountIdentity]] data. 
*/ 
object AccountIdentity extends ((
    IdentityId, 
    String, 
    String, 
    String, 
    Option[String], 
    Option[String], 
    AuthenticationMethod, 
    Option[OAuth1Info], 
    Option[OAuth2Info], 
    Option[PasswordInfo]) => AccountIdentity) with AccountIdentityDAO with SocialUserJson { 

    /** 
    * Returns an `AccountIdentity` initialized with the specified identity. 
    * 
    * @param  identity The identity that Initializes the `AccountIdentity`. 
    */ 
    def apply(identity: Identity) : AccountIdentity = { 
    AccountIdentity(
     identity.identityId, 
     identity.firstName, 
     identity.lastName, 
     identity.fullName, 
     identity.email, 
     identity.avatarUrl, 
     identity.authMethod, 
     identity.oAuth1Info, 
     identity.oAuth2Info, 
     identity.passwordInfo 
    ) 
    } 
} 

/** 
* Provides database access for [[AccountIdentity]] data. 
*/ 
trait AccountIdentityDAO extends ModelCompanion[AccountIdentity, IdentityId] { 

    private def collection = mongoCollection("identities") 
    val dao = new SalatDAO[AccountIdentity, IdentityId](collection) {} 

    collection.ensureIndex(DBObject("email" -> 1, "_id.providerId" -> 1), "emailProvider", unique = true) 

    /** 
    * Finds the [[AccountIdentity]] identified by the specified identity id. 
    * 
    * @param  identityId The identity id. 
    * @return An `Option` value containing the `AccountIdentity`, or `None` 
    *   if there is no `AccountIdentity` identified by `identityId`. 
    */ 
    def find(identityId: IdentityId): Option[AccountIdentity] = { 
    dao.findOne(DBObject("_id.userId" -> identityId.userId, "_id.providerId" -> identityId.providerId)) 
    } 

    /** 
    * Finds the [[AccountIdentity]] identified by the specified email and provider id. 
    * 
    * @param  email The user email. 
    * @param  providerId The provider id. 
    * @return An `Option` value containing the `AccountIdentity`, or `None` if 
    *   there is no `AccountIdentity` associated with `email` and `providerId`. 
    */ 
    def findByEmailAndProvider(email: String, providerId: String): Option[AccountIdentity] = { 
    dao.findOne(DBObject("email" -> email, "_id.providerId" -> providerId)) 
    } 
} 

/** 
* Provides functionality for serializing/deserializing [[AccountIdentity]] 
* data to/from JSON. 
*/ 
trait SocialUserJson { 

    import IdentityId._ 
    import AuthenticationMethod._ 
    import OAuth1Info._ 
    import OAuth2Info._ 
    import PasswordInfo._ 

    /** 
    * An [[AccountIdentity]] serialized to JSON. 
    */ 
    implicit val identityJsonWrite = new Writes[AccountIdentity] { 
    def writes(identity: AccountIdentity): JsValue = { 
     Json.obj(
     "identityId" -> identity.identityId, 
     "firstName" -> identity.firstName, 
     "lastName" -> identity.lastName, 
     "fullName" -> identity.fullName, 
     "email" -> identity.email, 
     "avatarUrl" -> identity.avatarUrl, 
     "authMethod" -> identity.authMethod, 
     "oAuth1Info" -> identity.oAuth1Info, 
     "oAuth2Info" -> identity.oAuth2Info, 
     "passwordInfo" -> identity.passwordInfo 
    ) 
    } 
    } 

    /** 
    * An [[AccountIdentity]] deserialized from JSON. 
    */ 
    implicit val identityJsonRead = (
    (__ \ 'identityId).read[IdentityId] ~ 
    (__ \ 'firstName).read[String] ~ 
    (__ \ 'lasttName).read[String] ~ 
    (__ \ 'fullName).read[String] ~ 
    (__ \ 'email).readNullable[String] ~ 
    (__ \ 'avatarUrl).readNullable[String] ~ 
    (__ \ 'authMethod).read[AuthenticationMethod] ~ 
    (__ \ 'oAuth1Info).readNullable[OAuth1Info] ~ 
    (__ \ 'oAuth2Info).readNullable[OAuth2Info] ~ 
    (__ \ 'passwordInfo).readNullable[PasswordInfo] 
)(AccountIdentity) 
} 

.

EDIT1 : ... 물론 나는 또한 IdentityId에 대한 직렬화/역 직렬화를 구현 :

import play.api.libs.json._ 
import play.api.libs.functional.syntax._ 

/** 
* Provides functionality for serializing/deserializing [[securesocial.core.IdentityId]] 
* data to/from JSON. 
*/ 
object IdentityId { 

    /** 
    * An `IdentityId` serialized to JSON. 
    */ 
    implicit val identityIdJsonWrite = new Writes[securesocial.core.IdentityId] { 
    def writes(identityId: securesocial.core.IdentityId): JsValue = { 
     Json.obj(
     "userId" -> identityId.userId, 
     "providerId" -> identityId.providerId 
    ) 
    } 
    } 

    /** 
    * An `IdentityId` deserialized from JSON. 
    */ 
    implicit val identityIdJsonRead = (
    (__ \ 'userId).read[String] ~ 
    (__ \ 'providerId).read[String] 
)(securesocial.core.IdentityId.apply _) 
} 

답변

0

찾을 ... 난 그냥 다시 매핑 할 필요 identityId_id에 :

import com.novus.salat._ 
import com.mongodb.casbah.Imports._ 

import play.api.Play 
import play.api.Play.current 

/** 
* Defines a custom Salat context for MongoDB. 
*/ 
package object mongodbContext { 

    /** 
    * The custom context that globally overrides the Salat defaults. 
    */ 
    implicit val context = { 
    val context = new Context { 
     val name = "global" 
     override val typeHintStrategy = StringTypeHintStrategy(when = TypeHintFrequency.WhenNecessary, typeHint = "_t") 
    } 

    context.registerGlobalKeyOverride(remapThis = "identityId", toThisInstead = "_id") 
    context.registerClassLoader(Play.classloader) 
    context 
    } 
} 

... 결국 데이터베이스의 데이터는 정확합니다.

> db.identities.find() 
{ "_id" : { "userId" : "joey", "providerId" : "userpass" }, "firstName" : "Joey", "lastName" : "Smith", "fullName" : "Joey Smith", "email" : "[email protected]", "authMethod" : { "method" : "userPassword" }, "passwordInfo" : { "hasher" : "bcrypt", "password" : "$2a$10$lWxiZz3XJcj3ckOOTTgleOo3tBy2zZvO.LfX9jeUtatHENcTHQ.hS" } } 
관련 문제