Hazelcast Serialization

Hazelcast Python Client is a binary compatible implementation of Hazelcast serialization.

Content:

Warning : Python client does not support Dataserializable as it’s a Java class name dependency. Please use IdentifiedDataSerializable instead.

Builtin serializers

For Python builtin types; None, bool, int, long, float, str, arrays of them are supported by default.

Integer Type: Python has a different int type than Java. Python 2.x has integer type based on the data size which is int or long. So in Python we have a configuration for int size to map server data type.

You can configure the default integer type as:

config.serialization_config.default_integer_type = INTEGER_TYPE.INT

Please see :INTEGER_TYPE for details. Please be careful with INTEGER_TYPE.VAR as static type lang’s cannot deserialize it.

There exist an internal serializer for any custom class that is not registered a serializer such as IdentifiedDataSerializable, Portable or Custom Serializer. So the serializer service searches for a serializer for a custom class; if it fails to find one, it uses Python builtin serialization cPickle to handle it. Please note that this behaviour can be overridden by a global serializer.

IdentifiedDataSerializable

This is the Python implementation of IdentifiedDataSerializable . In order to implement IdentifiedDataSerializable you can either extend builtin class IdentifiedDataSerializable or implement your own class with same method signatures as in IdentifiedDataSerializable.

example IdentifiedDataSerializable implementation:

class Customer(IdentifiedDataSerializable):
    CLASS_ID = 1
    FACTORY_ID = 10
    def __init__(self, customer_id=None, name=None, surname=None):
        self.customer_id = customer_id
        self.name = name
        self.surname = surname

    def write_data(self, out):
        out.write_int(self.customer_id)
        out.write_boolean(self.name)
        out.write_char(self.surname)

    def read_data(self, inp):
        self.customer_id = inp.read_int()
        self.name = inp.read_utf()
        self.surname = inp.read_utf()

    def get_factory_id(self):
        return FACTORY_ID

    def get_class_id(self):
        return CLASS_ID

A factory definition is registered to configuration in order to use the above Customer class:

identifiedDataSerializable_factory = {Customer.CLASS_ID: Customer}
config.serialization_config.add_data_serializable_factory(Customer.FACTORY_ID, identifiedDataSerializable_factory)

With the above registration you can use your class:

client = HazelcastClient(config)
map = client.get_map("customer_map")
#let's assume we have variables customer_id, name, surname
map.put(customer_id, Customer(customer_id, name, surname))

Portable

This is the Python implementation of Portable . In order to implement Portable you can either extend builtin class Portable or implement your own class with same method signatures as in Portable.

example Portable implementation:

class Customer(Portable):
    CLASS_ID = 1
    FACTORY_ID = 10
    def __init__(self, customer_id=None, name=None, surname=None):
        self.customer_id = customer_id
        self.name = name
        self.surname = surname

    def write_portable(self, writer):
        writer.write_int("customer_id", self.customer_id)
        writer.write_utf("name", self.name)
        writer.write_utf("surname", self.surname)

    def read_portable(self, reader):
        self.customer_id = reader.read_int("customer_id")
        self.name = reader.read_utf("name")
        self.surname = reader.read_utf("surname")

    def get_factory_id(self):
        return FACTORY_ID

    def get_class_id(self):
        return CLASS_ID

A factory definition is registered to the configuration in order to use the above Customer class:

portable_factory = {Customer.CLASS_ID: Customer}
config.serialization_config.add_portable_factory(Customer.FACTORY_ID, portable_factory)

With the above registration you can use your class:

client = HazelcastClient(config)
map = client.get_map("customer_map")
#let's assume we have variables customer_id, name, surname
map.put(customer_id, Customer(customer_id, name, surname))

With Portable serialization you can make query on your domain object without having the classes registered on server side:

from hazelcast.serialization.predicate import sql

map = client.get_map("customer_map").blocking()
map.put(1, Customer(1, "John", "Doe"))
map.put(2, Customer(2, "Jane", "Roe"))

map.values(sql("name = 'John'"))

Portable serialization supports server side field extraction so you can query an object with many fields without deserializing them

Custom Serializers

When you need more control of the serialization or want to integrate a third party serialization framework, custom serializers is your way to go. You simply implement StreamSerializer and register it in the configuration

#CustomSerializer is already implemented elsewhere and you have a CustomClass
config.set_custom_serializer(CustomClass, CustomSerializer)

With the above registration, all of the serialization will be delegated to your CustomSerializer.

Please refer to Hazelcast Custom Serialization for details.

Global Serializers

Please refer to Hazelcast Global Serializer for details.