java.lang.ClassCastException when deserializing Scala object

248 views Asked by At

So I have an object like this

case class QueryResult(events: List[Event])

that I need to serialize deserialize. For serialization I have this implicit class

  implicit class Serializer(obj: Object) {
    def serialize: Array[Byte] = {
      val stream = new ByteArrayOutputStream()
      val objectOutputStream = new ObjectOutputStream(stream)
      objectOutputStream.writeObject(obj)
      objectOutputStream.close
      stream.toByteArray
    }
  }

It's used like

val byteArray = QueryResult(events).serialize

Then for desrialization I have this trait that can be extended by the companion class.

trait Deserializer[A] {
  private type resultType = A
  def deserialize(bytes: Array[Byte]): A = {
    val objectInputStream = new ObjectInputStream(
      new ByteArrayInputStream(bytes)
    )
    val value = objectInputStream.readObject.asInstanceOf[resultType]
    objectInputStream.close
    value
  }
}

You would use it like so

object QueryResult extends Deserializer[QueryResult]

Then you should be able to reconstruct an instance of QueryResult from a byte array like so

val QueryResult: QueryResult = QueryResult.deserialize(byteArray)

The issue is this sometimes causes an error like the one below

java.lang.ClassCastException: cannot assign instance of scala.collection.generic.DefaultSerializationProxy to field co.app.QueryResult.events of type scala.collection.immutable.List in instance of co.app.QueryResult
  at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2205)
  at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2168)
  at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1422)
  at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2450)
  at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
  at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2166)
  at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1668)
  at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:482)
  at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:440)
  at co.app.Deserializer.deserialize(Types.scala:51)
  at co.app.Deserializer.deserialize$(Types.scala:47)
  at co.app.LocalStorage$QueryResults$.get(LocalStorage.scala:241)
  ... 36 elided

Now when I say sometimes I mean the deserialization works when I assemble the code into a jar and run it using the java cli, but it breaks when I try to execute that code via sbt test, sbt console, or ammonite. Any idea why it breaks under these circumstances and possible suggestions to fix?

0

There are 0 answers