show header

Object serialization

Serializable objects

10Duke SDK defines object serialization framework that is used for serializing and deserializing objects in XML and JSON formats. In the serialized formats objects can be easily passed over interfaces including system integrations and client applications (e.g. web browsers). Serialized objects can also be stored on disk. The serialization framework is extensible, and other formats could be supported in the future.

A class is serializable by the serialization framework if it meets the following conditions:

  • Class implements SerializableObject interface. SerializableObject interface is used to take special care of two properties of serializable objects: unique id's and object hierarchies with two-way navigability.

  • Class is annotated with SerializableClass annotation. SerializableClass annotation is used for controlling serializable object naming and object scanning performed by factories that support instantiating serializable objects.

If the two conditions above are met, the class is serializable, and object id's and hierarchies are persisted in serialization. However, in order to include object fields in serialization, all fields that need to be included must be annotated with SerializableField annotation. SerializableField annotation controls field naming and field value constraints. It is also used to control fields that define relations between the class and other classes. A minimal serializable class could look like this:

package com.example;

import com.tenduke.types.SerializableClass;
import com.tenduke.types.SerializableField;
import com.tenduke.types.SerializableObject;

/**
 * Minimal example serializable class.
 * @author 10Duke Software
 */
@SerializableClass
public class ExampleSerializableClass implements SerializableObject {

    /**
     * Example field to be serialized. Object type Integer is used in order to allow null value.
     */
    @SerializableField(name = "code")
    private Integer _code;
    
    /**
     * Gets value of the example serialized code field.
     */
    public Integer getCode() {
        //
        return _code;
    }

    /**
     * Sets value of the example serialized code field.
     */
    public void setCode(Integer code) {
        //
        _code = code;
    }    
}

Implementation of SerializableObject interface is not included in the example above. Typically SerializableObject interface would be implemented by simply defining id and parent fields, and implementing the methods defined by SerializableObject as accessors to these fields, as shown here:

/**
     * Unique id of the object.
     */
    private UUID _id;

    /**
     * Parent object in current hierarchy of objects, dependent on dynamic situation where objects are organized hierarchically.
     */
    private SerializableObject _parent;

    /**
     * Gets unique id of the object.
     */
    @Override
    public UUID getId() {
        //
        return _id;
    }

    /**
     * Sets unique id of the object.
     */
    @Override
    public void setId(UUID id) {
        //
        _id = id;
    }

    /**
     * Gets the parent object, i.e. object that aggregates this object in the current hierarchy where objects are organized.
     */
    @Override
    public SerializableObject getParentNode() {
        //
        return _parent;
    }

    /**
     * Sets the parent object, i.e. object that aggregates this object in the current hierarchy where objects are organized.
     */
    @Override
    public void setParentNode(SerializableObject parent) {
        //
        _parent = parent;
    }

All classes of 10Duke SDK object model are serializable, as well as many other SDK classes. If extending the object model in applications, it is recommended that the extended or specific object model classes are implemented as serializable classes as described here.

Serializers

There are currently two serializers included in 10Duke SDK:

  • XmlSerializer serializes and deserializes objects to / from an XML format

  • JsonSerializer serializes objects to JSON format, deserialization is not implemented by JsonSerializer

The ExampleSerializableClass introduced above is serialized by XmlSerializer to this kind of xml:

<ExampleSerializableClass code="1"></ExampleSerializableClass>

And JsonSerializer serializes it like this:

{"code":1}

Common base class for the serializers is AbstractSerializableObjectSerializer. Examples of serialization and deserialization calls using these serializers:

//
// Serialize object to XML using a StringBuilder
StringBuilder xmlSerialized = new StringBuilder();
new XmlSerializer().serialize(objectToSerialize, xmlSerialized);
//
// Deserialize object from XML String
ExampleSerializableClass deserializedObject =
  (ExampleSerializableClass) new XmlSerializer().deserialize(new StringReader(xmlSerialized.toString()));
//
// Serialize object to JSON using a StringBuilder
StringBuilder jsonSerialized = new StringBuilder();
new JsonSerializer().serialize(objectToSerialize, jsonSerialized);

Creating instances of serializable classes

Deserialization uses internally SerializableObjectFactory to create new instances of classes found in serialized data. SerializableObjectFactory relies on names specified for serializable classes using SerializableClass annotation. If no name or an empty String is specified for the name attribute of a SerializableClass annotation, class simple name is used. SerializableObjectFactory scans classes as configured, caches information of serializable classes found by the scan, and instantiates objects when requested by serialized name.

Configuration

SerializableObjectFactory class scanning can be configured to control where SerializableObjectFactory scans for serializable classes. This configuration is optional, and it is usually defined if SerializableObjectFactory class scanning needs to be optimized for performance.

SerializableObjectFactory is able to instantiate serializable objects only for serializable classes that it has found by class scanning. Configuration parameter used to configure SerializableObjectFactory class scanning is serialization.serializableobjectfactory.jarwhitelist, and its value is a comma-separated list of file name prefix Strings that are matched against names of .jar files found in classpath of the application. Example of this configuration parameter is given below:

<entry key="serialization.serializableobjectfactory.jarwhitelist" >mycompany,myclientscompany.jar,mybaselibrary.jar</entry>

This example configuration parameter defines that only such .jar files where name starts with mycompany, myclientscompany.jar or mybaselibrary.jar are scanned for serializable classes.

If * is included in the list or if the configuration parameter is not set, all .jar files found in application's classpath are included in scanning.

SerializableObjectFactory class scanning is initiated by LifecycleManager in the beginning of application lifecycle, i.e. when the application is started.