Extending the ReflectionBasedAutoSerializer
You can extend the ReflectionBasedAutoSerializer
to handle serialization in a customized manner. This section provides an overview of the available method-based customization options and an example of extending the serializer to support BigDecimal and BigInteger types.
Reasons to Extend the ReflectionBasedAutoSerializer
One of the main use cases for extending the ReflectionBasedAutoSerializer
is that you want it to handle an object that would currently need to be handled by standard Java serialization. There are several issues with having to use standard Java serialization that can be addressed by extending the PDX ReflectionBasedAutoSerializer
.
- Each time we transition from a Geode serialized object to an object that will be Java I/O serialized, extra data must get serialized. This can cause a great deal of serialization overhead. This is why it is worth extending the
ReflectionBasedAutoSerializer
to handle any classes that normally would have to be Java I/O serialized. - Expanding the number of classes that can use the
ReflectionBasedAutoSerializer
is beneficial when you encounter object graphs. After we use Java I/O serialization on an object, any objects under that object in the object graph will also have to be Java I/O serialized. This includes objects that normally would have been serialized using PDX orDataSerializable
. - If standard Java I/O serialization is done on an object and you have enabled check-portability, then an exception will be thrown. Even if you are not concerned with the object’s portability, you can use this flag to find out what classes would use standard Java serialization (by getting an exception on them) and then enhancing your auto serializer to handle them.
Overriding ReflectionBasedAutoSerializer Behavior
You can customize the specific behaviors in ReflectionBasedAutoSerializer
by overriding the following methods:
-
isClassAutoSerialized
customizes which classes to autoserialize. -
isFieldIncluded
specifies which fields of a class to autoserialize. -
getFieldName
defines the specific field names that will be generated during autoserialization. -
isIdentifyField
controls which field is marked as the identity field. Identity fields are used when a PdxInstance computes its hash code to determine whether it is equal to another object. -
getFieldType
determines the field type that will be used when autoserializing the given field. -
transformFieldValue
controls whether specific field values of a PDX object can be transformed during serialization. -
writeTransform
controls what field value is written during auto serialization. -
readTransform
controls what field value is read during auto deserialization.
These methods are only called the first time the ReflectionBasedAutoSerializer
sees a new class. The results will be remembered and used the next time the same class is seen.
For details on these methods and their default behaviors, see the JavaDocs on ReflectionBasedAutoSerializer for details.
Example of Optimizing Autoserialization of BigInteger and BigDecimal Types
This section provides an example of extending the ReflectionBasedAutoSerializer
to optimize the automatic serialization of BigInteger and BigDecimal types.
The following code sample illustrates a subclass of the ReflectionBasedAutoSerializer
that optimizes BigInteger and BigDecimal autoserialization:
public static class BigAutoSerializer extends ReflectionBasedAutoSerializer {
public BigAutoSerializer(Boolean checkPortability, string… patterns) {
super(checkPortability, patterns);
}
@Override
public FieldType get FieldType(Field f, Class<?> clazz) {
if (f.getType().equals(BigInteger.class)) {
return FieldType.BYTE_ARRAY;
} else if (f.getType().equals(BigDecimal.class)) {
return FieldType.STRING;
} else {
return super.getFieldType(f, clazz);
}
}
@Override
public boolean transformFieldValue(Field f, Class<?> clazz) {
if (f.getType().equals(BigInteger.class)) {
return true;
} else if (f.getType().equals(BigDecimal.class)) {
return true;
} else {
return super.transformFieldValue(f, clazz);
}
}
@Override
public Object writeTransform(Field f, Class<?> clazz, Object originalValue) {
if (f.getType().equals(BigInteger.class)) {
byte[] result = null;
if (originalValue != null) {
BigInteger bi = (BigInteger)originalValue;
result = bi.toByteArray();
}
return result;
} else if (f.getType().equals(BigDecimal.class)) {
Object result = null;
if (originalValue != null) {
BigDecimal bd = (BigDecimal)originalValue;
result = bd.toString();
}
return result;
} else {
return super.writeTransform(f, clazz, originalValue);
}
}
@Override
public Object readTransform(Field f, Class<?> clazz, Object serializedValue) {
if (f.getType().equals(BigInteger.class)) {
BigInteger result = null;
if (serializedValue != null) {
result = new BigInteger((byte[])serializedValue);
}
return result;
} else if (f.getType().equals(BigDecimal.class)) {
BigDecimal result = null;
if (serializedValue != null) {
result = new BigDecimal((String)serializedValue);
}
return result;
} else {
return super.readTransform(f, clazz, serializedValue);
}
}
}