Skip to content

Commit

Permalink
[DOCS-590]: Serialization content improvements (#862)
Browse files Browse the repository at this point in the history
* Serialization content improvements

* Gathering low-lighted options under a parent title in ToC.
  • Loading branch information
Serdaro authored Sep 29, 2023
1 parent 2c0ad6b commit dc62841
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 202 deletions.
156 changes: 1 addition & 155 deletions docs/modules/serialization/pages/implementing-dataserializable.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,159 +61,5 @@ NOTE: Since Hazelcast needs to create an instance during the deserialization, `D
NOTE: `DataSerializable` is a good option if serialization is only needed for in-cluster communication.

NOTE: `DataSerializable` is not supported by non-Java clients as it uses Java reflection.
If you need non-Java clients, please use <<identifieddataserializable, IdentifiedDataSerializable>>,
If you need non-Java clients, please use xref:implementing-identifieddataserializable.adoc[IdentifiedDataSerializable],
xref:implementing-portable-serialization.adoc[Portable], or xref:compact-serialization.adoc[Compact].

== IdentifiedDataSerializable

For a faster serialization of objects, avoiding reflection and long class names,
Hazelcast recommends you implement `com.hazelcast.nio.serialization.IdentifiedDataSerializable`
which is a slightly better version of `DataSerializable`.

`DataSerializable` uses reflection to create a class instance, as mentioned in
<<implementing-dataserializable, Implementing DataSerializable>>.
But `IdentifiedDataSerializable` uses a factory for this purpose and
it is faster 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.

[source,java]
----
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`.

[source,java]
----
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`.

[[register]]
=== 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.

[tabs]
====
XML::
+
--
[source,xml]
----
<hazelcast>
...
<serialization>
<data-serializable-factories>
<data-serializable-factory factory-id="1">
com.company.package.EmployeeDataSerializableFactory
</data-serializable-factory>
</data-serializable-factories>
</serialization>
...
</hazelcast>
----
--
YAML::
+
[source,yaml]
----
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:

* https://github.com/hazelcast/hazelcast-csharp-client#41-identifieddataserializable-serialization[.NET^]
* https://github.com/hazelcast/hazelcast-cpp-client#41-identifieddataserializable-serialization[C++^]
* https://github.com/hazelcast/hazelcast-nodejs-client#41-identifieddataserializable-serialization[Node.js^]
* https://github.com/hazelcast/hazelcast-python-client#41-identifieddataserializable-serialization[Python^]
* https://github.com/hazelcast/hazelcast-go-client#41-identifieddataserializable-serialization[Go^]
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
= 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 xref:implementing-dataserializable.adoc[`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.

[source,java]
----
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`.

[source,java]
----
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`.

[[register]]
== 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.

[tabs]
====
XML::
+
--
[source,xml]
----
<hazelcast>
...
<serialization>
<data-serializable-factories>
<data-serializable-factory factory-id="1">
com.company.package.EmployeeDataSerializableFactory
</data-serializable-factory>
</data-serializable-factories>
</serialization>
...
</hazelcast>
----
--
YAML::
+
[source,yaml]
----
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:

* https://github.com/hazelcast/hazelcast-csharp-client#41-identifieddataserializable-serialization[.NET^]
* https://github.com/hazelcast/hazelcast-cpp-client#41-identifieddataserializable-serialization[C++^]
* https://github.com/hazelcast/hazelcast-nodejs-client#41-identifieddataserializable-serialization[Node.js^]
* https://github.com/hazelcast/hazelcast-python-client#41-identifieddataserializable-serialization[Python^]
* https://github.com/hazelcast/hazelcast-go-client#41-identifieddataserializable-serialization[Go^]
Loading

0 comments on commit dc62841

Please sign in to comment.