简体   繁体   English

Scala-玩! 2-通用Crud

[英]Scala - Play! 2 - Generic Crud

I'm trying to create a generic crud controller, but I'm falling into a json problem. 我正在尝试创建一个通用的crud控制器,但是我陷入了json问题。

I have an implicit read and write for each of my domain objects and since my crud controller is "generic", I'm passing T for it, which causes no implicit converter found for type T. 我对每个域对象都有隐式读写,并且由于我的crud控制器是“泛型”的,所以我为此传递了T,这导致找不到类型T的隐式转换器。

Here is my TestController 这是我的TestController

object AddressController extends Controller with CrudController[Address, AddressServiceModule] {

} }

and this is my CrudController 这是我的CrudController

trait CrudController[T, K <: GenericServiceModule[T]] extends Controller {

  var service: K = _

  def get(uuid: String) = Action.async {
    val future = service.genericService.getById(UUID.fromString(uuid))
    future.map {
      case Some(t) => Ok(Json.toJson(t))
      case None => NotFound
    }.recover {
      case t =>
        Logger.error("Something went wrong", t)
        InternalServerError(t.getMessage)
    }
  }
}

then I got 然后我得到了

No Json serializer found for type T.

As I said, I have a read and write for my Address model 就像我说的,我对我的地址模型有读写作用

implicit val addressReads = Json.reads[Address]
implicit val addressWrites = Json.writes[Address]

But since converters are verified at compile time, I have no idea how to solve this scenario. 但是由于转换器是在编译时验证的,所以我不知道如何解决这种情况。 No chance to write 10, 20 crud controllers with the same logic. 没有机会用相同的逻辑编写10、20个Crud控制器。

Any idea? 任何想法?

UPDATE 更新

Just for test, I changed the Ok(Json.toJson(t)) for Ok(t.toString) then I got another problem... 只是为了测试,我将Ok(Json.toJson(t))更改为Ok(t.toString),然后又遇到了另一个问题...

a NullPointer on my service 我的服务上的NullPointer

var service: K = _

My GenericServiceModule is the following: 我的GenericServiceModule是以下内容:

trait GenericServiceModule[T] {

  def genericService: GenericCommonService[T]

  /**
   * Common Services
   * @tparam T
   */
  trait GenericCommonService[T] {
    def getById(uuid: UUID): Future[Option[T]]
    def deleteById(uuid: UUID): Future[ResultSet]
    def insert(t: T): (UUID, Future[ResultSet])
    def update(uuid: UUID, t: T): (UUID, Future[ResultSet])
  }

}

and the AddressServiceModule which I'm passing to the AddressController is the following: 我传递给AddressController的AddressServiceModule如下:

trait AddressServiceModule extends GenericServiceModule[Address] with CassandraService {

  object genericService extends GenericCommonService[Address] {

    override def getById(uuid: UUID): Future[Option[Address]] = {
      Address.select.where(_.id eqs uuid).one()
    }
}

is there a way to inject anyhow this Service through my CrudController? 有没有办法通过我的CrudController注入此服务?

What about using some sort of trait for each companion object to require the Reads and Writes ? 怎么样使用某种特质的每一个同伴对象需要ReadsWrites

trait CrudObject[T] {
    val reads: Reads[T]
    val writes: Writes[T]
}

For example: 例如:

object Address extends CrudObject[Address] {
    implicit val reads: Reads[Address] = Json.reads[Address]
    implicit val writes: Writes[Address] = Json.writes[Address]

    // other code ..
}

Then in your generic controller, require references to the companion object (marked by the CrudObject trait) and the GenericServiceModule . 然后,在您的通用控制器中,需要引用伴随对象(由CrudObject特征标记)和GenericServiceModule This won't quite make the implicit resolution work, but once you have that reference, you can then rely on inheritance to make the Reads and Writes available within the controller. 这不会完全使隐式解析起作用,但是一旦有了该引用,就可以依靠继承来使控制器中的ReadsWrites可用。

trait CrudController[T] extends Controller {

  def service: GenericServiceModule[T]

  def companion: CrudObject[T]

  implicit def reads: Reads[T] = companion.reads

  implicit def writes: Reads[T] = companion.writes

  def get(uuid: String) = Action.async {
    val future = service.genericService.getById(UUID.fromString(uuid))
    future.map {
      case Some(t) => Ok(Json.toJson(t))
      case None => NotFound
    }.recover {
      case t =>
        Logger.error("Something went wrong", t)
        InternalServerError(t.getMessage)
    }
  }
}

Then your implementation could look like: 然后,您的实现可能如下所示:

object AddressController extends CrudController[Address] {

   def service = AddressServiceModule

   def companion = Address

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM