Hazelcast 3.6.1 "There is no suitable de-serializer for type" exception

Ayub Malik picture Ayub Malik · Apr 1, 2016 · Viewed 8.8k times · Source

I am using Hazelcast 3.6.1 to read from a Map. The object class stored in the map is called Schedule.

I have configured a custom serializer on the client side like this.

ClientConfig config = new ClientConfig();
SerializationConfig sc = config.getSerializationConfig();
sc.addSerializerConfig(add(new ScheduleSerializer(), Schedule.class));
...
private SerializerConfig add(Serializer serializer, Class<? extends Serializable> clazz) {
    SerializerConfig sc = new SerializerConfig();
    sc.setImplementation(serializer).setTypeClass(clazz);
    return sc;
}

The map is created like this

private final IMap<String, Schedule> map = client.getMap("schedule");

If I get from the map using schedule id as key, the map returns the correct value e.g.

return map.get("zx81");

If I try to use an SQL predicate e.g.

return new ArrayList<>(map.values(new SqlPredicate("statusActive")));

then I get the following error

Exception in thread "main" com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for type 2. This exception is likely to be caused by differences in the serialization configuration between members or between clients and members.

The custom serializer is using Kryo to serialize (based on this blog http://blog.hazelcast.com/comparing-serialization-methods/)

public class ScheduleSerializer extends CommonSerializer<Schedule> {

    @Override
    public int getTypeId() {
        return 2;
    }

    @Override
    protected Class<Schedule> getClassToSerialize() {
        return Schedule.class;
    }

}

The CommonSerializer is defined as

public abstract class CommonSerializer<T> implements StreamSerializer<T> {

    protected abstract Class<T> getClassToSerialize();

    @Override
    public void write(ObjectDataOutput objectDataOutput, T object) {
        Output output = new Output((OutputStream) objectDataOutput);
        Kryo kryo = KryoInstances.get();
        kryo.writeObject(output, object);
        output.flush(); // do not close!
        KryoInstances.release(kryo);
    }

    @Override
    public T read(ObjectDataInput objectDataInput) {
        Input input = new Input((InputStream) objectDataInput);
        Kryo kryo = KryoInstances.get();
        T result = kryo.readObject(input, getClassToSerialize());
        input.close();
        KryoInstances.release(kryo);
        return result;
    }

    @Override
    public void destroy() {
        // empty
    }
}

Do I need to do any configuration on the server side? I thought that the client config would be enough.

I am using Hazelcast client 3.6.1 and have one node/member running.

Answer

noctarius picture noctarius · Apr 1, 2016

Queries require the nodes to know about the classes as the bytestream has to be deserialized to access the attributes and query them. This means that when you want to query on objects you have to deploy the model classes (and serializers) on the server side as well.

Whereas when you use key-based access we do not need to look into the values (neither into the keys as we compare the byte-arrays of the key) and just send the result. That way neither model classes nor serializers have to be available on the Hazelcast nodes.

I hope that makes sense.