Lagom: 1.4.15
Scala: 2.12.8
Persistence: Cassandra
Following the documentation for the schema evolution, entities in one of the two keyspaces in the scope of the application have been migrated successfully. Fetching entity from the other keyspace throws below error:
2021-01-11 13:27:59,776 [error] com.lightbend.lagom.internal.scaladsl.persistence.PersistentEntityActor [73] - Persistence failure when replaying events for persistenceId [SomeEntity|SomeEntityId]. Last known sequence number [0]
java.io.InvalidClassException: com.some.package.impl.entity.SomeEntity; local class incompatible: stream classdesc serialVersionUID = 76280542
69364365264, local class serialVersionUID = -799129383219407853
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1939)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1805)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2096)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1624)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:464)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:422)
at akka.serialization.JavaSerializer.$anonfun$fromBinary$1(Serializer.scala:336)
at scala.util.DynamicVariable.withValue(DynamicVariable.scala:62)
at akka.serialization.JavaSerializer.fromBinary(Serializer.scala:336)
at akka.serialization.Serialization.$anonfun$deserializeByteArray$1(Serialization.scala:235)
at akka.serialization.Serialization.withTransportInformation(Serialization.scala:172)
at akka.serialization.Serialization.deserializeByteArray(Serialization.scala:230)
at akka.serialization.Serialization.$anonfun$deserialize$5(Serialization.scala:220)
at scala.util.Try$.apply(Try.scala:213)
at akka.serialization.Serialization.deserialize(Serialization.scala:212)
at akka.persistence.cassandra.journal.CassandraJournal$EventDeserializer.deserializeEvent(CassandraJournal.scala:531)
at akka.persistence.cassandra.query.EventsByPersistenceIdStage$$anon$1.extractEvent(EventsByPersistenceIdStage.scala:420)
at akka.persistence.cassandra.query.EventsByPersistenceIdStage$$anon$1.tryPushOne(EventsByPersistenceIdStage.scala:364)
at akka.persistence.cassandra.query.EventsByPersistenceIdStage$$anon$1.$anonfun$newResultSetCb$1(EventsByPersistenceIdStage.scala:173)
at akka.persistence.cassandra.query.EventsByPersistenceIdStage$$anon$1.$anonfun$newResultSetCb$1$adapted(EventsByPersistenceIdStage.scala:160)
at akka.stream.impl.fusing.GraphInterpreter.runAsyncInput(GraphInterpreter.scala:452)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:476)
at akka.stream.impl.fusing.GraphInterpreterShell.processEvent(ActorGraphInterpreter.scala:574)
at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:742)
at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:757)
at akka.actor.Actor.aroundReceive(Actor.scala:539)
at akka.actor.Actor.aroundReceive$(Actor.scala:537)
at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:664)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:610)
at akka.actor.ActorCell.invoke(ActorCell.scala:579)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:268)
at akka.dispatch.Mailbox.run(Mailbox.scala:229)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Trying to figure out the reason as to why the process is not even entering the migration code, it was found that “ser_manifest” column in the messages table for the events of SomeEntity is EMPTY while in another messages table for which schema evolution ran successfully, it carries the value as fully qualified class name of the event that row contains. Hence, the deserialization process might be requiring the exact binary form of the class as it was at the time of the event. But the class of course has changed. That’s why migration is being written. So, help is sought to figure out below questions:
- How is it that the value in the “ser_manifest” column is empty in one of the messages tables in the application and carries the value as the class name of the event in another?
- Secondly, now when the old messages do not carry any value in the “ser_manifest” column, what is the correct way to evolve schema?