この章の内容は次のとおりです。
シリアライズとは、オブジェクトをバイナリ形式にエンコードするプロセスです。これは、ネットワークを介してデータを移動する必要がある場合のCoherenceの操作に不可欠な機能です。Portable Object Format(POF)は言語に依存しないバイナリ形式です。POFは領域と時間の両面で効率を向上させるように設計されており、Coherenceの使用時に不可欠なものとなっています。POFバイナリ・ストリームの詳細は、『Oracle Coherence開発者ガイド』の「PIF-POFバイナリ形式」を参照してください。POF APIの使用の詳細は「Portable Object Formatの使用」を参照してください。
シリアライズで使用可能なオプションには、標準Javaシリアライズ、POF、独自のカスタム・シリアライズ・ルーチンなど、いくつかあります。各オプションには、それぞれトレードオフがあります。標準Javaシリアライズは簡単に実装可能であり、循環オブジェクト・グラフをサポートし、オブジェクトIDを保持します。ただし、比較的動作が低速で、冗長なバイナリ形式が使用され、Javaオブジェクトのみが処理対象となります。
Portable Object Formatには次のようなメリットがあります。
現在はJava、.NETおよびC++をサポートしており、言語に依存しません。
非常に効率的です。1つのString、1つのlongおよび3つのintsを備えた簡単なテスト・クラスでは、標準のJavaシリアライズと比較して、シリアライズおよびデシリアライズが7倍高速化され、生成されるバイナリのサイズが1/6になります。
バージョニングが可能です。オブジェクトの向上を図ることが可能であり、上位および下位の互換性があります。
シリアライズ・ロジックを外部化することができます。
索引付けされ、オブジェクト全体をデシリアライズせずに値を抽出できます。
POFには、オブジェクトのシリアライズおよびデシリアライズの方法を認識するシリアライズ・ルーチンの実装が必要です。識別するには、次の2つの方法があります。
使用するオブジェクトにcom.tangosol.io.pof.PortableObjectインタフェースを実装させます。
com.tangosol.io.pof.PofSerializerインタフェースを使用して、オブジェクトのシリアライザを実装します。
PortableObjectインタフェースは、次の2つのメソッドで構成される単純なインタフェースです。
public void readExternal(PofReader reader)
public void writeExternal(PofWriter writer)
前述のように、POF要素は索引付けされます。そのためには、POFストリームに対して書込みまたは読取りを実行する各要素に数字の索引を付けます。索引はPOFストリームにおいて書込みと読取りが実行される各要素に対して一意である必要があります。索引はスーパー・クラスと派生クラスの間で一意である必要があるため、派生タイプが存在する場合には特に注意が必要です。
例16-1はPortableObjectインタフェースの簡単な実装例です。
例16-1 PortableObjectインタフェースの実装
public void readExternal(PofReader in) 
        throws IOException 
    {
    m_symbol    = (Symbol) in.readObject(0);
    m_ldtPlaced = in.readLong(1);
    m_fClosed   = in.readBoolean(2);
    }
 
public void writeExternal(PofWriter out) 
        throws IOException 
    {
    out.writeObject(0, m_symbol);
    out.writeLong(1, m_ldtPlaced);
    out.writeBoolean(2, m_fClosed);
    }
PofSerializerインタフェースには、シリアライズ・ロジックをシリアライズするクラスから外部化する手段が用意されています。これは、CoherenceでPOFを使用する場合に、クラスの構造を変更したくないときには特に役立ちます。PofSerializerインタフェースは、次の2つのメソッドで構成されています。
public Object deserializer(PofReader in)
public void writeObject(PofWriter out, Object o)
PortableObjectインタフェース同様、POFストリームに対して書込みまたは読取りが実行される要素はすべて一意に索引付けされている必要があります。PofSerializerインタフェースの実装例を、次に示します。
例16-2 PofSerializerインタフェースの実装
public Object deserialize(PofReader in) 
        throws IOException 
    {
    Symbol symbol    = (Symbol)in.readObject(0);
    long   ldtPlaced = in.readLong(1);
    bool   fClosed   = in.readBoolean(2);
    
    // mark that the read is complete
    in.readRemainder(null);
 
    return new Trade(symbol, ldtPlaced, fClosed);
    }
 
public void serialize(PofWriter out, Object o) 
        throws IOException 
    {
    Trade trade = (Trade) o;
    out.writeObject(0, trade.getSymbol());
    out.writeLong(1, trade.getTimePlaced());
    out.writeBoolean(2, trade.isClosed());
    
    // mark that write is complete
    out.writeRemainder(null);
    }
オブジェクトの属性にPOFの索引を割り当てる際には、次の点に留意することが重要です。
読取りと書込みの順序: シリアライズ・ルーチンの最小索引値から開始して、最大索引値で終了します。値をデシリアライズするときには、書込みと同じ順序で読取りを実行します。
連続していない索引を使用することはできますが、読取り/書込みは順次処理する必要があります。
サブクラス作成時に索引の範囲を予約する場合: 索引は派生タイプ間で累積されます。そのため、各派生タイプがそのスーパークラスで予約されたPOF索引範囲を認識する必要があります。
索引を他の目的に使用しない: 進化のサポートを必要とする場合は、クラス・リビジョン全体で属性の索引を他の目的に使用しないようにすることが必須です。
索引のラベル付け: 索引にpublic static final intでラベル付けすると、特に、PofExtractorおよびPofUpdaterを使用する場合に、オブジェクトの操作がはるかに容易になります。索引のラベル付けを行った後も、前述のように、必ず順番どおりに読取りおよび書出しが実行されるようにします。
Coherenceは、POFのシリアライズされたオブジェクトを適切なシリアライズ・ルーチンに(PofSerializer、またはPortableObjectインタフェースを介したコールによって)マッピングするConfigurablePofContextクラスを備えています。クラスごとに、オプションのPofSerializerにマッピング可能な、POFにおいて一意のtype-idを指定します。各クラスにシリアライズ・ルーチンを割り当てた後は、それらのクラスをConfigurablePofContextに登録する必要があります。ConfigurablePofContextへのカスタムのユーザー定義型の登録には、POF構成ファイルを使用します。これはXMLファイルであり、このファイル内の<user-type-list>要素には、PortableObjectを実装するクラス、またはPofSerializerが関連付られたクラスのリストが格納されます。各クラスのtype-idは一意である必要があり、またすべてのクラスタ・インスタンス(拡張クライアントを含む)で一致している必要があります。
pof-config.xmlファイルの例を次に示します。
<?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
   coherence-pof-config.xsd">
   <user-type-list>
      <include>coherence-pof-config.xml</include>
      <!-- User types must be above 1000 -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>com.examples.MyTrade</class-name>
         <serializer>
            <class-name>com.examples.MyTradeSerializer</class-name>
         </serializer>
      </user-type>
 
      <user-type>
        <type-id>1002</type-id>
        <class-name>com.examples.MyPortableTrade</class-name>
      </user-type>
   </user-type-list>
</pof-config>
| 注意:Coherenceでは、最初の1000個のtype-idは内部使用のために予約されています。よく見ると、user-type-listに coherence-pof-config.xmlファイルがインクルードされているのがわかります。ここで、Coherence固有のユーザー型が定義されています。このファイルをすべてのPOF構成ファイルにインクルードする必要があります。 | 
POFの使用を開始するためには、さらに、各サービスに対して、ConfigurablePofContextを使用するように構成する必要があります。そのためには、キャッシュ構成ファイルでキャッシュ・スキームの<serializer>要素を使用します。ConfigurablePofContextには、POF構成ファイルをポイントする、文字列ベースの<init-param>を指定します。
POFを使用するように構成した分散キャッシュ・スキームの例を次に示します。
 <distributed-scheme>
   <scheme-name>example-distributed</scheme-name>
   <service-name>DistributedCache</service-name>
   <serializer>
      <instance>
         <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
         <init-params>
            <init-param>
               <param-type>String</param-type>
               <param-value>my-pof-config.xml</param-value>
            </init-param>
         </init-params>
      </instance>
   </serializer>
</distributed-scheme>
もう1つの方法として、次のシステム・プロパティを指定して、POFを使用するようにJVMインスタンス全体を構成することもできます。
tangosol.pof.enabled=true: JVMインスタンス全体でPOFを有効にします。
tangosol.pof.config=CONFIG_FILE_PATH: 使用するPOF構成ファイルへのパスです。クラスパスにない場合は、ファイル・リソースとして表現する必要があります(例: file:///opt/home/coherence/mycustom-pof-config.xml)。
POFの使用には、パフォーマンス上のメリットから言語の非依存性まで、様々なメリットがあります。Coherenceで作業する際には、シリアライズ・ソリューションとしてPOFを詳細に検討することをお薦めします。C++でのPOFの操作の詳細は、『Oracle Coherenceクライアント・ガイド』の「C++クライアントの統合オブジェクトの構築」を参照してください。.NETでのPOFの操作の詳細は、『Oracle Coherenceクライアント・ガイド』の「.NETクライアントの統合オブジェクトの構築」を参照してください。