gremlin-scala
gremlin-scala copied to clipboard
Problem marshalling case class with OrientDb
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
?
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...
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!
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