【问题标题】:No implementation for OWrites and Reads was bound in Scala Play appScala Play 应用程序中没有绑定 OWrites 和 Reads 的实现
【发布时间】:2017-09-20 01:13:00
【问题描述】:

我有多个模型类,它们都共享相同的属性。出于这个原因,我创建了一个特征,例如:

trait Player extends Temp {

  val gameId: BSONObjectID

  val personalDetails: abc.PersonalDetails // <- comes from shared library

}

case class FootballPlayer(var _id: Option[BSONObjectID] = None,
                         gameId: BSONObjectID,
                         personalDetails: abc.PersonalDetails,
                         var created: Option[DateTime] = None,
                         var updated: Option[DateTime] = None
                        ) extends Player

case class VideogamePlayer(var _id: Option[BSONObjectID] = None,
                         gameId: BSONObjectID,
                         personalDetails: abc.PersonalDetails,
                         var created: Option[DateTime] = None,
                         var updated: Option[DateTime] = None
                        ) extends Player

所有这些模型都定义为伴随对象 play.api.libs.json.Readsplay.api.libs.json.OWrites

例如:

object FootballPlayer {

  import play.api.libs.functional.syntax._
  import play.api.libs.json.Reads._
  import play.api.libs.json._
  import reactivemongo.play.json.BSONFormats.BSONObjectIDFormat

  implicit val footballPlayerReads: Reads[FootballPlayer] = (
    (__ \ "_id").readNullable[BSONObjectID].map(_.getOrElse(BSONObjectID.generate)).map(Some(_)) and
      (__ \ "gameId").read[BSONObjectID] and
      (__ \ "personalDetails").read[abc.PersonalDetails] and
      (__ \ "created").readNullable[DateTime].map(_.getOrElse(new DateTime())).map(Some(_)) and
      (__ \ "updated").readNullable[DateTime].map(_.getOrElse(new DateTime())).map(Some(_))
    ) (FootballPlayer.apply _)


  implicit val sharedPersonalDetailsWrites: Writes[abc.PersonalDetails] = abc.PersonalDetails.sharedPersonalDetailsWrites

  implicit val footballPlayerWrites: OWrites[FootballPlayer] = (
    (__ \ "_id").writeNullable[BSONObjectID] and
      (__ \ "gameId").write[BSONObjectID] and
      (__ \ "personalDetails").write[abc.PersonalDetails] and
      (__ \ "created").writeNullable[DateTime] and
      (__ \ "updated").writeNullable[DateTime]
    ) (unlift(FootballPlayer.unapply))

}

现在我想将它们存储在不同的集合中,但我只想拥有一个 DAO,所以我实现了以下内容:

trait PlayerDAO[T <: Player] {

  def findById(_id: BSONObjectID)(implicit reads: Reads[T]): Future[Option[T]]

  def insert(t: T)(implicit writes: OWrites[T]): Future[T]

}

class MongoPlayerDAO[T <: Player] @Inject()(
                                           playerRepository: PlayerRepository[T]
                                         ) extends PlayerDAO[T] {

  def findById(_id: BSONObjectID)(implicit reads: Reads[T]): Future[Option[T]] = playerRepository.findById(_id)

  def insert(t: T)(implicit writes: OWrites[T]): Future[T] = playerRepository.insert(t).map(_ => t)

}

然后,我有以下存储库:

class PlayerService[T <: Player] @Inject()(playerDAO: PlayerDAO[T])(implicit reads: Reads[T], writes: OWrites[T]) {

  def findById(_id: BSONObjectID): Future[Option[T]] = playerDAO.findById(_id)


  def save(t: T): Future[T] = playerDAO.save(t)

}

我的模块如下所示:

class PlayerModule extends AbstractModule with ScalaModule {

  def configure() {
    bind[PlayerDAO[FootballPlayer]].to[MongoPlayerDAO[FootballPlayer]]
    bind[PlayerDAO[VideogamePlayer]].to[MongoPlayerDAO[VideogamePlayer]]
    // ...
    ()
  }
}

在我的 Play 控制器中,我注入以下内容:

import models.FootballPlayer._
import models.VideogamePlayer._ 

class PlayerController @Inject()(
                                 val messagesApi: MessagesApi,
                                 footballPlayerService: PlayerService[FootballPlayer],
                                 videogamePlayerService: PlayerService[VideogamePlayer]
                               ) extends Controller with I18nSupport

但是,不幸的是,我得到了以下异常:

1) 没有实现 play.api.libs.json.OWrites 已绑定。 2) 没有 play.api.libs.json.OWrites 的实现 被束缚。 3)没有实现 play.api.libs.json.Reads 已绑定。 4) 没有 play.api.libs.json.Reads 的实现 被绑定了。

我该如何解决这个问题?

【问题讨论】:

  • 1. OWritesReads 的定义没有说明。 2. 在case class 中使用var 可能不是一个好主意。
  • OWrites & Reads 在对应的伴随对象中定义,并在PlayerController中导入。
  • 你能发布你是如何在伴随对象中定义 OWrites 和 Reads 的吗?
  • @SumeetSharma 请查看我更新的问题。
  • @JohnDoe 你能分享你的 playerrepository 定义吗?

标签: scala playframework guice


【解决方案1】:

在进行 dao 注入时,它可能无法找到隐式上下文。尝试在定义绑定的 AbstractModule 中包含隐式。

编辑

在 git 上查看我的解决方案。 Here

我试图模仿你正在尝试做的任何事情并且它工作正常。

我不太确定您当前的代码有什么问题,因为我无法访问整个代码,但我认为这与搜索 OWrites 和 Reads 隐含 Player 而不是 @ 的应用程序有关987654323@或VideoGamePlayer

【讨论】:

  • MongoPlayerDao 类怎么样..你可以尝试在那里添加隐式定义吗?
  • 感谢您的帮助!谢谢!不幸的是,我无法让它工作。我能看到的唯一区别是我使用了一个PlayerRepository 而不是VideoGameMongoRepoFootballMongoRepo。也许这就是问题所在?
  • 这就是为什么我缺少CustomModule 中的前两行并且只有`bind(classOf[PlayerDAO[FootballPlayer]]).to(classOf[MongoPlayerDAO[FootballPlayer]])` 和@ 987654329@,这会给我以下错误:repositories.app.PlayerRepository&lt;T&gt; cannot be used as a key; It is not fully specified.
  • 通过使用 PlayerRepository[VideoGamePlayer] 的命名依赖和 PlayerRepository[FootballPlayer] 的默认注入,您可以使其工作。检查我已经做到了,它有效。我认为这就是你想要做的。您还可以查看用于注入泛型类型的 TypeLiteral。我不能让它工作,但这是你可以研究的。
【解决方案2】:

看起来您正在尝试注入(反)序列化程序,而您可以将它们作为类的隐式参数提供:

class PlayerService[T <: Player](implicit reads: Reads[T], writes: OWrites[T]) @Inject()(playerDAO: PlayerDAO[T])

甚至更简单(写,但含义完全相同):

class PlayerService[T <: Player: Reads: OWrites] @Inject()(playerDAO: PlayerDAO[T])

由于Reads[T]OWrites[T] 没有作为模块实现,Guice 无法正确注入它们。但是,它们仍然可以是您的类的常规参数。

【讨论】:

  • 您建议的方法均无效。使用第一个时,我得到以下编译错误:';' expected but '@' found.,使用第二个时,我得到与以前相同的结果:No implementation for play.api.libs.json.OWrites was bound
猜你喜欢
  • 1970-01-01
  • 2021-08-12
  • 2015-09-03
  • 2020-09-20
  • 1970-01-01
  • 2014-02-21
  • 1970-01-01
  • 2017-05-06
  • 2016-11-03
相关资源
最近更新 更多