For a domain object that you cannot or do not want to modify, use the PdxSerializer
class to serialize and deserialize the object’s fields. You use one PdxSerializer
implementation for the entire cache, programming it for all of the domain objects that you handle in this way.
With PdxSerializer
, you leave your domain object as-is and handle the serialization and deserialization in the separate serializer. You register the serializer in your cache PDX configuration. Program the serializer to handle all of the domain objects you need.
If you write your own PdxSerializer
and you also use the ReflectionBasedAutoSerializer
, then the PdxSerializer
needs to own the ReflectionBasedAutoSerializer
and delegate to it. A Cache can only have a single PdxSerializer
instance.
Note: The PdxSerializer
toData
and fromData
methods differ from those for PdxSerializable
. They have different parameters and results.
Procedure
In the domain classes that you wish to PDX serialize, make sure each class has a zero-arg constructor. For example:
public PortfolioPdx(){}
If you have not already implemented PdxSerializer
for some other domain object, perform these steps:
Create a new class as your cache-wide serializer and make it implement PdxSerializer
. If you want to declare your new class in the cache.xml
file, have it also implement Declarable
.
Example:
import org.apache.geode.cache.Declarable;
import org.apache.geode.pdx.PdxReader;
import org.apache.geode.pdx.PdxSerializer;
import org.apache.geode.pdx.PdxWriter;
public class ExamplePdxSerializer implements PdxSerializer, Declarable {
...
In your cache PDX configuration, register the serializer class in the cache’s <pdx>
<pdx-serializer>
<class-name>
attribute.
Example:
// Configuration setting PDX serializer for the cache
<cache>
<pdx>
<pdx-serializer>
<class-name>com.company.ExamplePdxSerializer</class-name>
</pdx-serializer>
</pdx>
...
</cache>
Or use the CacheFactory.setPdxSerializer
API.
Cache c = new CacheFactory
.setPdxSerializer(new ExamplePdxSerializer())
.create();
Note: You cannot specify a custom pdx-serializer
class using gfsh, however the configure pdx
command automatically configures the org.apache.geode.pdx.ReflectionBasedAutoSerializer class. See configure pdx.
Program PdxSerializer.toData
to recognize, cast, and handle your domain object:
PdxWriter
write methods.PdxWriter
markIdentityField
method for each field you want to have Tanzu GemFire use to identify your object. Put this after the field’s write method. Tanzu GemFire uses this information to compare objects for operations like distinct queries. If you do not set as least one identity field, then the equals
and hashCode
methods will use all PDX fields to compare objects and consequently, will not perform as well. It is important that the fields used by your equals
and hashCode
implementations are the same fields that you mark as identity fields.checkPortability
parameter when using thePdxWriter
writeObject
, writeObjectArray
, and writeField
methods.Example toData
code:
public boolean toData(Object o, PdxWriter writer)
{
if(!(o instanceof PortfolioPdx)) {
return false;
}
PortfolioPdx instance = (PortfolioPdx) o;
writer.writeInt("id", instance.id)
//identity field
.markIdentityField("id")
.writeDate("creationDate", instance.creationDate)
.writeString("pkid", instance.pkid)
.writeObject("positions", instance.positions)
.writeString("type", instance.type)
.writeString("status", instance.status)
.writeStringArray("names", instance.names)
.writeByteArray("newVal", instance.newVal)
return true;
}
Program PdxSerializer.fromData
to create an instance of your class, read your data fields from the serialized form into the object’s fields using the PdxReader
read methods, and return the created object.
Provide the same names that you did in toData
and call the read operations in the same order as you called the write operations in your toData
implementation.
Tanzu GemFire provides the domain class type and PdxReader
to the fromData
method.
Example fromData
code:
public Object fromData(Class<?> clazz, PdxReader reader)
{
if(!clazz.equals(PortfolioPdx.class)) {
return null;
}
PortfolioPdx instance = new PortfolioPdx();
instance.id = reader.readInt("id");
instance.creationDate = reader.readDate("creationDate");
instance.pkid = reader.readString("pkid");
instance.positions = (Map<String, PositionPdx>)reader.readObject("positions");
instance.type = reader.readString("type");
instance.status = reader.readString("status");
instance.names = reader.readStringArray("names");
instance.newVal = reader.readByteArray("newVal");
return instance;
}
If desired, you can also enable extra validation in your use of PdxWriter
. You can set this by setting the system property gemfire.validatePdxWriters
to true. Note that you should only set this option if you are debugging new code as this option can decrease system performance.