gremlin-scala icon indicating copy to clipboard operation
gremlin-scala copied to clipboard

Problem marshalling case class with OrientDb

Open flaprimo opened this issue 8 years ago • 3 comments

I'm excusing myself in advance as I'm not sure if this problem belongs to gremlin-scala or another library.

Context

I'm using OrientDb as a database for an akka http application that works as a REST service. The model is implemented as follows (service methods use the toCC[Account] as a return):

@label("account")
case class Account(@id id: Option[String], username: String, password: String)

And it is then marshalled as a response by a controller method as Json with spray json.

Problem

When trying to marshalling the response it gives me this error: java.lang.ClassCastException: com.orientechnologies.orient.core.id.ORecordId cannot be cast to java.lang.String

Solution (but not exactly the one I like)

Changing the model to use ORecordId as id type:

@label("account")
case class Account(@id id: Option[ORecordId], username: String, password: String)

and by adding a custom type to spray json to correctly marshall/unmarshall ORecordId:

trait AccountProtocols extends DefaultJsonProtocol {
  implicit object ORecordIdFormat extends JsonFormat[ORecordId] {
    def write(obj: ORecordId) = JsString(obj.toString)
    def read(json: JsValue) : ORecordId = json match {
      case JsString(langString) => new ORecordId(langString)
      case _ => throw new DeserializationException("ORecordId expected")
    }
  }
}

it works perfectly, but in this way every other part of the application has to deal with OrientDb specific code.

The question

Shouldn't toCC[Account] map the orientdb entity to the case class including the id as an Option[String]? Is there a way to threat ids always as String?

flaprimo avatar May 09 '16 18:05 flaprimo

The Orient driver (https://github.com/mpollmeier/orientdb-gremlin) defines the ID type as an ORecordId, and since the serialisation macro doesn't support type conversions there's not really a nice way around it. Another workaround would be to define your own Marshallable instance that converts the ORecordId to/from String.

In theory we could add such a conversion to the serialisation macro, but I'm planning to replace it with a shapeless based solution...

mpollmeier avatar May 09 '16 19:05 mpollmeier

You mean by doing something like this (https://github.com/mpollmeier/gremlin-scala/blob/master/gremlin-scala/src/test/scala/gremlin/scala/MarshallableSpec.scala)? Is it possible to generalize a marshallable for every case class or every case class should have it's own implementation?

How will it work as a "shapeless solution"?

Thanks for the quick reply and your awesome work!

flaprimo avatar May 09 '16 21:05 flaprimo

Yup, in https://github.com/mpollmeier/gremlin-scala/blob/master/gremlin-scala/src/test/scala/gremlin/scala/MarshallableSpec.scala#L112

You'll need a separate marshaller instance for each case class, but you can reuse the parts...

I started some work on the shapeless powered serialisation in this branch: https://github.com/mpollmeier/gremlin-scala/tree/picopickle

mpollmeier avatar May 10 '16 12:05 mpollmeier