IdentifiedDataSerializable

For a faster serialization of objects, avoiding reflection and long class names, Hazelcast recommends you to implement com.hazelcast.nio.serialization.IdentifiedDataSerializable.

IdentifiedDataSerializable uses a factory to create a class instance (with reflection) and it is fast during deserialization, which requires new instance creations.

getClassId and getFactoryId Methods

IdentifiedDataSerializable extends DataSerializable and introduces the following methods:

  • int getClassId();

  • int getFactoryId();

IdentifiedDataSerializable uses getClassId() instead of class name and it uses getFactoryId() to load the class when given the id. To complete the implementation, you should also implement com.hazelcast.nio.serialization.DataSerializableFactory and register it into SerializationConfig, which can be accessed from Config.getSerializationConfig(). Factory’s responsibility is to return an instance of the right IdentifiedDataSerializable object, given the id. This is currently the most efficient way of Serialization that Hazelcast supports off the shelf.

Implementing IdentifiedDataSerializable

Let’s take a look at the following example code and configuration to see IdentifiedDataSerializable in action.

public class Employee
    implements IdentifiedDataSerializable {

    private String surname;

    public Employee() {}

    public Employee( String surname ) {
        this.surname = surname;
    }

    @Override
    public void readData( ObjectDataInput in )
      throws IOException {
        this.surname = in.readString();
    }

    @Override
    public void writeData( ObjectDataOutput out )
      throws IOException {
        out.writeString( surname );
    }

    @Override
    public int getFactoryId() {
        return EmployeeDataSerializableFactory.FACTORY_ID;
    }

    @Override
    public int getClassId() {
        return EmployeeDataSerializableFactory.EMPLOYEE_TYPE;
    }

    @Override
    public String toString() {
        return String.format( "Employee(surname=%s)", surname );
    }
}

The methods getClassId and getFactoryId return a unique positive number within the EmployeeDataSerializableFactory. Now, let’s create an instance of this EmployeeDataSerializableFactory.

public class EmployeeDataSerializableFactory
    implements DataSerializableFactory{

    public static final int FACTORY_ID = 1;

    public static final int EMPLOYEE_TYPE = 1;

    @Override
    public IdentifiedDataSerializable create(int typeId) {
        if ( typeId == EMPLOYEE_TYPE ) {
            return new Employee();
        } else {
            return null;
        }
    }
}

The only method you should implement is create, as seen in the above example. It is recommended that you use a switch-case statement instead of multiple if-else blocks if you have a lot of subclasses. Hazelcast throws an exception if null is returned for typeId.

Registering EmployeeDataSerializableFactory

As the last step, you need to register EmployeeDataSerializableFactory declaratively (declare in the configuration file hazelcast.xml/yaml) as shown below. Note that factory-id has the same value of FACTORY_ID in the above code. This is crucial to enable Hazelcast to find the correct factory.

  • XML

  • YAML

<hazelcast>
    ...
    <serialization>
        <data-serializable-factories>
            <data-serializable-factory factory-id="1">
                com.company.package.EmployeeDataSerializableFactory
            </data-serializable-factory>
        </data-serializable-factories>
    </serialization>
    ...
</hazelcast>
hazelcast:
  serialization:
    data-serializable-factories:
      - factory-id: 1
        class-name: com.company.package.EmployeeDataSerializableFactory

Hazelcast Clients

When using a client/server deployment, you also need to register the implemented factory on the client side. For a Java client, the process is the same as described above to be performed in the client configuration, e.g., hazelcast-client.xml/yaml. For the other Hazelcast clients, see the following for details: