ヘッダーをスキップ
Oracle Coherenceクライアント・ガイド
リリース3.5
B56041-01
  目次
目次

戻る
戻る
 
次へ
次へ
 

15 .NETクライアントの統合可能オブジェクトの構築

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

POFコンテキストの構成

POFでは、共通の.NET型およびJava型がすべてそのままサポートされます。カスタムの.NETクラスおよびJavaクラスもPOFストリームにシリアライズ可能ですが、そのためには次の追加手順が必要となります。

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

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

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

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

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

IPortableObject実装の作成(.NET)

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

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

例15-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
}

PortableObject実装の作成(Java)

Javaでの移植可能なクラスの実装は、前述の例に示した.NETでの実装と非常によく似ています。

例15-2は、例15-1の.NETクラスをJavaで実現した場合を示しています。

例15-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コンフィギュレーション・ファイルを使用してマッピング情報が格納されます。これを例15-3に示します。これらの要素の詳細は、「POFユーザー定義型の構成要素」を参照してください。

例15-3 POFユーザー定義型コンフィギュレーション・ファイルへのマッピング情報の格納

<?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より小さい数値は内部使用に予約されています。

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

型識別子とカスタム型の間のマッピングを構成したら、キャッシュ・コンフィギュレーション・ディスクリプタにserializer要素を追加して、それらのマッピングを使用するようCoherence for .NETを構成する必要があります。たとえば、例15-3に示したユーザー定義型のマッピングがmy-dotnet-pof-config.xmlに保存されている場合は、例15-4に示すようにserializer要素を指定する必要があります。

例15-4 キャッシュ・コンフィギュレーション・ファイルでのserializerの使用

<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>

POFシリアライザを明示的に指定しない場合は、ConfigurablePofContext型がPOFシリアライザとして使用されます。このシリアライザは、デフォルトのコンフィギュレーション・ファイル($AppRoot/coherence-pof-config.xml)を使用するか(存在する場合)、Coherence for .NETアプリケーション・コンフィギュレーション・ファイルのpof-config要素で特定されるファイルを使用します。次に例を示します。

例15-5 POFコンフィギュレーション・ファイルの指定

<?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>

詳細は、「Coherence for .NETクライアント・ライブラリの構成と使用」を参照してください。

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

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

クラスタ側のPOFコンフィギュレーション・ファイルは、クライアントで作成されたコンフィギュレーション・ファイルと似ています。唯一の違いは、class-name要素で.NETクラス名のかわりに完全修飾されたJavaクラス名を指定する必要がある点です。

例15-6は、クラスタ側のPOFコンフィギュレーション・ファイルのサンプル(my-java-pof-config.xml)を示しています。

例15-6 クラスタ側のPOFコンフィギュレーション・ファイル

<?xml version="1.0"?>
<!DOCTYPE pof-config SYSTEM "pof-config.dtd">
<pof-config>
  <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>
    </user-type>
    ...
  </user-type-list>
</pof-config>

カスタム型を追加したら、オブジェクトのシリアライズ時に各自のPOFコンフィギュレーション・ファイルが使用されるようサーバーを構成する必要があります。これを例15-7に示します。

例15-7 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型のバージョンよりも新しい場合にのみ存在します。

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

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

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インタフェースを実装することでクラスの進化をサポートするように変更できます。

例15-9 クラスの進化をサポートするように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)、あるいはその両方を作成することで、ユーザー定義型の移植可能なシリアライズを外部化できます。

例15-10は、.NET型のContactInfoIPofSerializerインタフェースの実装を示しています。

例15-10 .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インタフェースの実装は次のようになります。

例15-11 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のクラス名を指定します。これを例15-12に示します。

例15-12 .NET型のIPofSerializer実装の登録

<?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>
      <serializer>
        <class-name>My.Example.ContactInfoSerializer, MyAssembly</class-name>
      </serializer>
    </user-type>
      ...
  </user-type-list>
</pof-config>

同様に、Java型のContactInfoPofSerializer実装を登録できます。これを例15-13に示します。

例15-13 Java型のPofSerializer実装の登録

<?xml version="1.0"?>
<!DOCTYPE pof-config SYSTEM "pof-config.dtd">
<pof-config>
  <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>

.NETクライアント・ライブラリの構成と使用

.NETアプリケーションでCoherence for .NETライブラリを使用するには、Coherence.dllライブラリへの参照をプロジェクトに追加し、必要なコンフィギュレーション・ファイルを作成する必要があります。

Coherence.dllへの参照を作成する手順は次のとおりです。

  1. 作成したプロジェクトで「プロジェクト」→「参照の追加」を選択します。または「ソリューション エクスプローラ」の「参照設定」を右クリックして、「参照の追加」を選択します。

  2. 表示される「参照の追加」ウィンドウで「参照」タブを選択し、ファイル・システム上のCoherence.dllライブラリを探します。

    図15-1 「参照の追加」ウィンドウ

    この図については本文で説明しています。
  3. OK」をクリックします。

次に、必要なコンフィギュレーション・ファイルを作成し、そのパスをアプリケーション・コンフィギュレーション設定で指定する必要があります。そのためには、アプリケーション・コンフィギュレーション・ファイルをプロジェクトに追加し(まだ作成されていない場合)、Coherence for .NETのコンフィギュレーション・セクション(<coherence/>)をそのファイルに追加します。

例15-14 アプリケーション・コンフィギュレーション・ファイルのサンプル

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

Coherence for .NETのコンフィギュレーション・セクションの要素は次のとおりです。

図15-2は、コンフィギュレーション・ファイルを追加した後のソリューションを示しています。

図15-2 コンフィギュレーション・ファイルを表示しているファイル・システム

この図については本文で説明しています。

CacheFactory

CacheFactoryは、Coherence for .NETクライアント・アプリケーションのエントリ・ポイントです。CacheFactoryINamedCacheインスタンスのファクトリであり、ロギングのための様々なメソッドを提供します。CacheFactoryを明示的に構成していない場合は、アセンブリが埋め込まれたリソースであるデフォルトのコンフィギュレーション・ファイルcoherence.xmlが使用されます。このデフォルトのコンフィギュレーション・ファイルは無効にできます。そのためには、アプリケーション・コンフィギュレーション・ファイルのCoherence for .NETコンフィギュレーション・セクションにcache-factory-config要素を追加し、その値を目的のコンフィギュレーション・ファイルのパスに設定します。

例15-15 INamedCacheインスタンスのファクトリの構成

<?xml version="1.0"?>

<configuration>
  <configSections>
    <section name="coherence" type="Tangosol.Config.CoherenceConfigHandler, Coherence"/>
  </configSections>
  <coherence>
    <cache-factory-config>my-coherence.xml</cache-factory-config>
    ...
  </coherence>
</configuration>

このファイルには、CacheFactoryで静的なプロパティを使用して公開される次の2つのコンポーネントが構成されています。

  • CacheFactory.ConfigurableCacheFactory: CacheFactoryINamedCacheインスタンスの取得、解放および破棄に使用されるIConfigurableCacheFactory実装

  • CacheFactory.Logger: メッセージと例外を記録するために使用されるLoggerインスタンス

CacheFactoryの使用が終了したら(アプリケーションをシャットダウンする場合など)、Shutdown()メソッドを使用してCacheFactoryをシャットダウンする必要があります。このメソッドによって、すべてのサービスとLoggerインスタンスが終了します。

IConfigurableCacheFactory

IConfigurableCacheFactory実装は、<configurable-cache-factory-config>要素の内容で指定されます。

  • class-name: 実装タイプをそのアセンブリ修飾名で指定します。

  • init-params: IConfigurableCacheFactoryのインスタンス化に使用されるパラメータを定義します。各パラメータは、対応する子要素param-typeおよびparam-valueで指定されます。

例15-16 ConfigurableCacheFactory実装の構成

<coherence>
  <configurable-cache-factory-config>
    <class-name>Tangosol.Net.DefaultConfigurableCacheFactory, Coherence</class-name>
    <init-params>
      <init-param>
        <param-type>string</param-type>
        <param-value>simple-cache-config.xml</param-value>
      </init-param>
    </init-params>
  </configurable-cache-factory-config>
</coherence>

IConfigurableCacheFactory実装がコンフィギュレーションに定義されていない場合は、デフォルトの実装(DefaultConfigurableCacheFactory)が使用されます。

DefaultConfigurableCacheFactory

DefaultConfigurableCacheFactoryは、前述のキャッシュ・コンフィギュレーション・ディスクリプタ(「クライアント側のキャッシュ・コンフィギュレーション・ディスクリプタ」を参照)で宣言されているキャッシュにアクセスするための機能を提供します。DefaultConfigurableCacheFactoryで使用されるデフォルトのコンフィギュレーション・ファイルは$AppRoot/coherence-cache-config.xmlです。$AppRootは、作業ディレクトリ(Windowsフォーム・アプリケーションの場合)またはアプリケーションのルート(Webアプリケーションの場合)です。

別のキャッシュ・コンフィギュレーション・ディスクリプタ・ファイルを指定する場合は、アプリケーション・コンフィギュレーション・ファイルのCoherence for .NETコンフィギュレーション・セクションにcache-config要素を追加して、その値をコンフィギュレーション・ファイルのパスに設定します。

例15-17 別のキャッシュ・コンフィギュレーション・ディスクリプタ・ファイルの指定

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

Logger

Loggerは次のlogging-config要素を使用して構成します。

  • destination: Loggerで使用するLogOutputのタイプを指定します。有効な値は次のとおりです。

    • common-loggerCommon.Loggingの場合)

    • stderrConsole.Errorの場合)

    • stdoutConsole.Outの場合)

    • ファイル・パス(メッセージをファイルに送信する必要がある場合)

  • severity-level: メッセージをログに記録するために満たすか、または超過する必要のあるログ・レベルを決定します。

  • message-format: ログ・メッセージの書式を決定します。

  • character-limit: ログ出力デーモンがメッセージ・キューから処理する文字の最大数を決定します。この数を超過すると、キューに残っているメッセージがすべて破棄されます。

例15-18 Loggerの構成

<coherence>
  <logging-config>
    <destination>log4net</destination>
    <severity-level>5</severity-level>
    <message-format>(thread={thread}): {text}</message-format>
    <character-limit>8192</character-limit>
  </logging-config>
</coherence>

CacheFactoryは、INamedCacheのインスタンスを取得および解放する、次の静的メソッドを提供します。

  • GetCache(String cacheName): リモートのCoherenceクラスタ内で稼働する、指定されたcacheNameNamedCacheに対応するINamedCache実装を取得します。

  • ReleaseCache(INamedCache cache): キャッシュの指定のインスタンスに関連付けられているローカル・リソースをすべて解放します。解放したキャッシュは使用できなくなります。

  • DestroyCache(INamedCache cache): 指定されたキャッシュをCoherenceクラスタ全体で破棄します。

メッセージと例外を記録するためのメソッドは次のとおりです。

  • IsLogEnabled(int level): 指定された重大度のメッセージをLoggerで記録するかどうかを決定します。

  • Log(Exception e, int severity): 指定された重大度の例外を記録します。

  • Log(String message, int severity): 指定された重大度のテキスト・メッセージを記録します。

  • Log(String message, Exception e, int severity): 指定された重大度のテキスト・メッセージと例外を記録します。

ロギング・レベルはCacheFactory.LogLevelenumの値で定義されます(昇順)。

  • Always

  • Error

  • Warn

  • Info

  • Debug(デフォルトのログ・レベル)

  • Quiet

  • Max

Common.Loggingライブラリの使用

Common.Loggingは、明確に定義された一連のインタフェースの背後で、各種の一般的なオープンソース・ロギング・ライブラリをプラグインできるようにするオープンソース・ライブラリです。現在サポートされているライブラリは、Log4Net(バージョン1.2.9と1.2.10)およびNLogです。Common.Loggingは、現在Spring.NETフレームワークで使用されており、IBatis.NETおよびNHibernateの今後のリリースでも使用される可能性があります。このため、これらのフレームワークをCoherence for .NETと組み合せて使用している場合は、アプリケーション・レイヤー全体で一貫してロギングを構成できることから、Common.Loggingの使用を検討してください。

Coherence for .NETにはCommon.Loggingライブラリが含まれていません。Loggerコンフィギュレーションにcommon-loggerを使用する場合は、Common.Loggingアセンブリをダウンロードし、そのアセンブリへの参照をプロジェクトに組み込む必要があります。.NET 1.1用および2.0用のCommon.Loggingアセンブリは、次の場所からダウンロードできます。

http://netcommon.sourceforge.net/

Coherence for .NETのCommon.Logging Logger実装は、これらのアセンブリの署名付きリリース・バージョンに対してコンパイルされています。

INamedCache

INamedCacheインタフェースはIDictionaryを拡張するため、ディクショナリと同様に操作できます。取得したINamedCacheインスタンスでは、いくつかのプロパティが公開されます。

  • CacheName: キャッシュ名

  • Count: キャッシュ・サイズ

  • IsActive: キャッシュがアクティブ(つまり解放も破棄もされていない)かどうかを判定します。

  • Keys: キャッシュ・マッピング内のすべてのキーのコレクション

  • Values: キャッシュ・マッピング内のすべての値のコレクション

指定されたキーの値は、cache[key]を使用して取得できます。同様に、新しい値を追加したり、プロパティを新しい値に設定することで古い値を変更したりできます(cache[key] = value)。

キャッシュ・エントリのコレクションにアクセスするには、キャッシュ内のマッピングを反復処理するGetEnumerator()を使用します。

INamedCacheインタフェースは、キャッシュの内容を操作するための複数のメソッドを提供します。

  • Clear(): キャッシュからすべてのマッピングを削除します。

  • Contains(Object key): 指定されたキーのマッピングがキャッシュにあるかどうかを判定します。

  • GetAll(ICollection keys): 指定されたキー・コレクションにマップされているすべての値を返します。

  • Insert(Object key, Object value): キャッシュに新しいマッピングを挿入します。指定されたキーのマッピングがすでに存在する場合は、その値が指定された値で上書きされ、古い値が返されます。

  • Insert(Object key, Object value, long millis): キャッシュに新しいマッピングを挿入しますが、有効期限がミリ秒単位で指定されます。

  • InsertAll(IDictionary dictionary): 指定されたディクショナリのすべてのマッピングをキャッシュにコピーします。

  • Remove(Object key): 指定されたキーのマッピングが存在する場合はそれを削除し、そのキーがマップされていた値を返します。

INamedCacheインタフェースは、この他にIQueryCacheIObservableCacheおよびIInvocableCacheの3つのインタフェースを拡張します。

IQueryCache

IQueryCacheインタフェースは、様々なフィルタを使用してキャッシュを問い合せる機能を備えています。

  • GetKeys(IFilter filter): 対象のキャッシュに格納されているキーのうち、フィルタで表された基準を満たすエントリのキーのコレクションを返します。

  • GetEntries(IFilter filter): 対象のキャッシュに格納されているエントリのうち、フィルタで表された基準を満たすエントリのコレクションを返します。

  • GetEntries(IFilter filter, IComparer comparer): 対象のキャッシュに格納されているエントリのうち、フィルタで表された基準を満たすエントリのコレクションを返します。この場合、列挙子は必ずコレクションをエントリ値の昇順で横断します。エントリ値は指定されたcomparerでソートされているか、またはcomparerがnullの場合は自然な順序でソートされています。

さらにIQueryCacheインタフェースには、索引を追加または削除する機能があります。索引はキャッシュに格納されている値を対応するキーに関連付けるために使用され、GetKeysメソッドとGetEntriesメソッドのパフォーマンスを大幅に向上します。

  • AddIndex(IValueExtractor extractor, bool isOrdered, IComparer comparator): 指定されたIValueExtractorによって抽出された値を対応するエントリに対するキーに関連付ける索引を、対象のキャッシュに追加します。索引情報は順序付けることもできます。

  • RemoveIndex(IValueExtractor extractor): 対象のキャッシュから索引を削除します。

例15-19は、年齢プロパティの値が55以上であるすべてのエントリのキーを効率よく問い合せるコードを示しています。

例15-19 特定の値に関するキーの問合せ

IValueExtractor extractor = new ReflectionExtractor("getAge");

cache.AddIndex(extractor, true, null);
ICollection keys = cache.GetKeys(new GreaterEqualsFilter(extractor, 55));

IObservableCache

IObservableCacheインタフェースは、キャッシュの内容が変更されたときにアプリケーションがイベントを受信できるようにします。変更イベントに関心があることを登録するには、そのキャッシュに対するListener実装をアプリケーションで追加します。対象キャッシュでは、イベント・タイプ(挿入、更新、削除)、変更されたエントリのキー、およびエントリの古い値と新しい値などに関する情報を含むイベントが受信されます。

  • AddCacheListener(ICacheListener listener): キャッシュから発行されたすべてのイベント(挿入、更新、削除)を、そのキー、古い値および新しい値を含めて受信する標準のキャッシュ・リスナーを追加します。

  • RemoveCacheListener(ICacheListener listener): 以前に登録した標準のキャッシュ・リスナーを削除します。

  • AddCacheListener(ICacheListener listener, object key, bool isLite): 特定のキーに関するキャッシュ・リスナーを追加します。isLitetrueである場合は、イベントに古い値と新しい値が含まれないことがあります。

  • RemoveCacheListener(ICacheListener listener, object key): 指定されたキーを使用して以前に登録されたキャッシュ・リスナーを削除します。

  • AddCacheListener(ICacheListener listener, IFilter filter, bool isLite): フィルタの評価に基づいてイベントを受信するキャッシュ・リスナーを追加します。isLiteがtrueである場合は、イベントに古い値と新しい値が含まれないことがあります。

  • RemoveCacheListener(ICacheListener listener, IFilter filter): 指定されたフィルタを使用して以前に登録されたキャッシュ・リスナーを削除します。

フィルタベースのメソッドを使用して登録されたListenerは、すべてのイベント・タイプ(挿入、更新および削除)を受信します。イベントをさらにフィルタリングするには、CacheEventFilter内にフィルタをラップし、CacheEventMask列挙値を使用して監視対象とするイベントのタイプを指定します。

例15-20では、IsMarriedプロパティ値がtrueに設定されたEmployeeオブジェクトがキャッシュに挿入されると、フィルタがtrueに評価されます。

例15-20 挿入されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.Inserted, new EqualsFilter("IsMarried", true));

例15-21では、キャッシュからオブジェクトが1つでも削除されると、フィルタがtrueに評価されます。

例15-21 削除されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.Deleted);

例15-22では、EmployeeオブジェクトのLastNameプロパティがSmithから変更されると、フィルタthattrueに評価されます。

例15-22 変更されたオブジェクトに対するフィルタリング

new CacheEventFilter(CacheEventMask.UpdatedLeft, new EqualsFilter("LastName", "Smith"));

IInvocableCache

IInvocableCacheは、エントリ別処理と集計操作の両方の起動対象とすることができるキャッシュです。キャッシュの内容に対する操作は、キャッシュによって(したがって、特定の領域に制限されたキャッシュの内容の中で)実行できます。この機能は特に分散環境で役立ちます。これは、処理対象のエントリが管理されている場所に処理を移すことで、処理を局所化して効率を高めることができるためです。

  • Invoke(object key, IEntryProcessor agent): 渡されたキーで指定されるエントリに対して渡されたプロセッサを起動し、その起動の結果を返します。

  • InvokeAll(ICollection keys, IEntryProcessor agent): 渡されたキーで指定されるエントリに対して渡されたプロセッサを起動し、それぞれの起動の結果を返します。

  • InvokeAll(IFilter filter, IEntryProcessor agent): 指定されたフィルタで選択されるエントリに対して渡されたプロセッサを起動し、それぞれの起動の結果を返します。

  • Aggregate(ICollection keys, IEntryAggregator agent): 渡されたキーで指定されるエントリに対して集約操作を実行します。

  • Aggregate(IFilter filter, IEntryAggregator agent): 指定されたフィルタで選択されるエントリに対して集約操作を実行します。

フィルタ

IQueryCacheインタフェースは、IFilter実装を使用して表される、所定の基準を満たすキャッシュ・エントリを検索する機能を提供します。

すべてのフィルタはIFilterインタフェースを実装する必要があります。

  • Evaluate(object o): 指定されたオブジェクトにテストを適用し、テストに合格した場合はtrue、そうでない場合はfalseを返します。

Coherence for .NETでは、Tangosol.Util.FilterネームスペースにいくつかのIFilter実装が含まれています。

例15-23のコードでは、値が5であるすべてのエントリのキーが取得されます。

例15-23 ある数値と等しいキーの取得

EqualsFilter equalsFilter = new EqualsFilter(IdentityExtractor.Instance, 5);
ICollection  keys         = cache.GetKeys(equalsFilter);

例15-24のコードでは、値が55以上であるすべてのキーが取得されます。

例15-24 ある数値より大きいか、それと等しいキーの取得

GreaterEqualsFilter greaterEquals = new GreaterEqualsFilter(IdentityExtractor.Instance, 55);
ICollection         keys          = cache.GetKeys(greaterEquals);

例15-25のコードでは、値がBelgで始まるすべてのキャッシュ・エントリが取得されます。

例15-25 ある文字列値に基づいたキーの取得

LikeFilter  likeFilter = new LikeFilter(IdentityExtractor.Instance, "Belg%", '\\', true);
ICollection entries    = cache.GetEntries(likeFilter);

例15-26のコードでは、値がan(大文字と小文字を区別)で終わるか、またはAn(大文字と小文字の区別なし)で始まるすべてのキャッシュ・エントリを取得します。

例15-26 大文字と小文字を区別する文字列値に基づいたキーの取得

OrFilter    orFilter = new OrFilter(new LikeFilter(IdentityExtractor.Instance, "%an", '\\', false), new LikeFilter(IdentityExtractor.Instance, "An%", '\\', true));
ICollection entries  = cache.GetEntries(orFilter);

値エクストラクタ

エクストラクタは、オブジェクトから値を抽出するために使用されます。すべてのエクストラクタはIValueExtractorインタフェースを実装する必要があります。

  • Extract(object target): 渡されたオブジェクトから値を抽出します。

Coherence for .NETには次のエクストラクタがあります。

  • IdentityExtractor: 渡された値から何も抽出せず、その値そのものを返す単純な実装です。

  • KeyExtractor: 値ではなく主要なオブジェクトに対して問合せを実行する必要があることを示す、特殊な目的の実装です。

  • ReflectionExtractor: 指定したオブジェクトのプロパティから値を抽出します。

  • MultiExtractor: エクストラクタの配列に基づく複合的なIValueExtractor実装です。配列内のエクストラタはすべて同じターゲット・オブジェクトに適用され、抽出した値のIListが抽出結果となります。

  • ChainedExtractor: エクストラクタの配列に基づく複合的なIValueExtractor実装です。配列内のエクストラクタは左から右に順次適用され、前のエクストラクタの結果が次のエクストラクタのターゲット・オブジェクトとなります。

例15-27のコードでは、キーの値が5より大きいすべてのキャッシュ・エントリが取得されます。

例15-27 ある数値より大きいキャッシュ・エントリの取得

IValueExtractor extractor = new KeyExtractor(IdentityExtractor.Instance);
IFilter         filter    = new GreaterFilter(extractor, 5);
ICollection     entries   = cache.GetEntries(filter);

例15-28のコードでは、値のCityプロパティがcity1と等しいすべてのキャッシュ・エントリが取得されます。

例15-28 ある文字列値に基づいたキャッシュ・エントリの取得

IValueExtractor extractor = new ReflectionExtractor("City");
IFilter         filter    = new EqualsFilter(extractor, "city1");
ICollection     entries   = cache.GetEntries(filter);

入力プロセッサ

入力プロセッサは、キャッシュ内のエントリ・オブジェクトに対して作動する起動可能なエージェントです。

すべての入力プロセッサはIEntryProcessorインタフェースを実装する必要があります。

  • Process(IInvocableCacheEntryエントリ): 指定されたエントリを処理します。

  • ProcessAll(ICollectionエントリ): エントリのコレクションを処理します。

Coherence for .NETでは、Tangosol.Util.ProcessorネームスペースにいくつかのIEntryProcessor実装が含まれています。

例15-29のコードは、条件付設定を示しています。key1に現在マップされている値が600より大きい場合にのみ、この値が680に設定されます。

例15-29 ある数値に基づいたキー値の条件付設定

IFilter         greaterThen600 = new GreaterFilter(IdentityExtractor.Instance, 600);
IEntryProcessor processor      = new ConditionalPut(greaterThen600, 680);
cache.Invoke("key1", processor);

例15-30のコードでは、キーがBGDであるTemperatureオブジェクトに対し、UpdaterProcessorを使用してそのオブジェクトのDegreeプロパティを新しい値26に更新します。

例15-30 ある数値に基づいたキー値の設定

cache.Insert("BGD", new Temperature(25, 'c', 12));
IValueUpdater   updater   = new ReflectionUpdater("setDegree");
IEntryProcessor processor = new UpdaterProcessor(updater, 26);
object          result    = cache.Invoke("BGD", processor);

入力アグリゲータ

入力アグリゲータは、IInvocableCacheにあるエントリの一部のサブセットに対して実行し、集計結果を得るように指定できる処理を表します。集計の一般的な例として、最小、最大、合計、平均などの関数があります。ただし、集計の概念は、エントリのグループを評価して1つの答えを算出する必要のある任意のプロセスに適用されます。集計は、分散環境などで並列に実行する機能を明示的に備えています。

すべてのアグリゲータはIEntryAggregatorインタフェースを実装する必要があります。

  • Aggregate(ICollectionエントリ): エントリのコレクションを処理して集約結果を生成します。

Coherence for .NETでは、Tangosol.Util.AggregatorネームスペースにいくつかのIEntryAggregator実装が含まれています。

例15-31のコードでは、キャッシュのサイズが返されます。

例15-31 キャッシュのサイズを返す

IEntryAggregator aggregator = new Count();
object           result     = cache.Aggregate(cache.Keys, aggregator);

例15-32のコードでは、キャッシュ内の一意の値と等しいキーを持ち、かつキャッシュ内の対応する値のインスタンス数と等しい値を持つIDictionaryが返されます。

例15-32 IDictionaryを返す

IEntryAggregator aggregator = GroupAggregator.CreateInstance(IdentityExtractor.Instance, new Count());
object           result     = cache.Aggregate(cache.Keys, aggregator);

注意:

例15-31および例15-32は簡単な例にすぎず、大量のキーやサイズがきわめて大きいキーを渡す用途には実用的ではありません。そのような用途では、GroupAggregator.CreateInstance(String, IEntryAggregator, IFilter)メソッドを使用してAlwaysFilterオブジェクトを渡します。

キャッシュした値オブジェクト同様、IFilterIExtractorIProcessorおよびIAggregatorのすべてのカスタム実装クラスは、.NETアプリケーションのPOFコンテキストおよびクライアントが接続されているクラスタ側ノードのPOFコンテキストに正しく登録する必要があります。したがって、カスタムの.NET型の対応するJava実装を、クラスタ側ノードで作成、コンパイルおよびデプロイする必要があります。このようなカスタム型を実際に実行するのは、.NETの実装ではなくJavaの実装であることに注意してください。

詳細は、「POFコンテキストの構成」を参照してください。

CoherenceのDefaultCacheServerプロセスの起動

すでに説明したクラスタ側のCoherenceキャッシュ・コンフィギュレーションを使用するDefaultCacheServerを起動し、TCP/IPを使用してCoherence for .NETクライアントをCoherenceクラスタに接続できるようにするには、次の手順を実行する必要があります。

  1. 現在のディレクトリをOracle Coherenceのライブラリ・ディレクトリに変更します(Windowsの場合は%COHERENCE_HOME%\lib、UNIXの場合は$COHERENCE_HOME/lib)。

  2. Javaコマンドが実行されるようにパスを構成します。

  3. DefaultCacheServerコマンドライン・アプリケーションを起動します。その際に、-Dtangosol.coherence.cacheconfigシステム・プロパティを、すでに説明したクラスタ側Coherenceキャッシュ・コンフィギュレーション・ディスクリプタの場所に設定します。

例15-33にコマンドラインのサンプルを示します。

例15-33 Coherenceのデフォルト・キャッシュ・サーバーを起動するコマンド

java -cp coherence.jar -Dtangosol.coherence.cacheconfig=file://<path to the server-side cache configuration descriptor> com.tangosol.net.DefaultCacheServer