2015-11-08 9 views
1

Я нашел несколько вопросов, которые очень близки к моему вопросу (например, Play Framework/Scala: abstract repository and Json de/serialization), но они не решили мою проблему.Play 2/Scala - Generic Reactive Mongo CRUD - сериализация json

То, что я пытаюсь достичь, - это абстракция моего CRUD DAO для обычных операций с crud.

Я строю GenericMongoDaoActor для этого:

abstract class GenericMongoDaoActor[T <: Entity: Writes](implicit inj:Injector, implicit val f:Format[T]) extends Actor with Injectable { 
    protected val db = inject[DefaultDB] 
    protected val collectionName: String 
    protected val collection:JSONCollection 

    //set to None to use fallback 
    def defaultSelector(obj:T):Option[JsObject] = None 
    def fallbackSelector(obj:T) = Json.obj("_id" -> Json.obj("$elemMatch" -> obj._id)) 

    protected def find(jsObject: JsObject) = { 
    val currentSender = sender 
    val futureOption = collection 
     .find(jsObject) 
     .cursor[T](ReadPreference.primaryPreferred) 
     .headOption 

    futureOption.mapTo[Option[T]].flatMap { 
     case Some(pobj) => 
     currentSender ! Some(pobj) 
     Future{pobj} 
     case None => 
     currentSender ! None 
     Future{None} 
    } 
    } 

    protected def save(obj:T):Unit = { 
    update(obj, true) 
    } 

    protected def update(obj:T):Unit = { 
    update(obj, false) 
    } 

    private def update(obj:T, upsert: Boolean):Unit = { 
    val selector = defaultSelector(obj) match { 
     case None => fallbackSelector(obj) 
     case Some(sel) => sel 
    } 
    collection.update(
     selector, 
     obj, 
     GetLastError.Default, 
     upsert).onComplete { 
     case Failure(e) => Logger.error("[" + this.getClass.getName + "] Couldn`t update " + obj.getClass.getName + ": " + Json.prettyPrint(Json.toJson(obj)), e) 
     case Success(lastError) => //currentSender ! lastError todo: do something with lastError 
    } 
    } 

    def findAll() = { 
    collection.find(Json.obj()).cursor[T](ReadPreference.primaryPreferred).collect[List]() 
    } 

} 

DAOActor ручки сущностей, которые наследуют абстрактный класс "Entity":

abstract class Entity { 
    val _id: BSONObjectID 
} 

В настоящее время существует 2 классы, наследуемые Entity ..

Как вы можете видеть, мой DOAActor уже имеет контекст для поиска Writes [T] в области.

abstract class GenericMongoDaoActor[T <: Entity: Writes] 

Когда я пытаюсь построить такой проект, он жалуется, что нет никаких OWrites, заданных для сериализации «obj» типа «T» в методе обновления.

No Json serializer as JsObject found for type T. Try to implement an implicit OWrites or OFormat for this type. 

collection.update(<------------- 

Я не смог найти способ решить эту проблему. Пожалуйста, дайте мне знать, если сможете.

ответ

0

У меня были подобные проблемы, когда я перешел из более ранней версии ReactiveMongo. То, что сработало для меня, заключалось в том, чтобы конвертировать около .as[JsObject] конверсий в различные вызовы API ReactiveMongo.

Так, если до этого я:

collection.update(
    selector, 
    obj, 
    ... 
) 

я заменил его:

collection.update(
    selector, 
    obj.as[JsObject], 
    ... 
) 

Это казалось достаточно, хотя я утра подачи необходимо JSON конвертер (ы) в немного по-другому; подклассы моего абстрактного класса должны реализовать элемент implicit val fmt:Format[T]. Я сомневаюсь, что это важно, но это подход, который, кажется, работает :-)

+0

Это решило мою проблему. Большое спасибо. Я до сих пор не понимаю, почему он жалуется, что ему нужны овертиты или форматы сверху .. – muenchnair

-1

Для написания и форматирования вам необходимо использовать OWrites и OFormat. Я знаю, что OWrites расширяет Writes и OFormat расширяет формат, но версия reactivemongo, которую вы используете, ждет OWrites и OFormat, а не ее супер-типы.

+0

Невозможно использовать 'Writes' вместо' OWrites', поскольку специфика записи структуры, соответствующей ожидаемому документу BSON, должна выполняться с ' JsObject', а не 'JsValue' (результат' Writes'). – cchantep

+0

@cchantep Я сказал: «Используйте OWrites вместо Writes». Использование .as [JsObject] - это взлом, а не решение. В новейших версиях play-reactivemongo используются OWrites, OFormat и т. Д. У меня была такая же ошибка. Пожалуйста, прочитайте ошибку. – David