blob: 2da8ff9d8822376bd63308dfe8dca167488294be [file] [log] [blame]
---
title: Serializing Your Domain Object with a PdxSerializer
---
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
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**
1. In the domain classes that you wish to PDX serialize, make sure each class has a zero-arg constructor. For example:
``` pre
public PortfolioPdx(){}
```
2. If you have not already implemented `PdxSerializer` for some other domain object, perform these steps:
1. 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:
``` pre
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 {
...
```
2. In your cache PDX configuration, register the serializer class in the cache's `<pdx>` `<pdx-serializer>` `<class-name>` attribute.
Example:
``` pre
// 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.
``` pre
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 <span class="keyword apiname">org.apache.geode.pdx.ReflectionBasedAutoSerializer</span> class. See [configure pdx](../../tools_modules/gfsh/command-pages/configure.html#topic_jdkdiqbgphqh).
3. Program `PdxSerializer.toData` to recognize, cast, and handle your domain object:
1. Write each standard Java data field of your domain class using the `PdxWriter` write methods.
2. Call the `PdxWriter` `markIdentityField` method for each field you want to have <%=vars.product_name%> use to identify your object. Put this after the field's write method. <%=vars.product_name%> 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.
3. For a particular version of your class, you need to consistently write the same named field each time. The field names or number of fields must not change from one instance to another for the same class version.
4. For best performance, do fixed width fields first and then variable length fields.
5. If desired, you can check the portability of the object before serializing it by adding the `checkPortability` parameter when using the` PdxWriter` `writeObject`, `writeObjectArray`, and `writeField` methods.
Example `toData` code:
``` pre
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;
}
```
1. 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.
<%=vars.product_name%> provides the domain class type and `PdxReader` to the `fromData` method.
Example `fromData` code:
``` pre
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;
}
```
4. 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.