4 Using POF Serialization

Serialization is the process of encoding an object into a binary format. It is a critical component when working with Coherence as data must be moved around the network. The Portable Object Format (also referred to as POF) is a language agnostic binary format. POF was designed to be incredibly efficient in both space and time and has become a cornerstone element in working with Coherence. Using POF has many advantages ranging from performance benefits to language independence. It's recommended that you look closely at POF as your serialization solution when working with Coherence.

This chapter focuses only on the changes and additions that you need to make to your TopLink application files to make them eligible to participate in POF serialization. For more detailed information on using and configuring POF, see "Using Portable Object Format" in the Developers Guide for Oracle Coherence.

This chapter contains the following sections:

4.1 Implement a Serialization Routine

You must implement serialization routines that know how to serialize and deserialize your Entities. You can do this by implementing the PortableObject interface or by creating a serializer using the com.tangosol.io.pof.PofSerializer interface.

  • Implement the PortableObject interface in your Entity class files

    The com.tangosol.io.pof.PortableObject interface provides classes with the ability to self-serialize and deserialize their state to and from a POF data stream. To use this interface, you must also provide implementations of the required methods readExternal and writeExternal.

    Example 4-1 illustrates a sample Entity class file that implements the PortableObject interface. Note the implementations of the required readExternal and writeExternal methods.

    Also note that the class includes an @OneToOne annotation to define the relationship mapping between the Trade object and a Security object. TopLink supports all of the relationship mappings defined by the JPA specification: one-to-one, one-to-many, many-to-many, and many-to-many. These relationships can be expressed as annotations. Do not serialize or deserialize relationship mappings; TopLink Grid will perform these operations automatically.

    Example 4-1 Sample Entity Class that Implements PortableObject

    package oracle.toplinkgrid.codesample.pof.models.trader;
     
    import java.io.IOException;
    import java.io.Serializable;
     
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToOne;
     
    import com.tangosol.io.pof.PofReader;
    import com.tangosol.io.pof.PofWriter;
    import com.tangosol.io.pof.PortableObject;
     
    /**
     * This class will not be stored within Coherence as Trades are not high 
     * throughput objects in this model.
     *
     */
    @Entity
    public class Trade implements Serializable, PortableObject{
        /**
         * 
         */
        private static final long serialVersionUID = -244532585419336780L;
        @Id
        @GeneratedValue
        protected long id;
        @OneToOne(fetch=FetchType.EAGER)
        protected Security security;
        protected int quantity;
        protected double amount;
        public long getId() {
            return id;
        }
        public void setId(long id) {
            this.id = id;
        }
        public Security getSecurity() {
            return security;
        }
        public void setSecurity(Security security) {
            this.security = security;
        }
        public int getQuantity() {
            return quantity;
        }
        public void setQuantity(int quantity) {
            this.quantity = quantity;
        }
        public double getAmount() {
            return amount;
        }
        public void setAmount(double amount) {
            this.amount = amount;
        }
        public void readExternal(PofReader pofreader) throws IOException {
            id = pofreader.readLong(0);
            quantity = pofreader.readInt(2);
            amount = pofreader.readDouble(3); 
            
        }
        public void writeExternal(PofWriter pofwriter) throws IOException {
            pofwriter.writeLong(0, id);
            pofwriter.writeInt(2, quantity);
            pofwriter.writeDouble(3, amount);
            
        }
    }
    
  • Create a POFSerializer for the Entities

    An alternative to implementing the PortableObject interface is to implement the com.tangosol.io.pof.PofSerializer interface to create your own serializer and deserializer. This interface provides you with a way to externalize your serialization logic from the Entities you want to serialize. This is particularly useful when you do not want to change the structure of your classes to work with POF and Coherence. The POFSerializer interface provides these methods:

    • public Object deserialize(PofReader in)

    • public void serialize(PofWriter out, Object o)

4.2 Define a Cache Configuration File

In the cache configuration file, create cache mappings corresponding to the Entities you will be working with. Identify the serializer (such as com.tangosol.io.pof.ConfigurablePofContext) and the POF configuration file pof-config.xml. Identify the EclipseLink cache store (such as oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore) in the <cachestore-scheme> attribute.

Example 4-2 Sample Cache Configuration File

<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
              xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config http://xmlns.oracle.com/coherence/coherence-cache-config/1.0/coherence-cache-config.xsd">
  <caching-scheme-mapping>
    <cache-mapping>
        <cache-name>ATTORNEY_JPA_CACHE</cache-name>
        <scheme-name>eclipselink-jpa-distributed</scheme-name>
    </cache-mapping>
    <cache-mapping>
        <cache-name>CONTACT_JPA_CACHE</cache-name>
        <scheme-name>eclipselink-jpa-distributed-load</scheme-name>
    </cache-mapping>
...
additional cache mappings 
...
<caching-schemes>
    <distributed-scheme>
      <scheme-name>eclipselink-jpa-distributed-load</scheme-name>
      <service-name>EclipseLinkJPA</service-name>
 
    <serializer>
      <instance>
      <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
      <init-params>
        <init-param>
          <param-type>String</param-type>                 
          <param-value>trader-pof-config.xml</param-value>
        </init-param>
      </init-params>
      </instance>
    </serializer>
      <backing-map-scheme>
        <read-write-backing-map-scheme>
          <internal-cache-scheme>
            <local-scheme/>
          </internal-cache-scheme>
        </read-write-backing-map-scheme>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>
    <distributed-scheme>
      <scheme-name>eclipselink-jpa-distributed</scheme-name>
      <service-name>EclipseLinkJPA</service-name>
    <serializer>
      <instance>
      <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
      <init-params>
        <init-param>
          <param-type>String</param-type>
          <param-value>trader-pof-config.xml</param-value>
        </init-param>
      </init-params>
      </instance>
    </serializer>
 
      <backing-map-scheme>
        <read-write-backing-map-scheme>
          <internal-cache-scheme>
            <local-scheme/>
          </internal-cache-scheme>
          <!-- Define the cache scheme -->
          <cachestore-scheme>
            <class-scheme>
              <class-name>oracle.eclipselink.coherence.integrated.EclipseLinkJPACacheStore</class-name>
              <init-params>
                <init-param>
                  <param-type>java.lang.String</param-type>
                  <param-value>{cache-name}</param-value>
                </init-param>
                <init-param>
                  <param-type>java.lang.String</param-type>
                  <param-value>coherence-pu</param-value>
                </init-param>
              </init-params>
            </class-scheme>
          </cachestore-scheme>
        </read-write-backing-map-scheme>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>
  </caching-schemes>
</cache-config>

4.3 Provide a POF Configuration File

Provide a file that identifies the Entity classes that will participate in POF serialization. Coherence provides a POF configuration file which is named pof-config.xml by default. Use the file to assign type-ids to the Entity classes.

The POF configuration file must also contain type-id entries for the following classes:

  • oracle.eclipselink.coherence.integrated.internal.cache.WrapperInternal—This interface is used to access internal attributes of the Entity wrappers.

    oracle.eclipselink.coherence.integrated.cache.WrapperPofSerializer—Associated serializer. This class is used to provide serialization support for the Entity Wrappers within Coherence when you want to access Coherence caches directly. This includes users who have custom Value Extractors.

  • oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkExtractor—This interface is used for Coherence POF serialization to mark an EclipseLink Extractor for serialization. It extracts values from TopLink Grid entities for Filters.

    oracle.eclipselink.coherence.integrated.cache.ExtractorSerializer—Associated serializer. This class is used to provide serialization support for the Entity Wrappers within Coherence when you want to access the Coherence caches directly. This includes users who have custom Value Extractors.

  • oracle.eclipselink.coherence.integrated.internal.cache.VersionPutProcessor—An internal file, used for optimistic lock-aware updates to the grid.

  • oracle.eclipselink.coherence.integrated.internal.cache.VersionRemoveProcessor—An internal file, used for optimistic lock-aware removals from the grid.

  • oracle.eclipselink.coherence.integrated.internal.cache.RelationshipUpdateProcessor—An internal file, used to update lazy-loaded relationship data into the Grid.

  • oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$SubClassOf—An internal file. This is a Filter extension that filters on the type of Entity, eliminating superclasses from polymorphic queries.

Example 4-3 illustrates a sample POF configuration file that includes the TopLink Grid support files.

Example 4-3 Sample POF Configuration File

<?xml version="1.0"?>
<pof-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.oracle.com/coherence/coherence-pof-config"
    xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-pof-config http://xmlns.oracle.com/coherence/coherence-pof-config/1.0/coherence-pof-config.xsd">
  <user-type-list>
    <!-- include all "standard" Coherence POF user types -->
    <include>coherence-pof-config.xml</include>
     <user-type>
       <type-id>1163</type-id>
      <class-name>oracle.toplinkgrid.codesample.pof.models.trader.Attorney</class-name>
     </user-type>
   ...
   additional type IDs for Entity classes 
   ...
     <user-type>
       <type-id>1144</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.cache.WrapperInternal</class-name>
       <serializer>
         <class-name>oracle.eclipselink.coherence.integrated.cache.WrapperPofSerializer</class-name>
       </serializer>
     </user-type>
     <user-type>
       <type-id>1142</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkExtractor</class-name>
       <serializer>
         <class-name>oracle.eclipselink.coherence.integrated.cache.ExtractorSerializer</class-name>
       </serializer>
     </user-type>
     <user-type>
       <type-id>1141</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.cache.VersionPutProcessor</class-name>
     </user-type>
     <user-type>
       <type-id>1140</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.cache.VersionRemoveProcessor</class-name>
     </user-type>
     <user-type>
       <type-id>1139</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.cache.RelationshipUpdateProcessor</class-name>
     </user-type>
     <user-type>
       <type-id>1138</type-id>
       <class-name>oracle.eclipselink.coherence.integrated.internal.querying.EclipseLinkFilterFactory$SubClassOf</class-name>
     </user-type>
   </user-type-list>
 
   <allow-interfaces>true</allow-interfaces>
   <allow-subclasses>true</allow-subclasses>
 </pof-config>