apache / fury

A blazingly fast multi-language serialization framework powered by JIT and zero-copy.
https://fury.apache.org/
Apache License 2.0
2.98k stars 219 forks source link

[Java] Custom Serializer for fields #1806

Open miladamery opened 4 weeks ago

miladamery commented 4 weeks ago

Hi. When using Akka toolkit you need to serialize objects for persistence and clustering. Akka gives you the option for providing your own serializer. The problem is, in akka you have something called ActorRef. this class is used for replying to actors that send commands. but this ActorRef serialization/deserialization is special in Akka. Here describes how you can serizlize/deserialize ActorRef. Fury provides custom serializers for whole class according to here. Here is my implementation for serializing ActorRef (I appreciate it if some one can say if this is correct)

import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorRefResolver;
import org.apache.fury.Fury;
import org.apache.fury.memory.MemoryBuffer;
import org.apache.fury.serializer.Serializer;

public class FuryActorRefSerializer extends Serializer<ActorRef> {

    private final ActorRefResolver actorRefResolver;

    public FuryActorRefSerializer(Fury fury, ActorRefResolver actorRefResolver) {
        super(fury, ActorRef.class);
        this.actorRefResolver = actorRefResolver;
    }

    @Override
    public void write(MemoryBuffer buffer, ActorRef value) {
       // toSerializationFormat returns String
        var serialized = actorRefResolver.toSerializationFormat(value).getBytes();
        buffer.writeInt32(serialized.length);
        buffer.writeBytes(serialized);
    }

    @Override
    public ActorRef read(MemoryBuffer buffer) {
        var length = buffer.readInt32();
        var ref = buffer.readBytes(length);
        return actorRefResolver.resolveActorRef(new String(ref));
    }
}

but this ActorRef discussed earlier is usually used as a field in commands(which are Java Records) not as a standalone class. Because creating a custom serializer for each Record of my project is not logical Is there a way that Fury support this? I mean writing a serializer like above and fury understands class field it is serializing and use appropriate serializer for that field?

chaokunyang commented 4 weeks ago

Hi @miladamery , you are right. If you register a serializer for a type, the serialization for fields of this type will use this serializer too

miladamery commented 3 weeks ago

@chaokunyang Thanks for your reply, i really appreciate it. The serializer mentioned in issue didn't work so I though problem is that fury doesn't respect custom serializers for fields which was wrong. By debugging I found what the problem was. ActorRef is an interface not the implementation, on serializing/deserializing fury was checking the actual implementation type which was ActorRefAdapter and was choosing the general serializer for ActorRefAdapter not the custom one provided. So i changed FuryActorRefSerializer type from ActorRef to ActorRefAdapter and everything works now. But my question is shouldn't fury pick the custom serializer for interface and its implementations?

chaokunyang commented 3 weeks ago

Hi @miladamery , Fury should pick customized serializer for interface. It should get serializer for concrete type first. If It doesn't exist, it should pick serializer for its inferface. Would you like to contribute this feature?

miladamery commented 3 weeks ago

@chaokunyang Hi, I will try to see if i can do it