orientechnologies / orientdb-gremlin

TinkerPop3 Graph Structure Implementation for OrientDB
Apache License 2.0
91 stars 32 forks source link

Serialization fails when property is a scala Map #67

Closed yusefnapora closed 8 years ago

yusefnapora commented 8 years ago

I wasn't sure whether to open this here or on gremlin-scala, but I think this is specific to orient serialization.

If I have a case class Foo with a Map[String, String] field:

case class Foo(m: Map[String, String])

and try to add it to a remote OrientGraph:

val graph: OrientGraph = GraphHelper.getPersistentGraph()  // connect to remote orientdb
graph + Foo(Map("hello" -> "world"))

Orient will spit out a huge stack trace... the relevant bit seems to be

Caused by: com.orientechnologies.orient.core.exception.ODatabaseException: Error on deserialization of Serializable
  at com.orientechnologies.orient.core.serialization.serializer.record.binary.OSerializableWrapper.fromStream(OSerializableWrapper.java:47)
  at com.orientechnologies.orient.core.serialization.serializer.record.binary.ORecordSerializerBinaryV0.readSingleValue(ORecordSerializerBinaryV0.java:384)
  ... 13 more
Caused by: java.lang.ClassNotFoundException: scala.collection.immutable.Map$Map1

This looks like the orient client lib is serializing the scala Map to a byte stream, but the remote orient server chokes because it doesn't know about scala...

I can also get it to die client-side if I make a vertex class for Foo and set the field to be an EMBEDDEDMAP, although then it fails because the scala map doesn't implement java.util.Map

I've been working around this with a custom gremlin-scala marshaller, where I pull the m field out of the valueMap and convert to/from a java.util.HashMap

Is this just a fundamental limitation of orient's serializer, or is there a correct way to do this? The only other workaround I can come up with is just using a java.util.Map as the field type in my case classes, and providing accessors to convert to/from scala collections.

Thanks, and sorry in advance if this is a problem with orient / scala instead of this driver (which is excellent, btw)

mpollmeier commented 8 years ago

You are right, this is related to both gremlin-scala and the orient driver. You see this error because orient doesn't (and shoulnd't) know anything about a scala Map. And you wouldn't get there in the first place if the serialisation macro in gremlin-scala would convert the scala Map to a java Map. For now you'll have to choose one of the workarounds you describe. I'm currently working on replacing the macro based serialiser with a shapeless based one (see https://github.com/netvl/picopickle/pull/17), and will address this problem there.

yusefnapora commented 8 years ago

right on; I'll close this then :)

I wish I knew enough about shapeless to help out with the new serializer.