I am working on switching my application from Java serialization to Jackson. I am running up against an error in my custom durable state store plugin that I am having trouble tracking down.
Here is the relevant portion of the stack trace:
Caused by: java.lang.IllegalStateException: Can't access current ActorSystem, Serialization.currentTransportInformation was not set.
at akka.serialization.jackson.ActorSystemAccess.currentSystem(ActorSystemAccess.scala:19)
at akka.serialization.jackson.ActorSystemAccess.currentSystem$(ActorSystemAccess.scala:15)
at akka.serialization.jackson.TypedActorRefSerializer.currentSystem(TypedActorRefModule.scala:37)
at akka.serialization.jackson.TypedActorRefSerializer.serialize(TypedActorRefModule.scala:41)
at akka.serialization.jackson.TypedActorRefSerializer.serialize(TypedActorRefModule.scala:37)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:772)
... 27 common frames omitted
And this is how I’m performing the state serialization:
I am not sure how else I should be passing the system into the serializer, or why if I provide it there Jackson wouldn’t have access to it. I’ve looked at a few other durable state store implementations floating around online and their serialization code all look pretty similar to this.
The reason why it is needed eludes me right now, but you should be able to use akka.serialization.Serialization.withTransportInformation(system) { ... serialization call ... } to pass the system to the serializer and make it work.
Thanks for the suggestion. Unfortunately it looks like withTransportInformation is a private method which my code is unable to access. Changing the serialization code to this:
return akka.serialization.Serialization.withTransportInformation(() -> {
Serialization serialization = new Serialization(system);
Serializer serializer = serialization.findSerializerFor(value);
int serializerId = serializer.identifier();
String manifest = Serializers.manifestFor(serializer, value);
byte[] state = serializer.toBinary(value);
return new SerializationResult(serializerId, manifest, state);
});
Results in the following compiler error.
MariaDBDurableStateStoreJavaImpl.java:171: error: <T>withTransportInformation(Function0<T>) has private access in Serialization
return akka.serialization.Serialization.withTransportInformation(() -> {
^
where T is a type-variable:
T extends Object declared in method <T>withTransportInformation(Function0<T>)
There’s two withTransportInformations, one that takes an ActorSystem and a function (which is public) and one that’s private which just takes a function.
Note that using serialization.serialize and inspecting the returned Try will do the withTransportInformation for you (the R2DBC plugin among others takes advantage of this).
I still wasn’t able to access that method, I think it is probably some quirk of how Java and Scala interact. However, calling serialization.serialize(value).get() appears to work as expected so I will go that route. Thanks for the assistance.
Ah, yes, the public static method ends up on akka.serialization.Serialization$.
# On 2.9.0's jar, but should be the same in 2.9.3
$ javap -p Serialization.class | grep with
private <T> T withTransportInformation(scala.Function0<T>);
$ javap -p Serialization$.class | grep with
public <T> T withTransportInformation(akka.actor.ExtendedActorSystem, scala.Function0<T>);