プライマリ・コンテンツに移動
Oracle® Fusion Middleware Oracle Coherenceリモート・クライアントの開発
12c (12.2.1)
E69907-02
目次へ移動
目次

前
次

18 統合オブジェクトの構築(.NET)

この章では、.NETクライアント作成時にPortable Object Format (POF)シリアライズ形式を使用する手順を説明します。

この章は次の各項で構成されています。

統合オブジェクトの構築(.NET)の概要

Coherenceキャッシュは、値オブジェクトをキャッシュするために使用されます。.NETクライアントがCoherence JVMと正常に通信するためには、プラットフォームに依存しないシリアライズ形式が必要になります。これにより、.NETクライアントとCoherence JVM (Coherence*Extend Javaクライアントを含む)の両方で、Coherenceキャッシュに格納されている値オブジェクトを正しくシリアライズおよびデシリアライズできるようになります。Coherence for .NETクライアント・ライブラリおよびCoherence*Extendクラスタ化サービスでは、Portable Object Format (POF)というシリアライズ形式が使用されます。POFを使用すると、値オブジェクトのプラットフォームおよび元の言語と関係ない方法で、値オブジェクトをバイナリ・ストリームにエンコードできます。POFバイナリ・ストリームの詳細は、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

POFでは、あらゆる一般的な.NET型が即時利用可能な状態でサポートされます。カスタムの.NETクラスも次の手順でPOFストリームにシリアライズできます:

  1. IPortableObjectインタフェースを実装する.NETクラスを作成します。「IPortableObject実装の作成」を参照してください。

  2. 同様に、PortableObjectインタフェースを実装する、対応するJavaクラスを作成します。「PortableObject実装の作成(Java)」を参照してください。

  3. カスタムの.NETクラスをクライアントに登録します。「.NETクライアントでのカスタム型の登録」を参照してください。

  4. Coherence*Extendクラスタ化サービスを実行している各サーバーにカスタムのJavaクラスを登録します。「クラスタでのカスタム型の登録」を参照してください。

ここまでの手順が完了すると、組込みのデータ型と同じようにカスタムの.NETクラスをCoherenceキャッシュにキャッシュできるようになります。さらに対応するJavaクラスを使用すれば、それらの型をCoherenceまたはCoherence*Extend JVMから取得し、操作して、格納できます。

IPortableObject実装の作成

IPortableObjectを実装する各クラスは、自身の状態をPOFデータ・ストリームにシリアライズし、POFデータ・ストリームからデシリアライズできます。この処理は、ReadExternalメソッド(デシリアライズ)およびWriteExternalメソッド(シリアライズ)で行われます。概念上は、すべてのユーザー定義型が0個以上の索引付き値(プロパティ)で構成されており、それらが1つずつPOFデータ・ストリームから読み取られ、POFデータ・ストリームに書き込まれます。移植可能なクラスには、IPortableObjectインタフェースの実装が必要であること以外の唯一の要件として、デフォルト・コンストラクタが必要です。これにより、POFデシリアライザで、デシリアライズ時にクラスのインスタンスを作成できるようになります。

例18-1 は、移植可能なユーザー定義クラスを示しています。

例18-1 移植可能なユーザー定義クラス

public class ContactInfo : IPortableObject
{
    private string name;
    private string street;
    private string city;
    private string state;
    private string zip;
    public ContactInfo()
    {}

    public ContactInfo(string name, string street, string city, string state, string zip)
    {
        Name   = name;
        Street = street;
        City   = city;
        State  = state;
        Zip    = zip;
    }
    public void ReadExternal(IPofReader reader)
    {
        Name   = reader.ReadString(0);
        Street = reader.ReadString(1);
        City   = reader.ReadString(2);
        State  = reader.ReadString(3);
        Zip    = reader.ReadString(4);
    }
    public void WriteExternal(IPofWriter writer)
    {
        writer.WriteString(0, Name);
        writer.WriteString(1, Street);
        writer.WriteString(2, City);
        writer.WriteString(3, State);
        writer.WriteString(4, Zip);
    }
    // property definitions ommitted for brevity
}

Javaバージョンの.NETオブジェクトの実装

POFの使用によって、並列のJava実装を必要とせずに、キーおよび値オブジェクトをクラスタ内に格納できます。これは、基本的なgetとputベースの操作を実行する場合に適しています。さらに、PofExtractorPofUpdater APIにより、Coherenceの非プリミティブ・タイプを使用するときの柔軟性が向上します。多くの拡張クライアントの場合、グリッド内に対応するJavaクラスは不要です。POFエクストラクタとPOFアップデータはバイナリをナビゲートできるため、キーと値全体をオブジェクト形式にデシリアライズしなくても済みます。これは、索引付けする値をPOFエクストラクタを使用してプルするだけで索引付けできることを意味します。

並列のJava実装の組込みが必要になる状況

Javaベースのキャッシュ・サーバーが、データ・オブジェクトのシリアライズ表現を保持するだけでなく、データ・オブジェクトと直接対話する必要がある場合は、並列のJava実装が必要です。たとえば、キャッシュ・ストアを使用するときJavaクラスは必要です。この場合、キーと値のデシリアライズ・バージョンがキャッシュ・ストアに渡され、バックエンドに書き込まれます。さらに、オブジェクトへの直接アクセスが必要な場合、問合せ、フィルタ、入力プロセッサおよびアグリゲータはJava実装が必要です。

Java実装が必要な場合は、実装はキャッシュ・サーバーにある必要があります。JavaバージョンのPOFでシリアライズ可能にする方法は前述の例とほぼ同じで、「PortableObject実装の作成(Java)」で説明されています。詳細は、IPortableObjectIPofSerializerのAPIを参照してください。これらのAPIは、.NETの方法と互換性があります。

キーの関連付けチェックの遅延

キー・クラスは、クラスタ側Java実装を必要としません。これはIKeyAssociationインタフェースを使用してデータのアフィニティを指定している場合でも同様です。キー・クラスは、クライアント側でチェックされ、修飾されたバイナリがクラスタによって作成および使用されます。ただし、キーの関連付けをJavaキー・クラスに依存している既存のクライアント実装は、Javaキー・クラスの使用を強制するためにdefer-key-association-checkパラメータを設定する必要があります。キーの関連付けを使用する既存クライアント・アプリケーションで、クライアント側のキー・バイナリを利用する場合は、getAssociatedKey()実装を既存のJavaクラスから対応するクライアント・クラスに移植する必要があります(IKeyAssociation.AssociatedKeyを参照)。

キーの関連付け処理をExtendクライアントによってではなくクラスタ側で実行するには、クライアント側キャッシュの構成で<remote-cache-scheme>要素の<defer-key-association-check>要素をtrueに設定します。次に例を示します。

<remote-cache-scheme>
   ...
   <defer-key-association-check>true</defer-key-association-check>
</remote-cache-scheme>

注意:

パラメータがtrueに設定されている場合、Javaキー・クラス実装は、キーの関連付けを使用していない場合でも、クラスタに存在する必要があります。

PortableObject実装の作成(Java)

Javaでの移植可能なクラスの実装は、.NETでの実装と非常によく似ています。例18-2 は、例18-1 の.NETクラスをJavaで実現した場合を示しています。

例18-2 Javaでのユーザー定義クラス

public class ContactInfo implements PortableObject
    {    private String m_sName;

    private String m_sStreet;
    private String m_sCity;
    private String m_sState;
    private String m_sZip;
    public ContactInfo()
        {
        }
    public ContactInfo(String sName, String sStreet, String sCity, String sState, String sZip)
        {
        setName(sName);
        setStreet(sStreet);
        setCity(sCity);
        setState(sState);
        setZip(sZip);
        }
    public void readExternal(PofReader reader)
            throws IOException
        {
        setName(reader.readString(0));
        setStreet(reader.readString(1));
        setCity(reader.readString(2));
        setState(reader.readString(3));
        setZip(reader.readString(4));
        }
    public void writeExternal(PofWriter writer)
            throws IOException
        {
        writer.writeString(0, getName());
        writer.writeString(1, getStreet());
        writer.writeString(2, getCity());
        writer.writeString(3, getState());
        writer.writeString(4, getZip());
        }
    // accessor methods omitted for brevity
}

.NETクライアントでのカスタム型の登録

各POFユーザー定義型は、POFストリーム内で整数値として表されます。したがって、POFには、ユーザー定義型をそのエンコードされた型識別子にマップするための外部メカニズムが必要です(また、この逆の場合も同様です)。このメカニズムでは、次に示すように、XML構成ファイルを使用してマッピング情報が格納されます。POF構成要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。

<?xml version="1.0"?>
<pof-config xmlns="http://schemas.tangosol.com/pof">
   <user-type-list>
    <!-- include all "standard" Coherence POF user types -->
      <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
      </include>
    <!-- include all application POF user types -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>My.Example.ContactInfo, MyAssembly</class-name>
      </user-type>
   </user-type-list>
</pof-config>

次の点に注意してください。

  • カスタム型の型識別子は1001以上の数値で始まる必要があります。1000より小さい数値は内部使用に予約されています。この例に示すように、<user-type-list>にはcoherence-pof-config.xmlファイルが含まれます。これにはCoherence固有のユーザー型が定義されており、そのユーザー型をすべてのPOF構成ファイルに含める必要があります。

  • class-name要素内では完全に修飾された型名を指定する必要はありません。型とアセンブリ名を指定すれば十分です。

型識別子とカスタム型の間のマッピングを構成したら、キャッシュ構成ディスクリプタにserializer要素を追加して、それらのマッピングを使用するようCoherence for .NETを構成する必要があります。次の各例では、ユーザーの型マッピングがmy-dotnet-pof-config.xmlファイルに保存されていることを前提とします。

<remote-cache-scheme>
   <scheme-name>extend-direct</scheme-name>
   <service-name>ExtendTcpCacheService</service-name>
   <initiator-config>
   ...
      <serializer>
         <class-name>Tangosol.IO.Pof.ConfigurablePofContext, Coherence
         </class-name>
         <init-params>
            <init-param>
               <param-type>string</param-type>
               <param-value>my-dotnet-pof-config.xml</param-value>
            </init-param>
         </init-params>
      </serializer>
   </initiator-config>
</remote-cache-scheme>

シリアライザを明示的に指定しない場合は、ConfigurablePofContext型がPOFシリアライザとして使用されます。これはpof-config.xmlというデフォルトの構成ファイルを使用します。Coherence .NETアプリケーションでは、アプリケーションのデプロイ先フォルダと、Webアプリケーションの場合はWebアプリケーションのルートの両方で、デフォルトのPOF構成ファイルが検索されます。POF構成ファイルが見つからない場合は、Coherence for .NETアプリケーション構成ファイルのpof-config要素の内容によるファイルの特定が試行されます。次に例を示します。

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
  </configSections>
  <coherence>
    <pof-config>my-dotnet-pof-config.xml</pof-config>
  </coherence>
</configuration>

クラスタでのカスタム型の登録

TCP/IP Coherence*Extendクラスタ化サービスを実行しているCoherenceノードでカスタム型のオブジェクトを送受信できるようにするには、各ノードに、カスタム型の類似したPOF構成ファイルが必要です。

クラスタ側のPOF構成ファイルは、クライアントで作成されたファイルと似ています。唯一の違いは、class-name要素で.NETクラス名のかわりに完全修飾されたJavaクラス名を指定する必要がある点です。クラスタ側のPOF構成ファイルのサンプル(my-java-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 all "standard" Coherence POF user types -->
      <include>coherence-pof-config.xml</include>
   <!-- include all application POF user types -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>com.mycompany.example.ContactInfo</class-name>
      </user-type>
   </user-type-list>
</pof-config>

カスタム型を追加したら、オブジェクトのシリアライズ時に各自のPOF構成ファイルが使用されるようサーバーを構成する必要があります。

<proxy-scheme>
   <service-name>ExtendTcpProxyService</service-name>
   <acceptor-config>
   ...
      <serializer>
         <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
         <init-params>
            <init-param>
               <param-type>string</param-type>
               <param-value>my-java-pof-config.xml</param-value>
            </init-param>
         </init-params>
      </serializer>
   </acceptor-config>
  ...
</proxy-scheme>

進化可能な移植性のあるユーザー定義型

PIF-POFは、シリアライズされた形式の移植可能なユーザー定義型の前方互換性および後方互換性をネイティブにサポートします。.NETでは、ユーザー定義型でIPortableObjectインタフェースのかわりにIEvolvablePortableObjectインタフェースを実装することで、このサポートが実現します。IEvolvablePortableObjectインタフェースは、IPortableObjectIEvolvableの両方のインタフェースを拡張するマーカー・インタフェースです。IEvolvableインタフェースは、型のバージョニングをサポートする3つのプロパティを追加します。IEvolvableクラスには整数のバージョン識別子n (n >= 0)が含まれていますシリアライズされた形式のIEvolvableクラスのコンテンツ、セマンティクス、またはそれら両方が変更されると、このバージョン識別子が引き上げられます。2つのバージョン識別子n1n2は、n1 == n2であれば同じバージョンを示し、n2 > n1であればn2のバージョンがn1のバージョンより新しいことを示します。

IEvolvableインタフェースは、データの追加による型の進化をサポートするように設計されています。あるデータに前のバージョンの型が依存している場合、そのデータを安全に削除することはできません。同様に、データの前の構造またはセマンティクスに前のバージョンの型が依存している場合、そのデータの構造またはセマンティクスを前のバージョンから安全に変更することはできません。

IEvolvableオブジェクトがデシリアライズされる場合は、新しいバージョンの型に追加された未知のデータ、およびそのデータ形式のバージョン識別子が保持されます。その後、このIEvolvableオブジェクトがシリアライズされると、保持されたバージョン識別子と未知の将来データがオブジェクトに取り込まれます。

古いバージョンを示すバージョン識別子を持つデータ・ストリームからIEvolvableオブジェクトをデシリアライズする場合は、その古いバージョン以降に追加されたデータ・フィールドやプロパティの値をデフォルトに設定し、計算する必要があります。その後、このIEvolvableオブジェクトがシリアライズされると、そのバージョン識別子と全データがオブジェクトに取り込まれます。この場合は未知の将来データがないことに注意してください。将来データは、データ・ストリームのバージョンがIEvolvable型のバージョンよりも新しい場合にのみ存在します。

例18-3 は、クラスの進化をサポートするように.NET型のContactInfoを変更する方法を示しています。

例18-3 クラスの進化をサポートするようにクラスを変更する

public class ContactInfo : IEvolvablePortableObject
{
    private string name;
    private string street;
    private string city;
    private string state;
    private string zip;
    // IEvolvable members
    private int    version;
    private byte[] data;
    public ContactInfo()
    {}
    public ContactInfo(string name, string street, string city, string state, string zip)
    {
        Name   = name;
        Street = street;
        City   = city;
        State  = state;
        Zip    = zip;
    }
    public void ReadExternal(IPofReader reader)
    {
        Name   = reader.ReadString(0);
        Street = reader.ReadString(1);
        City   = reader.ReadString(2);
        State  = reader.ReadString(3);
        Zip    = reader.ReadString(4);
    }
    public void WriteExternal(IPofWriter writer)
    {
        writer.WriteString(0, Name);
        writer.WriteString(1, Street);
        writer.WriteString(2, City);
        writer.WriteString(3, State);
        writer.WriteString(4, Zip);
    }
    public int DataVersion
    {
        get { return version; }
        set { version = value; }
    }
    public byte[] FutureData
    {
        get { return data; }
        set { data = value; }
    }
    public int ImplVersion
    {
        get { return 0; }
    }
    // property definitions ommitted for brevity
}

同様に、Java型のContactInfoは、EvolvablePortableObjectインタフェースを実装することでクラスの進化をサポートするように変更できます。

例18-4 クラスの進化をサポートするようにJava型のクラスを変更する

public class ContactInfo
        implements EvolvablePortableObject
    {
    private String m_sName;
    private String m_sStreet;
    private String m_sCity;
    private String m_sState;
    private String m_sZip;

    // Evolvable members
    private int    m_nVersion;
    private byte[] m_abData;

    public ContactInfo()
        {}

    public ContactInfo(String sName, String sStreet, String sCity,
            String sState, String sZip)
        {
        setName(sName);
        setStreet(sStreet);
        setCity(sCity);
        setState(sState);
        setZip(sZip);
        }

    public void readExternal(PofReader reader)
            throws IOException
        {
        setName(reader.readString(0));
        setStreet(reader.readString(1));
        setCity(reader.readString(2));
        setState(reader.readString(3));
        setZip(reader.readString(4));
        }

    public void writeExternal(PofWriter writer)
            throws IOException
        {
        writer.writeString(0, getName());
        writer.writeString(1, getStreet());
        writer.writeString(2, getCity());
        writer.writeString(3, getState());
        writer.writeString(4, getZip());
        }

    public int getDataVersion()
        {
        return m_nVersion;
        }

    public void setDataVersion(int nVersion)        {
        m_nVersion = nVersion;
        }

    public Binary getFutureData()
        {
        return m_binData;
        }

    public void setFutureData(Binary binFuture)
        {
        m_binData = binFuture;
        }

    public int getImplVersion()
        {
        return 0;
        }

    // accessor methods omitted for brevity
    }

変更なしで型を移植可能にする

既存のユーザー定義型を移植可能にする変更が望ましくない場合、または不可能な場合があります。その場合は、IPofSerializerの実装(.NET)、PofSerializerインタフェースの実装(Java)、またはその両方を作成することで、ユーザー定義型の移植可能なシリアライズを外部化できます。

例18-5 は、ContactInfoIPofSerializerインタフェースの実装を示しています。

例18-5 .NET型のIPofSerializerの実装

public class ContactInfoSerializer : IPofSerializer
{
    public object Deserialize(IPofReader reader)
    {
        string name   = reader.ReadString(0);
        string street = reader.ReadString(1);
        string city   = reader.ReadString(2);
        string state  = reader.ReadString(3);
        string zip    = reader.ReadString(4);

        ContactInfo info = new ContactInfo(name, street, city, state, zip);
        info.DataVersion = reader.VersionId;
        info.FutureData  = reader.ReadRemainder();

        return info;
    }

    public void Serialize(IPofWriter writer, object o)
    {
        ContactInfo info = (ContactInfo) o;

        writer.VersionId = Math.Max(info.DataVersion, info.ImplVersion);
        writer.WriteString(0, info.Name);
        writer.WriteString(1, info.Street);
        writer.WriteString(2, info.City);
        writer.WriteString(3, info.State);
        writer.WriteString(4, info.Zip);
        writer.WriteRemainder(info.FutureData);
    }
}

Java型のContactInfoPofSerializerインタフェースの実装は次のようになります。

例18-6 Java型クラスのPofSerializerの実装

public class ContactInfoSerializer
        implements PofSerializer
    {
    public Object deserialize(PofReader in)
            throws IOException
        {
        String sName   = in.readString(0);
        String sStreet = in.readString(1);
        String sCity   = in.readString(2);
        String sState  = in.readString(3);
        String sZip    = in.readString(4);

        ContactInfo info = new ContactInfo(sName, sStreet, sCity, sState, sZip);
        info.setDataVersion(in.getVersionId());
        info.setFutureData(in.readRemainder());

        return info;
        }

    public void serialize(PofWriter out, Object o)
            throws IOException
        {
        ContactInfo info = (ContactInfo) o;

        out.setVersionId(Math.max(info.getDataVersion(), info.getImplVersion()));
        out.writeString(0, info.getName());
        out.writeString(1, info.getStreet());
        out.writeString(2, info.getCity());
        out.writeString(3, info.getState());
        out.writeString(4, info.getZip());
        out.writeRemainder(info.getFutureData());
        }
    }

.NET型のContactInfoIPofSerializer実装を登録するには、POF構成ファイルのContactInfoユーザー定義型に関するuser-type要素で、serializer要素内にIPofSerializerのクラス名を指定します。次に例を示します。

<?xml version="1.0"?>

<pof-config xmlns="http://schemas.tangosol.com/pof"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://schemas.tangosol.com/pof
   assembly://Coherence/Tangosol.Config/pof-config.xsd">
   <user-type-list>
   <!-- include all "standard" Coherence POF user types -->
      <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
      </include>
   <!-- include all application POF user types -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>My.Example.ContactInfo, MyAssembly</class-name>
         <serializer>
            <class-name>My.Example.ContactInfoSerializer, MyAssembly</class-name>
         </serializer>
      </user-type>
   </user-type-list>
</pof-config>

同様に、Java型のContactInfoPofSerializer実装を登録できます。

<?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 all "standard" Coherence POF user types -->
      <include>example-pof-config.xml</include>
   <!-- include all application POF user types -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>com.mycompany.example.ContactInfo</class-name>
         <serializer>
            <class-name>com.mycompany.example.ContactInfoSerializer</class-name>
         </serializer>
      </user-type>
   </user-type-list>
</pof-config>

POFオブジェクト参照の使用

POFでは、POFストリーム内で複数回出現するオブジェクトに、オブジェクトのIDや参照の使用がサポートされています。オブジェクトには、IDが付けられ、同じPOFストリーム内で2回目以降に出現するラベルが付いたオブジェクトは、そのIDで参照されます。

参照を使用することで、同じオブジェクトを複数回エンコーディングすることを防ぎ、データサイズを削減できます。一般に、参照を使用するのは、サイズの大きな多数のオブジェクトが複数回生成されるときや、オブジェクトでネストや循環データ構造が使用されるときです。ただし、大量のデータがあり、繰返しが少ないアプリケーションの場合、オブジェクト参照を使用してもオブジェクトのIDや参照の追跡によって生じるオーバーヘッドのために、最小限の利点しかありません。

オブジェクト・アイデンティティおよび参照の使用には次の制限があります。

  • オブジェクト参照には、ユーザー定義のオブジェクト型のみがサポートされています。

  • IEvolvableオブジェクトでは、オブジェクト参照はサポートされていません。

  • キーでは、オブジェクト参照はサポートされていません。

  • 参照をサポートしていないPOFコンテキストによって記述されたオブジェクトは、参照をサポートするPOFコンテキストで読み込むことができません。また、この逆の場合も同様です。

  • POFエクストラクタを使用して、オブジェクト・アイデンティティおよび参照を使用するPOFオブジェクトを問い合せることはできません。かわりに、IValueExtractor APIを使用してオブジェクト値を問い合せるか、またはオブジェクト参照を無効にしてください。

  • オブジェクト参照を使用するとき、IPofNavigatorおよびIPofValue APIの使用には次の制約があります。

    • 読取り操作のみ許可されます。書込み操作はUnsupportedOperationExceptionとなります。

    • ユーザー・オブジェクトは非共通コレクションでアクセスできますが、共通コレクションではアクセスできません。

    • 読取り操作については、オブジェクトがデータ・ストリームで複数回出現する場合、オブジェクトが最初に出現した場所で読み取られてから、次のデータの部分で読み取られる必要があります。そうでない場合は、IOException: missing identity: <ID>がスローされます。たとえば、リストが3つあり、そのすべてが同じPersonオブジェクトpを含む場合。pオブジェクトは、最初のリストで読み取られてから2番目または3番目のリストで読み取られる必要があります。

この項の内容は、次のとおりです。

POFオブジェクト参照の有効化

オブジェクト参照は、デフォルトでは無効になっており、SimplePofContextクラスを使用するときにpof-config.xml構成ファイル内か、プログラムによって有効にする必要があります。

POF構成ファイルでオブジェクト参照を有効にするには、<pof-config>要素内に<enable-references>要素を含めて、値をtrueに設定します。次に例を示します。

<?xml version="1.0"?>

<pof-config xmlns="http://schemas.tangosol.com/pof"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://schemas.tangosol.com/pof
   assembly://Coherence/Tangosol.Config/pof-config.xsd">
   ...
   <enable-references>true</enable-references>
</pof-config>

SimplePofContextクラスの使用時にオブジェクト参照を有効にするには、setReferenceEnabledメソッドをコールして、trueに設定します。次に例を示します。

SimplePofContext ctx = new SimplePofContext();
ctx.IsReferenceEnabled = true;

循環構造のオブジェクトやネストされたオブジェクトへのPOFオブジェクトIDの登録

循環構造のオブジェクトやネストされたオブジェクトは、オブジェクトの作成時に手動でIDを登録する必要があります。これを行わないと、親を参照する子が、参照マップで親のIDを検出しません。オブジェクトのIDは、Tangosol.IO.Pof.IPofReader.RegisterIdentityメソッドを使用し、デシリアライズ・ルーチンでシリアライザから登録できます。

次の例では、循環参照を含んだ2つのオブジェクト(CustomerおよびProduct)と、CustomerオブジェクトのIDを登録するシリアライザ実装を示しています。

Customerオブジェクトの定義は次のとおりです。

public class Customer
   {
      String m_name;
      Product m_product;
 
   public Customer(String name)
      {
      m_name = name;
      }
 
   public Customer(String name, Product product)
      {
      m_name = name;
      m_product = product;
      }
 
   public String getName()
      {
      return m_name;
      }
 
   public Product getProduct()
      {
      return m_product;
      }
 
   public void setProduct(Product product)
      {
         m_product = product;
      }
   }

Productオブジェクトの定義は次のとおりです。

public class Product
   {
      private Customer m_customer;
 
   public Product(Customer customer)
      {
      m_customer = customer;
      }
 
   public Customer getCustomer()
      {
      return m_customer;
      }
   }

デシリアライズの間にIDを登録するシリアライザ実装の定義は次のとおりです。

public class CustomerSerializer : IPofSerializer
   {
   public void Serialize(IPofWriter pofWriter, object o)
      {
      var c = (Customer) o;
      pofWriter.WriteString(0, c.getName());
      pofWriter.WriteObject(1, c.getProduct());
      pofWriter.WriteRemainder(null);
   }
 
   public object Deserialize(IPofReader pofReader)
      {
      String name = pofReader.ReadString(0);
      var customer = new Customer(name);
 
      pofReader.RegisterIdentity(customer);
      customer.setProduct((Product) pofReader.ReadObject(1));
      pofReader.ReadRemainder();
      return customer;
      }
   }

POF注釈を使用したオブジェクトのシリアライズ

POF注釈は、オブジェクトにシリアライズやデシリアライズ・ルーチンの実装を自動化する方法を提供します。POF注釈は、IPofSerializerインタフェースの実装であるPofAnnotationSerializerクラスを使用してシリアライズまたはデシリアライズします。注釈は、IPortableObjectおよびIPofSerializerインタフェースのかわりに使用でき、オブジェクトをシリアライズ可能にするために必要な時間やコードの量を削減します。

この項の内容は、次のとおりです。

POFシリアライズでのオブジェクトへの注釈付け

クラスとクラスのプロパティがPOFシリアライズ可能であることを示すために利用できる注釈は2つあります。

  • [Portable] - クラスをPOFシリアライズ可能とマークします。注釈は、クラス・レベルのみに使用でき、メンバーを含みません。

  • [PortableProperty] - プロパティ、アクセッサまたはメンバー変数をPOFシリアライズ化されたプロパティとしてマークします。注釈が付けられたメソッドは、アクセッサの表記法(GetSetIs)に従っている必要があります。メンバーを、POF索引や、シリアライズまたはデシリアライズの前後で実行するカスタム・コーデックの指定に使用できます。索引の値は省略可能で、自動的に割り当てられます。カスタム・コーデックを入力しない場合は、デフォルトのコーデックが使用されます。

次の例は、クラス、プロパティおよびメンバー変数への注釈付けを示しています。さらに、PortableProperty索引が明示的に指定されています。

[Portable]
public class Person
{
   [PortableProperty(0)]
   public string GetFirstName()
   {
      return m_firstName;
   }

   private String m_firstName;

   [PortableProperty(1)]
   public string LastName;
   {
      get; set;
   }

   [PortableProperty(2)]
   private int m_age;
}

POF注釈付きオブジェクトの登録

POF注釈付きオブジェクトは、pof-config.xmlファイルの<user-type要素内で登録する必要があります。POF構成要素の詳細なリファレンスは、『Oracle Coherenceでのアプリケーションの開発』を参照してください。POF注釈付きオブジェクトは、IPortableObjectを実装していない場合はPofAnnotationSerializerシリアライザを使用し、Portableとして注釈が付けられます。ただし、このシリアライザは、オブジェクトが注釈付きかどうかと、ユーザー定義型に含める必要がないことを自動的に仮定します。次の例では、注釈付きPersonオブジェクトのユーザー定義型を登録します。

<?xml version='1.0'?>
<pof-config xmlns="http://schemas.tangosol.com/pof">
   <user-type-list>
    <!-- include all "standard" Coherence POF user types -->
      <include>assembly://Coherence/Tangosol.Config/coherence-pof-config.xml
      <!-- User types must be above 1000 -->
      <user-type>
         <type-id>1001</type-id>
         <class-name>My.Examples.Person, MyAssembly</class-name>
      </user-type>
   </user-type-list>
</pof-config>

自動索引付けの有効化

POF注釈では、自動索引付けがサポートされており、明示的な索引値の割当てや管理の必要性を軽減されます。[PortableProperty]注釈を定義している場合は、索引値を省略します。索引の割当てはプロパティ名によって決定されます。明示的に索引値を割り当てるプロパティによって、自動索引値が割り当てられることはありません。次の表は、自動索引アルゴリズムの命令セマンティクスを示しています。自動索引付けは、明示的に定義された索引を維持し(プロパティc参照)、索引が省略されている場合は、索引を割り当てます。

名前 明示的な索引 決定された索引

c

1

1

a

省略

0

b

省略

2

注意:

自動索引では、現在、進化可能なクラスがサポートされていません。

自動索引付けを有効にするには、POF構成ファイルでユーザー定義型としてオブジェクトを登録するときにPofAnnotationSerializerシリアライザ・クラスを明示的に定義する必要があります。コンストラクタ内のautoIndexブール・パラメータで自動索引を有効にでき、必ずtrueに設定します。次に例を示します。

<user-type>
   <type-id>1001</type-id>
   <class-name>Examples.Person</class-name>
   <serializer>
      <class-name>Tangosol.IO.Pof.PofAnnotationSerializer, Coherence</class-name>
         <init-params>
         <init-param>
            <param-type>int</param-type>
            <param-value>{type-id}</param-value>
         </init-param>
         <init-param>
            <param-type>class</param-type>
            <param-value>{class}</param-value>
         </init-param>
         <init-param>
            <param-type>bool</param-type>
            <param-value>true</param-value>
         </init-param>
      </init-params>
   </serializer>
</user-type>

カスタム・コーデックの提供

コーデックによって、シリアライズまたはデシリアライズの前後でコードを実行できます。コーデックでは、IPofWriterおよびIPofReaderインタフェースを使用して、移植可能なプロパティをエンコードおよびデコードする方法を定義できます。コーデックは、一般に、デシリアライズ中に消失する可能性がある実用的な実装に使用します。または、オブジェクトをシリアライズする前にIPofWriterインタフェースで特定のメソッドを明示的にコールするために使用します。

コーデックを作成するには、ICodecインタフェースを実装するクラスを作成します。次の例は、リンクされたリスト型の実用的な実装を定義するコーデックを示しています。

public class LinkedListCodec<T> : ICodec
{
   public object Decode(IPofReader reader, int index)
      {
         return reader.ReadCollection(index, (ICollection)new LinkedList<T>());
      }

   public void Encode(IPofWriter writer, int index, object value)
      {
         writer.WriteCollection(index, (ICollection)value);
      }
}

コーデックをプロパティに割り当てるには、コーデックを[PortableProperty]属性のメンバーとして入力します。コーデックを指定しない場合は、デフォルトのコーデック(DefaultCodec)が使用されます。次の例は、前述のLinkedListCodecコーデックの割当て方法を示しています。

[PortableProperty(typeof(LinkedListCodec<string>))]