この章では、キャッシュ内にある複合オブジェクトを操作します。Eclipseを使用して新しいContactクラスを作成し、Portable Object Format(POF)シリアライズを使用してキャッシュにContactオブジェクトを格納し、格納したオブジェクトを取得します。
この章では次の項について説明します。
これまで、NamedCacheキャッシュでStringオブジェクトを値として挿入および取得してきました。Coherence Java APIのgetメソッドおよびputメソッドの実装の多くでは、値とキーをObjectタイプとして定義します。次に例を示します。
public java.lang.Object get(java.lang.Object oKey) public void put(java.lang.Object oKey, java.lang.Object oValue)
どのオブジェクトも値またはキーとして使用できます。これにより、複合オブジェクトを値としてキャッシュに格納できます。
Coherenceではオブジェクトをワイヤ経由で送信することがあるため、オブジェクトはシリアライズ可能である必要があります。オブジェクトのシリアライズは、オブジェクトの状態を一連のバイトとして保存し、その後、バイトを再ビルド(デシリアライズ)してアクティブなオブジェクトにするプロセスです。たとえば、java.io.Serializableインタフェースを実装するオブジェクトはシリアライズ可能です。
Javaのjava.io.Serializableインタフェースを使用するかわりに、高性能のシリアライズを目的としたCoherence独自のクラスcom.tangosol.io.pof.PortableObjectを使用することによってパフォーマンスを向上させることができます。 PortableObject形式は、標準のSerializableと比べると速度が最大6倍で、シリアライズ後の結果セットは小さくなります。
PortableObjectインタフェースにはreadExternalおよびwriteExternalという2つの単純なメソッドが用意されており、提供されているPofReaderストリームおよびPofWriterストリームからそれぞれ、シリアライズされたオブジェクト属性の読取りと書込みを明示的に行うことができます。シリアライズ形式を制御することによって、Coherenceではプロセスのパフォーマンスを向上させることができます。POFを使用すると、生成されるバイナリ・ファイルのサイズが縮小されます。多くの場合、バイナリ・ファイルのサイズは5分の1 - 10分の1になり、バイナリ・ファイルとの間の変換速度は、オブジェクトのサイズに応じて5 - 20倍になることがあります。
この演習では、従業員の名前、住所、誕生日および電話番号を格納するContactオブジェクトを作成します。また、POFシリアライズを使用して、PortableObjectインタフェースを実装することによりキャッシュにオブジェクトを挿入し、挿入したオブジェクトを取得します。
ここでは、後で別のデータ・オブジェクトに組み込まれる2つのデータ・オブジェクトの作成方法について説明します。Addressオブジェクトは従業員の住所情報を提供し、PhoneNumberオブジェクトは電話連絡先情報を提供します。
従業員の住所情報を格納するAddressオブジェクトを作成します。
Eclipseで、Contactsという新しいアプリケーション・クライアント・プロジェクトを作成します。開始ページの「Configuration」フィールドでCoherenceConfigが選択されていることと、「Application Client module」ページで「Create a default main」が選択されていないことを確認します。
詳細は、「Eclipse IDEでの新規プロジェクトの作成」を参照してください。
Addressという新しいJavaクラスを作成します。「Default Package」がcom.oracle.handsonであることを確認します。「Main Method」チェック・ボックスは選択しないでください。詳細は、「Javaクラスの作成」を参照してください。
データのシリアライズにPortableObjectインタフェースを使用するようにクラスを記述します。Eclipseコード・エディタで、生成したAddressクラスを、com.tangosol.io.pof.PortableObjectを実装するように変更します。PortableObjectインタフェースのimport文を追加します。
PortableObjectインタフェースで必要なcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectインタフェースで必要なAddressのパブリックなデフォルト・コントラクタを追加します。
Addressクラスの次のプライベート属性を入力します。必要に応じて他の属性を追加することもできます。
— String Street1
— String Street2
— String City
— String State
— String Country
この時点で、Addressクラスは次のようになります。
package com.oracle.handson;
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PortableObject;
import com.tangosol.io.pof.PofWriter;
import java.io.IOException;
public class Address  implements PortableObject 
{
           private String Street1;
           private String Street2;
           private String City;
           private String State;
           private String Zip;
           private String Country;
    /**
    * Default constructor (necessary for PortableObject implementation).    */ 
    public Address()
        {
        }
}
Eclipseでは、作成した属性についてデフォルトのgetメソッドおよびsetメソッドを生成できます。「Source」メニューから、「Generate Getters and Setters」を選択します。「Select All」をクリックして、クラス内のすべての属性を選択します。すべての属性が自動的に選択されます。「OK」をクリックして続行します。
図4-1に、Addressクラスのアクセッサを生成する「Generate Getters and Setters」ダイアログ・ボックスを示します。
デフォルトのコンストラクタおよびequalsメソッドを自動的に生成することもできます。「Source」メニューから、「Generate Constructor using Fields」を選択し、「Select All」をクリックして、「OK」をクリックします。
図4-2に、Street1、Street2、City、State、ZipおよびCountryの各フィールドを選択した「Generate Constructor using Fields」ダイアログ・ボックスを示します。
図4-2 「Generate Constructors using Fields」ダイアログ・ボックス

生成されたコンストラクタのメンバーにthisを追加します。生成されたコンストラクタは次のようになります。
    public Address(String Street1, String Street2, String City, String State, String Zip, String Country) {
        super();
        this.Street1 = Street1;
        this.Street2 = Street2;
        this.City = City;
        this.State = State;
        this.Zip = Zip;
        this.Country = Country;
    }
PortableObjectインタフェースでの必要に応じて、readExternalメソッドおよびwriteExternalメソッドを実装します。たとえば、readExternalメソッドを次のように実装すると、street、city、stateおよびcountryの値をPOFオブジェクトとして読み取ることができます。
public void readExternal(PofReader reader)
        throws IOException
     {
     setStreet1(reader.readString(0));
     setStreet2(reader.readString(1));
     setCity(reader.readString(2));
     setState(reader.readString(3));
     setZip(reader.readString(4));
     setCountry(reader.readString(5));
} 
 
equals、hashCodeおよびtoStringの各オブジェクト・メソッドを実装します。
| 注意:キャッシュのキーと値は、シリアライズ可能(たとえば、 java.io.Serializable)である必要があります。さらに、キャッシュ・キーはhashCode()メソッドとequals()メソッドの実装を提供する必要があり、これらのメソッドはクラスタ・ノード間で一貫性のある結果を返す必要があります。これは、hashCode()およびequals()の実装は、オブジェクトのシリアライズ可能な状態(つまり、オブジェクトの一時的でないフィールド)にのみ基づいている必要があることを示しています。String、Integer、Dateなどのほとんどの組込みのJava型はこの要件を満たしています。一部のキャッシュの実装(特にパーティション・キャッシュ)では、等価の検証にキー・オブジェクトのシリアライズされた形式を使用します。つまり、equals()メソッドでtrueを返すキーは、同様の方法でシリアライズされる必要があります。ほとんどの組込みのJava型はこの要件を満たしています。 | 
これらのメソッドをサポートするには、com.tangosol.util.Baseクラスとcom.tangosol.util.HashHelperクラスをインポートします。Baseクラスは、equalsメソッドのサポートを提供します。HashHelperクラスには、任意のグループのJava組込み関数のハッシュ・コード値を計算するためのヘルパー関数が格納されています。
次のコードは、equals()メソッドの実装例を示しています。
    public boolean equals(Object oThat)
        {
        if (this == oThat)
            {
            return true;
            }
        if (oThat == null)
            {
            return false;
            }
 
        Address that = (Address) oThat;
        return Base.equals(getStreet1(), that.getStreet1()) &&
               Base.equals(getStreet2(), that.getStreet2()) &&
               Base.equals(getCity(),    that.getCity())    &&
               Base.equals(getState(),   that.getState())   &&
               Base.equals(getZip(),     that.getZip())     &&
               Base.equals(getCountry(), that.getCountry());
        }
     
次のコードは、hashCode()メソッドの実装例を示しています。
    public int hashCode()
        {
        return HashHelper.hash(getStreet1(),
               HashHelper.hash(getStreet2(),
               HashHelper.hash(getZip(), 0)));
        }
次のコードは、toString()メソッドの実装例を示しています。
    public String toString()
        {
        return  getStreet1() + "\n" +
                getStreet2() + "\n" +
                getCity() + ", " + getState() + " "  + getZip() + "\n" +
                getCountry();
        }
作成されたクラスは例4-1のようになります。
例4-1 Addressクラスの実装
package com.oracle.handson;
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PortableObject;
import com.tangosol.io.pof.PofWriter;
 
import com.tangosol.util.Base;
import com.tangosol.util.HashHelper;
 
import java.io.IOException;
 
public class Address  implements PortableObject 
           {
           private String Street1;
           private String Street2;
           private String City;
           private String State;
           private String Zip;
           private String Country;
    /**
    * Default constructor (necessary for PortableObject implementation).
    */
    public Address() {
        }
 
    public Address(String Street1, String Street2, String City, String State,
                   String Zip, String Country) 
       {
        super();
        this.Street1 = Street1;
        this.Street2 = Street2;
        this.City    = City;
        this.State   = State;
        this.Zip     = Zip;
        this.Country = Country;
    }
  
    //------------ accessors--------------------------------
  
    public void setStreet1(String Street1) 
        {
        this.Street1 = Street1;
        }
 
    public String getStreet1() 
        {
        return Street1;
        }
 
    public void setStreet2(String Street2) 
        {
        this.Street2 = Street2;
        }
 
    public String getStreet2() 
        {
        return Street2;
        }
 
    public void setCity(String City)  
        {
        this.City = City;
        }
 
    public String getCity() 
        {
        return City;
        }
 
    public void setState(String State) 
        {
        this.State = State;
        }
 
    public String getState()  
        {
        return State;
        }
 
    public void setZip(String Zip) 
        {
        this.Zip = Zip;
        }
 
    public String getZip() 
        {
        return Zip;
        }
 
    public void setCountry(String Country) 
        {
        this.Country = Country;
        }
 
    public String getCountry() 
        {
        return Country;
        }
   // -------- PortableObject Interface------------------------------
    
    public void readExternal(PofReader reader)
            throws IOException
        {
        setStreet1(reader.readString(0));
        setStreet2(reader.readString(1));
        setCity(reader.readString(2));
        setState(reader.readString(3));
        setZip(reader.readString(4));
        setCountry(reader.readString(5));
        }
 
    public void writeExternal(PofWriter writer)
            throws IOException
        {
        writer.writeString(0, getStreet1());
        writer.writeString(1, getStreet2());
        writer.writeString(2, getCity());
        writer.writeString(3, getState());
        writer.writeString(4, getZip());
        writer.writeString(5, getCountry());
        }
    // ----- Object methods --------------------------------------------------
 
    
    public boolean equals(Object oThat)
        {
        if (this == oThat)
            {
            return true;
            }
        if (oThat == null)
            {
            return false;
            }
 
        Address that = (Address) oThat;
        return Base.equals(getStreet1(), that.getStreet1()) &&
               Base.equals(getStreet2(), that.getStreet2()) &&
               Base.equals(getCity(),    that.getCity())    &&
               Base.equals(getState(),   that.getState())   &&
               Base.equals(getZip(),     that.getZip())     &&
               Base.equals(getCountry(), that.getCountry());
        }
 
    
    public int hashCode()
        {
        return HashHelper.hash(getStreet1(),
               HashHelper.hash(getStreet2(),
               HashHelper.hash(getZip(), 0)));
        }
 
    
    public String toString()
        {
        return  getStreet1() + "\n" +
                getStreet2() + "\n" +
                getCity() + ", " + getState() + " "  + getZip() + "\n" +
                getCountry();
        }
}
電話連絡先データを格納するPhoneNumberクラスを作成します。
PhoneNumberという新しいJavaクラスを作成します。mainメソッドは含めないでください。
詳細は、「Javaクラスの作成」を参照してください。
データのシリアライズにPortableObjectインタフェースを使用します。Eclipseコード・エディタで、生成したPhoneNumberクラスを、PortableObjectを実装するように変更します。com.tangosol.io.pof.PortableObjectインタフェースのimport文を追加します。
PortableObjectインタフェースで必要なcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectインタフェースで必要なPhoneNumberクラスのパブリックなデフォルト・コントラクタを追加します。
PhoneNumberクラスの次のプライベート属性を入力します。他の属性を追加することもできます。
—short AccessCode
—short CountryCode
—short AreaCode
—int LocalNumber
Eclipseでは、作成した属性についてデフォルトのgetメソッドおよびsetメソッドを生成できます。「Source」メニューから、「Generate Getters and Setters」を選択します。「Select All」をクリックして、クラス内のすべての属性を選択します。すべての属性が自動的に選択されます。「OK」をクリックして続行します。
デフォルトのコンストラクタおよびequalsメソッドを自動的に生成することもできます。「Source」メニューから、「Generate Constructor using Fields」を選択し、「Select All」をクリックして、「OK」をクリックします。
生成されたコンストラクタのメンバーにthisを追加します。生成されたコンストラクタは次のようになります。
public PhoneNumber(short AccessCode, short CountryCode, short AreaCode,
             int LocalNumber) {
    super();
    this.AccessCode = AccessCode;
    this.CountryCode = CountryCode;
    this.AreaCode = AreaCode;
    this.LocalNumber = LocalNumber; 
    }
PortableObjectインタフェースでの必要に応じて、readExternalメソッドおよびwriteExternalメソッドを実装します。
equals、hashCodeおよびtoStringの各オブジェクト・メソッドを実装します。
作成されたクラスは例4-2のようになります。
例4-2 PhoneNumberクラスの実装
package com.oracle.handson;
 
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;
 
import com.tangosol.util.HashHelper;
 
import java.io.IOException;
 
public class PhoneNumber implements PortableObject 
{
    
    private short AccessCode;
    private short CountryCode;
    private short AreaCode;
    private int LocalNumber;
    
    //------------ constructors --------------------------------
    /**
    * Default constructor (necessary for PortableObject implementation).
    */
    public PhoneNumber() {
    }
 
    public PhoneNumber(short AccessCode, short CountryCode, short AreaCode,
                 int LocalNumber) 
        {
        super();
        this.AccessCode = AccessCode;
        this.CountryCode = CountryCode;
        this.AreaCode = AreaCode;
        this.LocalNumber = LocalNumber;
        }
 
    //------------ accessors--------------------------------
 
    public void setAccessCode(short AccessCode) 
        {
        this.AccessCode = AccessCode;
        }
 
    public short getAccessCode() 
        {
        return AccessCode;
        }
 
    public void setCountryCode(short CountryCode) 
        {
        this.CountryCode = CountryCode;
        }
 
    public short getCountryCode() 
        {
        return CountryCode;
        }
 
    public void setAreaCode(short AreaCode) 
        {
        this.AreaCode = AreaCode;
        }
 
    public short getAreaCode() 
        {
        return AreaCode;
        }
 
    public void setLocalNumber(int LocalNumber) 
        {
        this.LocalNumber = LocalNumber;
        }
 
    public int getLocalNumber() 
       {
        return LocalNumber;
        }
    // -------- PortableObject Interface------------------------------
    
    public void readExternal(PofReader reader)
            throws IOException
        {
        setAccessCode(reader.readShort(0));
        setCountryCode(reader.readShort(1));
        setAreaCode(reader.readShort(2));
        setLocalNumber(reader.readInt(3));
        }
 
    
    public void writeExternal(PofWriter writer)
            throws IOException
        {
        writer.writeShort(0, getAccessCode());
        writer.writeShort(1, getCountryCode());
        writer.writeShort(2, getAreaCode());
        writer.writeInt(3, getLocalNumber());
        }   
    // ----- Object methods -------------------------------------------------
 
    /**
    * {@inheritDoc}
    */
    public boolean equals(Object oThat)
        {
        if (this == oThat)
            {
            return true;
            }
        if (oThat == null)
            {
            return false;
            }
 
        PhoneNumber that = (PhoneNumber) oThat;
        return getAccessCode()  == that.getAccessCode()  &&
               getCountryCode() == that.getCountryCode() &&
               getAreaCode()    == that.getAreaCode()    &&
               getLocalNumber() == that.getLocalNumber();
        }
 
    /**
    * {@inheritDoc}
    */
    public int hashCode()
        {
        return HashHelper.hash(getAreaCode(),
               HashHelper.hash(getLocalNumber(), 0));
        }
 
    /**
    * {@inheritDoc}
    */
    public String toString()
        {
        return "+" + getAccessCode() + " " + getCountryCode() + " "
                   + getAreaCode()   + " " + getLocalNumber();
        }
}
Contactオブジェクトは、Addressデータ・オブジェクトとPhoneNumberデータ・オブジェクトを組み込むことによって、従業員の名前、住所および電話番号の情報を提供します。
Contactという新しいJavaクラスを作成します。mainメソッドは含めないでください。
詳細は、「Javaクラスの作成」を参照してください。
このクラスではデータのシリアライズにPortableObjectインタフェースを使用するため、Eclipseコード・エディタで、生成したContactクラスを、PortableObjectを実装するように変更します。com.tangosol.io.pof.PortableObjectインタフェースのimport文を追加します。
PortableObjectで必要なcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectで必要なContactのパブリックなデフォルト・コントラクタを追加します。
Contactクラスの次のプライベート属性を入力します。他の属性を追加することもできます。
String FirstName
String LastName
Address HomeAddress
Address WorkAddress
Map TelephoneNumbers
java.sql.Date BirthDate
Eclipseでは、作成した属性についてデフォルトのgetメソッドおよびsetメソッドを生成できます。「Source」メニューから、「Generate Getters and Setters」を選択します。「Select All」をクリックして、クラス内のすべての属性を選択します。「OK」をクリックして続行します。
従業員の年齢を計算するアクセッサgetAgeを作成します。
public int getAge()
        {
        return (int) ((System.currentTimeMillis() - BirthDate.getTime()) /  MILLIS_IN_YEAR);  
        }
MILLIS_IN_YEARの定義を追加します。
public static final long MILLIS_IN_YEAR = 1000L * 60L * 60L * 24L * 365L;
デフォルトのコンストラクタを自動的に生成できます。「Source」メニューから、「Generate Constructor using Fields」を選択し、「Select All」をクリックして、「OK」をクリックします。
生成されたコンストラクタは次のようになります。
public Contact(String FirstName, String LastName, Address HomeAddress,
               Address WorkAddress, Map TelephoneNumbers, Date BirthDate) {
    super();
    this.FirstName = FirstName;
    this.LastName = LastName;
    this.HomeAddress = HomeAddress;
    this.WorkAddress = WorkAddress;
    this.TelephoneNumbers = TelephoneNumbers;
    this.BirthDate = BirthDate;
} 
PortableObjectインタフェースでの必要に応じて、readExternalメソッドおよびwriteExternalメソッドを実装します。
equals、hashCodeおよびtoStringの各オブジェクト・メソッドを実装します。
作成されたクラスは例4-3のようになります。
例4-3 Contactクラスのサンプル
package com.oracle.handson;
import com.tangosol.io.pof.PortableObject;
 
import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
 
import java.io.IOException;
 
import java.sql.Date;
 
import java.util.Iterator;
import java.util.Map;
 
public class Contact implements PortableObject
       {
       private String FirstName;
       private String LastName;
       private Address HomeAddress;
       private Address WorkAddress;
       private Map TelephoneNumbers;
       private java.sql.Date BirthDate;
    
    // ----- constructors ---------------------------------------------------
 
    /**
    * Default constructor (necessary for PortableObject implementation).
    */
    public Contact()
        {
        }
 
    public Contact(String FirstName, String LastName, Address HomeAddress,
                   Address WorkAddress, Map TelephoneNumbers, Date BirthDate) 
        {
        super();
        this.FirstName = FirstName;
        this.LastName = LastName;
        this.HomeAddress = HomeAddress;
        this.WorkAddress = WorkAddress;
        this.TelephoneNumbers = TelephoneNumbers;
        this.BirthDate = BirthDate;
        }
    
    // -------- accessors --------------------------------------------
 
    public void setFirstName(String FirstName) 
        {
        this.FirstName = FirstName;
        }
 
    public String getFirstName() 
        {
        return FirstName;
        }
 
    public void setLastName(String LastName) 
        {
        this.LastName = LastName;
        }
 
    public String getLastName() 
        {
        return LastName;
        }
 
    public void setHomeAddress(Address HomeAddress) 
        {
        this.HomeAddress = HomeAddress;
        }
 
    public Address getHomeAddress() 
        {
        return HomeAddress;
        }
 
    public void setWorkAddress(Address WorkAddress) 
        {
        this.WorkAddress = WorkAddress;
        }
 
    public Address getWorkAddress() 
        {
        return WorkAddress;
        }
 
    public void setTelephoneNumbers(Map TelephoneNumbers) 
        {
        this.TelephoneNumbers = TelephoneNumbers;
        }
 
    public Map getTelephoneNumbers() 
        {
        return TelephoneNumbers;
        }
 
    public void setBirthDate(Date BirthDate) 
        {
        this.BirthDate = BirthDate;
        }
 
    public Date getBirthDate() 
        {
        return BirthDate;
        }
    /**
    * Get age.
    *
    * @return age
    */
    public int getAge()
        {
        return (int) ((System.currentTimeMillis() - BirthDate.getTime()) /
                MILLIS_IN_YEAR);
        }
 
 
    // ----- PortableObject interface ---------------------------------------
 
    /**
    * {@inheritDoc}
    */
    public void readExternal(PofReader reader)
            throws IOException
        {
        setFirstName(reader.readString(0));
        setLastName(reader.readString(1));
        setHomeAddress((Address) reader.readObject(2));
        setWorkAddress((Address) reader.readObject(3));
        setTelephoneNumbers(reader.readMap(4, null));
        setBirthDate(new Date(reader.readLong(5)));
        }
 
    /**
    * {@inheritDoc}
    */
    public void writeExternal(PofWriter writer)
            throws IOException
        {
        writer.writeString(0, getFirstName());
        writer.writeString(1, getLastName());
        writer.writeObject(2, getHomeAddress());
        writer.writeObject(3, getWorkAddress());
        writer.writeMap(4, getTelephoneNumbers());
        writer.writeLong(5, getBirthDate().getTime());
        }
 
 
    // ----- Object methods -------------------------------------------------
 
    /**
    * {@inheritDoc}
    */
    public String toString()
        {
        StringBuffer sb = new StringBuffer(getFirstName())
                .append(" ")
                .append(getLastName())
                .append("\nAddresses")
                .append("\nHome: ").append(getHomeAddress())
                .append("\nWork: ").append(getWorkAddress())
                .append("\nTelephone Numbers");
 
        for (Iterator iter = TelephoneNumbers.entrySet().iterator();
             iter.hasNext(); )
            {
            Map.Entry entry = (Map.Entry) iter.next();
            sb.append("\n")
               .append(entry.getKey()).append(": ").append(entry.getValue());
            }
        return sb.append("\nBirth Date: ").append(getBirthDate()).toString();
        }
    /**
    * Approximate number of millis in a year ignoring things such as leap
    * years. Suitable for example use only.
    */
    public static final long MILLIS_IN_YEAR = 1000L * 60L * 60L * 24L * 365L;
 
}
Contactエントリをキャッシュに挿入し、挿入したエントリを取得する、ContactDriverというドライバ・クラスを作成します。
Contactsプロジェクト内にContactDriverという新しいJavaクラスを作成します。mainメソッドを含むようにしてください。
詳細は、「Javaクラスの作成」を参照してください。
ContactDriverクラスで、contactという新しいNamedCacheを作成し、Contactオブジェクトの新しいインスタンスを挿入します。キャッシュからContactオブジェクトを取得し、2つのオブジェクトが同一であることを確認します。例4-4は、このクラスの実装例を示しています。
例4-4 ContactDriverクラスのサンプル
package com.oracle.handson;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
import java.sql.Date;
import java.util.Map;
import java.util.HashMap;
public class ContactDriver {
    public ContactDriver() 
    {
    }
            
    public static void main(String[] args) {
       NamedCache contact = CacheFactory.getCache("contact");
           
       Address homeAddress = new Address ("4157 Wash Ave", "Suite 4",    
                                    "Burlingame", "CA", "94407", "USA");
       Address workAddress = new Address ("500 Oracle Pkwy", "MS989", 
                                    "Redwood Shores", "CA", "94065", "USA");
       Date date = new Date(2009, 04, 01);
       PhoneNumber phonenumber = new PhoneNumber ((short)11, (short)650, (short)506, 7000);
       Map map = new HashMap();
       map.put("home", phonenumber);
               
       Contact con1 = new Contact("Tom", "Dunn", homeAddress, workAddress, 
                                      map, date);
       contact.put(con1.getFirstName(),con1);
 
       Contact con2 = (Contact)contact.get(con1.getFirstName());
       if (con2.getFirstName().equals(con1.getFirstName())) 
       {
       System.out.println("They are the same!!");
       } 
    }
}
POFシリアライズを使用するには、ユーザー定義オブジェクトをPOF構成ファイルに登録する必要があります。この構成によって、ユーザー定義オブジェクトのクラスが数値に関連付けられます。また、POFシリアライズおよびPOF構成ファイル名をキャッシュ構成ファイルで指定する必要があります。
Contactオブジェクト、AddressオブジェクトおよびPhoneNumberオブジェクトのPOF構成ファイルを作成します。
独自のデータ型のPOF構成ファイルを作成するには、プロジェクトで作成したpof-config.xmlファイルを使用します。
Contactオブジェクト、AddressオブジェクトおよびPhoneNumberオブジェクトの<user-type>要素を定義し、これらに型ID1001、1002および1003を割り当てて、完全なクラス名を指定します。このファイルには、Coherenceデータ型の最初の1000個のIDを予約するcoherence-pof-config.xmlファイルが含まれている必要があります。
Project Explorerでファイル名を変更し、contacts-pof-config.xmlとして保存します(このファイルはC:\home\oracle\workspace\Contacts\appClientModuleフォルダに保存されます)。例4-5に、contacts-pof-config.xmlファイルのサンプルを示します。
例4-5 POF構成ファイル
<?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>
    <!-- coherence POF user types -->
    <include>coherence-pof-config.xml</include>
    <!-- com.tangosol.examples package -->
    <user-type> 
      <type-id>1001</type-id> 
      <class-name>com.oracle.handson.Contact</class-name> 
    </user-type> 
    <user-type> 
      <type-id>1002</type-id> 
      <class-name>com.oracle.handson.Address</class-name> 
    </user-type> 
    <user-type> 
        <type-id>1003</type-id> 
      <class-name>com.oracle.handson.PhoneNumber</class-name> 
    </user-type> 
  </user-type-list>
  <allow-interfaces>true</allow-interfaces>
  <allow-subclasses>true</allow-subclasses>
</pof-config>
キャッシュ構成ファイルを作成します。Project Explorerでcoherence-cache-config.xmlファイルを使用できます。このファイルはcoherence-cache-config.xsdファイルに基づいています。また、coherence.jarファイルにcoherence-cache-config.xmlのコピーがあります。
scheme-nameとしてExamplesPartitionedPocSchemeを、service-nameとしてPartitionedPofCacheを使用します。
serializerセクションでは、POFシリアライズ・オブジェクトを適切なシリアライズ・ルーチン(PofSerializer、またはPortableObjectインタフェースを介したコールによる)にマップします。この場合は、com.tangosol.io.pof.ConfigurablePofContextクラスを使用します。
<init-param>セクションで、POF構成ファイルの名前(この場合はcontacts-pof-config.xml)を指定します。
Project Explorerでファイル名を変更し、contacts-cache-config.xmlとして保存します(このファイルはC:\home\oracle\workspace\Contacts\appClientModuleフォルダに保存されます)。例4-6に、contacts-cache-config.xmlファイルのサンプルを示します。
例4-6 キャッシュ構成ファイル
<?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 coherence-cache-config.xsd">
  <caching-scheme-mapping>
    <cache-mapping>
      <cache-name>*</cache-name>
      <scheme-name>ExamplesPartitionedPofScheme</scheme-name>
    </cache-mapping>
  </caching-scheme-mapping>
  <caching-schemes>
    <distributed-scheme>
      <scheme-name>ExamplesPartitionedPofScheme</scheme-name> 
      <service-name>PartitionedPofCache</service-name> 
      <serializer>  
       <instance>
        <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name> 
          <init-params> 
            <init-param> 
              <param-type>String</param-type>  
              <param-value>contacts-pof-config.xml</param-value> 
            </init-param> 
          </init-params> 
       </instance>
      </serializer>  
      <backing-map-scheme>
        <local-scheme>
          <!-- each node will be limited to 250MB -->
          <high-units>250M</high-units> 
          <unit-calculator>binary</unit-calculator> 
        </local-scheme>
      </backing-map-scheme>
      <autostart>true</autostart>
    </distributed-scheme>
  </caching-schemes>
</cache-config>
Contactsプロジェクトでは、キャッシュ・サーバーが実行されている必要があります。キャッシュ・サーバーとアプリケーションは、同じPOF構成ファイルおよびキャッシュ構成ファイルを参照する必要があります。ここでは、キャッシュ・サーバーとアプリケーションの実行構成を作成する方法について説明します。
実行中のキャッシュ・サーバーがあれば停止します。詳細は、「キャッシュ・サーバーの停止」を参照してください。
キャッシュ・サーバーを起動する実行可能ファイルを作成します。
プロジェクトを右クリックし、「Run As」、「Run Configurations」の順に選択します。「Run Configurations」ダイアログ・ボックスで、「Name」フィールドにContactsCacheServerと入力します。
「Main」タブで、「Project」フィールドに「Contacts」が表示されていることを確認します。「Include system libraries when searching for a main class」チェック・ボックスを選択し、「Search」ボタンをクリックします。「Select Main Type」ダイアログ・ボックスで、DefaultCacheServerと入力し、「DefaultCacheServer - com.tangosol.net」クラスを選択します。「Select Main Type」ダイアログ・ボックスで「OK」をクリックし、「Run Configurations」ダイアログ・ボックスで「Apply」をクリックします。
「Coherence」タブの「General」タブで、「Topology」フィールドの「Absolute File Path」を選択し、C:\home\oracle\workspace\Contacts\appClientModuleディレクトリのcontacts-cache-config.xmlファイルを参照します。「Enabled (cache server)」が選択されていることを確認します。「Cluster port」に一意の値を入力します。「Apply」をクリックします。「General」タブは図4-3のようになります。
「Coherence」タブの「Other」タブで、tangosol.pof.config項目までスクロールダウンします。POF構成ファイルへのパス(C:\home\oracle\workspace\Contacts\appClientModule\contacts-pof-config.xml)を入力します。
「Arguments」タブで、「VM Arguments」に-showversionと入力します。
「Classpath」タブで、「User Entries」にContactsプロジェクトが表示されていることを確認します。
「Common」タブで、「Shared file」を選択し、\Contactsプロジェクトを参照します。
「Run」をクリックして、Contactsキャッシュ・サーバーを起動します。出力は例4-7のようになります。
例4-7 Contactsキャッシュ・サーバーの出力
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
Java HotSpot(TM) Client VM (build 14.0-b16, mixed mode)
2011-03-15 15:30:10.095/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2011-03-15 15:30:10.095/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
2011-03-15 15:30:10.095/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "file:/C:/home/oracle/workspace/Contacts/build/classes/tangosol-coherence-override.xml"
2011-03-15 15:30:10.095/0.125 Oracle Coherence 3.7.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
 
Oracle Coherence Version 3.7.0.0 Build 22913
 Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 
2011-03-15 15:30:10.267/0.297 Oracle Coherence GE 3.7.0.0 <Info> (thread=main, member=n/a): Loaded cache configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-cache-config.xml"
2011-03-15 15:30:10.455/0.485 Oracle Coherence GE 3.7.0.0 <D4> (thread=main, member=n/a): TCMP bound to /130.35.99.213:8088 using SystemSocketProvider
2011-03-15 15:30:13.970/4.000 Oracle Coherence GE 3.7.0.0 <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0x96AB" with Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) UID=0x822363D50000012EBBA3FF26C2D51F98
2011-03-15 15:30:13.970/4.000 Oracle Coherence GE 3.7.0.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0x96AB
 
Group{Address=224.3.7.0, Port=3155, TTL=4}
 
MasterMemberSet
  (
  ThisMember=Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer)
  OldestMember=Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=1, BitSetCount=2
    Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer)
    )
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0, BitSetCount=0
    )
  )
 
TcpRing{Connections=[]}
IpMonitor{AddressListSize=0}
 
2011-03-15 15:30:14.017/4.047 Oracle Coherence GE 3.7.0.0 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1
2011-03-15 15:30:14.189/4.219 Oracle Coherence GE 3.7.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=1): Loaded POF configuration from "file:/C:/home/oracle/workspace/Contacts/build/classes/contacts-pof-config.xml"
2011-03-15 15:30:14.189/4.219 Oracle Coherence GE 3.7.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=1): Loaded included POF configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/coherence-pof-config.xml"
2011-03-15 15:30:14.220/4.250 Oracle Coherence GE 3.7.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Service PartitionedPofCache joined the cluster with senior service member 1
2011-03-15 15:30:14.252/4.282 Oracle Coherence GE 3.7.0.0 <Info> (thread=main, member=1): 
Services
  (
  ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.7pre, OldestMemberId=1}
  InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1, Version=3.1, OldestMemberId=1}
  PartitionedCache{Name=PartitionedPofCache, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257, BackupCount=1, AssignedPartitions=257, BackupPartitions=0}
  )
 
Started DefaultCacheServer...
ContactDriver実行可能ファイルの実行構成を作成します。
「Project Explorer」でContactDriver.javaファイルを右クリックし、「Run As」→「Run Configurations」を選択します。
「Run Configurations」ダイアログ・ボックスで、「Oracle Coherence」ノードをダブルクリックします。「Name」フィールドにContactsDriverと入力します。「Main」タブの「Project」フィールドでContactsを参照し、「Main class」フィールドでcom.oracle.handson.ContactDriverを参照します。「Apply」をクリックします。
「Coherence」タブの「General」タブの「Cache configuration descriptor」フィールドで、contacts-cache-config.xmlファイルへの絶対パスを参照します。「Disable (cache client)」ラジオ・ボタンを選択します。「Cluster port」フィールドに3155と入力します。
「Coherence」タブの「Other」タブで、「tangosol.pof.config」フィールドまでスクロールダウンし、値をcontacts-pof-config.xml POF構成ファイルへの絶対パスに置き換えます。
「Classpath」タブで、「Bootstrap Entries」に「Coherence37」が表示されていることを確認します。「User Entries」に「Contacts (default classpath)」が表示されていることを確認します。
「Run」をクリックして、ContactDriverの構成を実行します。Contactsの出力例は例4-8のようになります。
この例では、Contactオブジェクトが実行時にPOFに変換されます。POFを使用すると、CPU時間と生成されるバイナリ・ファイルのサイズにおいて、パフォーマンスが大幅に向上します。
例4-8 Eclipse IDEでのContactsの出力例
2011-03-15 15:31:50.970/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2011-03-15 15:31:50.970/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
2011-03-15 15:31:50.970/0.125 Oracle Coherence 3.7.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "file:/C:/home/oracle/workspace/Contacts/build/classes/tangosol-coherence-override.xml"
2011-03-15 15:31:50.986/0.141 Oracle Coherence 3.7.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
 
Oracle Coherence Version 3.7.0.0 Build 22913
 Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
 
2011-03-15 15:31:51.142/0.297 Oracle Coherence GE 3.7.0.0 <Info> (thread=main, member=n/a): Loaded cache configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-cache-config.xml"
2011-03-15 15:31:51.345/0.500 Oracle Coherence GE 3.7.0.0 <D4> (thread=main, member=n/a): TCMP bound to /130.35.99.213:8090 using SystemSocketProvider
2011-03-15 15:31:51.799/0.954 Oracle Coherence GE 3.7.0.0 <Info> (thread=Cluster, member=n/a): This Member(Id=2, Timestamp=2011-03-15 15:31:51.619, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) joined cluster "cluster:0x96AB" with senior Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1)
2011-03-15 15:31:51.799/0.954 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=n/a): Member 1 joined Service Cluster with senior member 1
2011-03-15 15:31:51.799/0.954 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=n/a): Member 1 joined Service Management with senior member 1
2011-03-15 15:31:51.799/0.954 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=n/a): Member 1 joined Service PartitionedPofCache with senior member 1
2011-03-15 15:31:51.814/0.969 Oracle Coherence GE 3.7.0.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0x96AB
 
Group{Address=224.3.7.0, Port=3155, TTL=4}
 
MasterMemberSet
  (
  ThisMember=Member(Id=2, Timestamp=2011-03-15 15:31:51.619, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver)
  OldestMember=Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=2, BitSetCount=2
    Member(Id=1, Timestamp=2011-03-15 15:30:10.47, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:4780, Role=CoherenceServer)
    Member(Id=2, Timestamp=2011-03-15 15:31:51.619, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver)
    )
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0, BitSetCount=0
    )
  )
 
TcpRing{Connections=[1]}
IpMonitor{AddressListSize=0}
 
2011-03-15 15:31:51.830/0.985 Oracle Coherence GE 3.7.0.0 <D5> (thread=Invocation:Management, member=2): Service Management joined the cluster with senior service member 1
2011-03-15 15:31:51.924/1.079 Oracle Coherence GE 3.7.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=2): Loaded POF configuration from "file:/C:/home/oracle/workspace/Contacts/build/classes/contacts-pof-config.xml"
2011-03-15 15:31:51.924/1.079 Oracle Coherence GE 3.7.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=2): Loaded included POF configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/coherence-pof-config.xml"
2011-03-15 15:31:51.970/1.125 Oracle Coherence GE 3.7.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=2): Service PartitionedPofCache joined the cluster with senior service member 1
They are the same!!
キャッシュ・サーバーの出力をもう一度参照すると、Contactsキャッシュ・クライアントがクラスタに参加し、処理を完了した後、クラスタから離脱したことを示すメッセージを確認できます。例4-9を参照してください。
例4-9 Contactsクライアントの参加と離脱を示すContactsキャッシュ・サーバー
... Started DefaultCacheServer... 2011-03-15 15:31:51.799/101.829 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2011-03-15 15:31:51.619, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver) joined Cluster with senior member 1 2011-03-15 15:31:51.845/101.875 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member 2 joined Service Management with senior member 1 2011-03-15 15:31:51.986/102.016 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member 2 joined Service PartitionedPofCache with senior member 1 2011-03-15 15:31:52.033/102.063 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): TcpRing disconnected from Member(Id=2, Timestamp=2011-03-15 15:31:51.619, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver) due to a peer departure; removing the member. 2011-03-15 15:31:52.033/102.063 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member 2 left service Management with senior member 1 2011-03-15 15:31:52.033/102.063 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member 2 left service PartitionedPofCache with senior member 1 2011-03-15 15:31:52.033/102.063 Oracle Coherence GE 3.7.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2011-03-15 15:31:52.033, Address=130.35.99.213:8090, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5720, Role=OracleHandsonContactDriver) left Cluster with senior member 1