この章では、キャッシュ内に存在する複合オブジェクトを扱います。JDeveloperを使用して新しいContactクラスを作成し、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のSerializableインタフェースを使用するかわりに、高性能シリアライズのためのCoherence独自のクラスcom.tangosol.io.pof.PortableObjectを使用してパフォーマンスを向上させることができます。PortableObjectは標準的なjava.io.Serializableの最大6倍の速さで、シリアライズ後の結果セットは標準より小さくなります。
PortableObjectインタフェースには、2つの単純なメソッドreadExternalおよびwriteExternalが用意されており、提供されているPofReaderストリームおよびPofWriterストリームからそれぞれ、シリアライズされたオブジェクト属性の読取りと書込みを明示的に行うことができます。シリアライズ形式を制御することにより、Coherenceでは、プロセスのパフォーマンスを大幅に向上させることができます。POFを使用すると、生成されるバイナリのサイズが大幅に縮小されます。バイナリのサイズは5分の1〜10分の1になり、バイナリとの間の変換速度は、オブジェクトのサイズにもよりますが、5〜20倍になる場合があります。
この演習では、従業員の名前、住所、誕生日および電話番号が含まれるContactオブジェクトを作成します。また、POFシリアライズを使用して、PortableObjectインタフェースを実装することによりキャッシュにオブジェクトを挿入して取得します。
この項では、後で別のデータ・オブジェクトに組み込まれる2つのデータ・オブジェクトの作成方法について説明します。Addressオブジェクトは従業員の住所情報を提供し、PhoneNumberオブジェクトは電話連絡先情報を提供します。
従業員の住所情報を格納するAddressオブジェクトを作成します。
JDeveloperで、Contactsという新規プロジェクトを作成します。詳細は、「既存アプリケーションでの新規プロジェクトの作成」を参照してください。
プロジェクトにContactsという名前を付けます。「デフォルト・パッケージ」がcom.oracle.handson、「Javaソースパス」がC:\home\oracle\labs\Contacts\src、「出力ディレクトリ」がC:\home\oracle\labs\Contacts\classesであることを確認します。
Coherenceエントリについて、「プロジェクト・プロパティ」をチェックし、さらに「ライブラリとクラスパス」の値をチェックします。coherence.jarのフルパスC:\oracle\product\coherence\lib\coherence.jarが指定されていることを確認します。
「実行/デバッグ/プロファイル」で、ローカル記憶域を無効にするようデフォルトの構成を編集します。「Javaオプション」フィールドに次の行を追加します。
-Dtangosol.coherence.distributed.localstorage=false
Addressという新規Javaクラスを作成します。詳細は、「Javaクラスの作成」を参照してください。
このJavaクラスにAddressという名前を付けます。「mainメソッド」チェック・ボックスは選択しないでください。
データのシリアライズにPortableObjectを使用するようクラスを記述します。JDeveloperコード・エディタで、com.tangosol.io.pof.PortableObjectを実装するように、生成したAddressクラスを変更します。PortableObjectクラス用にimport文を追加します。
PortableObjectで必要となるcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectで必要となるAddressのpublicなデフォルト・コンストラクタを追加します。
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()
{
}
}
JDeveloperでは、独自の属性用にデフォルトのgetメソッドおよびsetメソッドを生成できます。「ソース」メニューから、「アクセッサの生成」を選択します。Addressクラスの横にあるチェック・ボックスを選択します。これで、すべての属性が自動的に選択されます。「OK」をクリックして続行します。
デフォルトのコンストラクタおよびequalsメソッドを自動的に生成することもできます。「ソース」メニューから、「フィールドからコンストラクタの生成」を選択し、「すべて選択」をクリックしてから「OK」をクリックします。
生成されたコンストラクタは次のようになります。
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クラスをインポートします。次のコードは、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 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を使用します。JDeveloperコード・エディタで、com.tangosol.io.pof.PortableObjectを実装するように、生成したPhoneNumberクラスを変更します。PortableObjectクラス用にimport文を追加します。
PortableObjectで必要となるcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectで必要となるPhoneNumberのpublicなデフォルト・コンストラクタを追加します。
PhoneNumberクラス用に次のプライベート属性を入力します。必要に応じて他の属性も追加できます。
—short AccessCode
—short CountryCode
—short AreaCode
—int LocalNumber
JDeveloperでは、独自の属性用にデフォルトのgetメソッドおよびsetメソッドを生成できます。「ソース」メニューから、「アクセッサの生成」を選択します。PhoneNumberクラスの横にあるチェック・ボックスを選択します。これで、すべての属性が自動的に選択されます。「OK」をクリックして続行します。
デフォルトのコンストラクタを自動的に生成することができます。「ソース」メニューから、「フィールドからコンストラクタの生成」を選択し、「すべて選択」をクリックしてから「OK」をクリックします。
生成されたコンストラクタは次のようになります。
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 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;
/**
* 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を使用するため、com.tangosol.io.pof.PortableObjectを実装するように、JDeveloperコード・エディタで、生成したContactクラスを変更します。PortableObjectクラス用にimport文を追加します。
PortableObjectで必要となるcom.tangosol.io.pof.PofReaderクラス、com.tangosol.io.pof.PofWriterクラスおよびjava.io.IOExceptionクラスをインポートします。
PortableObjectで必要となるContactのpublicなデフォルト・コンストラクタを追加します。
Contactクラス用に次のプライベート属性を入力します。必要に応じて他の属性も追加できます。
String FirstName
String LastName
Address HomeAddress
Address WorkAddress
Map TelephoneNumbers
java.sql.Date BirthDate
JDeveloperでは、独自の属性用にデフォルトのgetメソッドおよびsetメソッドを生成できます。「ソース」メニューから、「アクセッサの生成」を選択します。Contactクラスの横にあるチェック・ボックスを選択します。これで、すべての属性が自動的に選択されます。「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;
デフォルトのコンストラクタを自動的に生成することができます。「ソース」メニューから、「フィールドからコンストラクタの生成」を選択し、「すべて選択」をクリックしてから「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 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 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構成ファイルを作成するには、モデルとしてcoherence-pof-config.xmlファイルを使用します。このファイルのコピーは、coherence.jarにあります。
Contactオブジェクト、AddressオブジェクトおよびPhoneNumberオブジェクトの<user-type>要素を定義し、これらに型ID 1001、1002および1003を割り当てて、完全なクラス名を指定します。このファイルには、Coherenceデータ型の最初の1000個のIDを予約するcoherence-pof-config.xmlファイルを含めます。
このファイルをcontacts-pof-config.xmlという名前でC:\home\oracle\labsディレクトリに保存します。coherence-pof-config.xmlファイルのコピーをlabsディレクトリにも保存します。例4-5は、contacts-pof-config.xmlファイルのサンプルを示しています。
例4-5 POF構成ファイル
<?xml version="1.0"?>
<!DOCTYPE pof-config SYSTEM "pof-config.dtd">
<pof-config>
<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>
キャッシュ構成ファイルを作成します。coherence-cache-config.xmlファイルを使用できます。これはcache-config.dtdに基づいています。coherence-cache-config.xmlのコピーは、coherence.jarにあります。
scheme-nameとしてExamplesPartitionedPocSchemeを、service-nameとしてPartitionedPofCacheを使用します。serializerセクションは、POFシリアライズされたオブジェクトの適切なシリアライズ・ルーチン(PofSerializer、またはPortableObjectインタフェースを介したコールによる)へのマッピングを担当します。この場合、com.tangosol.io.pof.ConfigurablePofContextクラスを使用します。<init-param>セクションは、POF構成ファイルの名前(この場合、contacts-pof-config.xml)を指します。
このファイルをcontacts-cache-config.xmlという名前でC:\home\oracle\labsディレクトリに保存します。cache-config.dtdファイルのコピーをlabsディレクトリにも保存します。例4-6は、contacts-cache-config.xmlファイルのサンプルを示しています。
例4-6 キャッシュ構成ファイル
<?xml version="1.0"?>
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
<cache-config>
<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>
<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>
</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-cache-server.cmdという名前を付け、次の情報を追加します。
クラスパスに対するcoherence.jarファイルの場所: %COHERENCE_HOME%\lib\coherence.jar
クラスパスに対するアプリケーション・クラス・ファイルの場所: C:\home\oracle\labs\Contacts\classes
クラスパスに対するPOF構成ファイルの場所: C:\home\oracle\labs
-Dtangosol.coherence.cacheconfigによるサーバー構成の場所
デフォルトのキャッシュ・サーバーを起動するコマンド: com.tangosol.net.DefaultCacheServer
例4-7に、contacts-cache-server.cmd実行可能ファイルのサンプルを示します。
例4-7 キャッシュ・サーバー実行可能ファイルのサンプル
@echo off
setlocal
if (%COHERENCE_HOME%)==() (
set COHERENCE_HOME=c:\oracle\product\coherence
)
set CONFIG=c:\home\oracle\labs
set COH_OPTS=%COH_OPTS% -server -cp %COHERENCE_HOME%\lib\coherence.jar;C:\home\oracle\labs\Contacts\classes;C:\home\oracle\labs;
set COH_OPTS=%COH_OPTS% -Dtangosol.coherence.cacheconfig=%CONFIG%\contacts-cache-config.xml
java %COH_OPTS% -Xms1g -Xmx1g -Xloggc: com.tangosol.net.DefaultCacheServer %2 %3 %4 %5 %6 %7
:exit
Contactsプロジェクトがまだコンパイルされていない場合は、これをコンパイルします。
Contactsプロジェクトを右クリックし、「Contacts.jprのメイク」を選択します。
実行されているキャッシュ・サーバーがあれば停止します。
コマンドラインでcontacts-cache-server.cmdを実行し、Contactsキャッシュ・サーバーを起動します。
例4-8に、contacts-cache-server.cmdを実行したときのサンプル出力を示します。
例4-8 POFキャッシュ・サーバーの起動
C:\oracle\product\coherence\bin>contacts-cache-server.cmd
2010-05-27 13:42:18.826/0.297 Oracle Coherence 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence.xml"
2010-05-27 13:42:18.826/0.297 Oracle Coherence 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml"
2010-05-27 13:42:18.826/0.297 Oracle Coherence 3.6.0.0 DPR3 <D5> (thread=main, member=n/a): Optional configuration override "/tangosol-coherence-override.xml" is not specified
2010-05-27 13:42:18.842/0.313 Oracle Coherence 3.6.0.0 DPR3 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
Oracle Coherence Version 3.6.0.0 DPR3 Build 16141
Grid Edition: Development mode
Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2010-05-27 13:42:19.092/0.563 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Loaded cache configuration from "file:/C:/home/oracle/labs/contacts-cache-config.xml"
2010-05-27 13:42:19.451/0.922 Oracle Coherence GE 3.6.0.0 DPR3 <D4> (thread=main, member=n/a): SystemSocketProvider bound to port 8088
2010-05-27 13:42:22.904/4.375 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0xC4DB" with Member(Id=1, Timestamp=2010-05-27 13:42:19.467, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5200, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2, SocketCount=1) UID=0x822363D500000128DB8051CBC2D51F98
2010-05-27 13:42:22.920/4.391 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0xC4DB
Group{Address=224.3.6.0, Port=36000, TTL=4}
MasterMemberSet
(
ThisMember=Member(Id=1, Timestamp=2010-05-27 13:42:19.467, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5200, Role=CoherenceServer)
OldestMember=Member(Id=1, Timestamp=2010-05-27 13:42:19.467, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5200, Role=CoherenceServer)
ActualMemberSet=MemberSet(Size=1, BitSetCount=2
Member(Id=1, Timestamp=2010-05-27 13:42:19.467, Address=130.35.99.213:8088, MachineId=49877, Location=site:us.oracle.com,machine:tpfaeffl-lap7,process:5200, Role=CoherenceServer)
)
RecycleMillis=1200000
RecycleSet=MemberSet(Size=0, BitSetCount=0
)
)
TcpRing{Connections=[]}
IpMonitor{AddressListSize=0}
2010-05-27 13:42:23.029/4.500 Oracle Coherence GE 3.6.0.0 DPR3 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1
2010-05-27 13:42:23.279/4.750 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=Cluster, member=1): Loaded POF configuration from "file:/C:/home/oracle/labs/contacts-pof-config.xml"
2010-05-27 13:42:23.295/4.766 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=Cluster, member=1): Loaded included POF configuration from "jar:file:/C:/oracle/product/coherence/lib/coherence.jar!/coherence-pof-config.xml"
2010-05-27 13:42:23.373/4.844 Oracle Coherence GE 3.6.0.0 DPR3 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Service PartitionedPofCac
he joined the cluster with senior service member 1
2010-05-27 13:42:23.388/4.859 Oracle Coherence GE 3.6.0.0 DPR3 <Info> (thread=main, member=1):
Services
(
ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.6, 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...
JDeveloperでPOFキャッシュ・サーバーを設定します。
既存のプロジェクト・プロパティにCLASSPATHエントリを追加します。「ツール」→「プロジェクト・プロパティ」→「ライブラリとクラスパス」に移動します。「JAR/ディレクトリの追加」をクリックします。プロジェクトでCLASSPATHにC:\home\oracle\labsを追加します。coherence.jarがクラスパスにあることを確認します。
「実行/デバッグ/プロファイル」をクリックしてランタイム・プロパティを編集します。ローカル記憶域が無効であることを確認します。「Javaオプション」フィールドにcontacts-cache-config.xmlファイルのパスを追加します。次を含む必要があります:
-Dtangosol.coherence.distributed.localstorage=false -Dtangosol.coherence.cacheconfig=c:\home\oracle\labs\contacts-cache-config.xml
「OK」をクリックしてランタイム構成の変更を保存し、再度「OK」をクリックして「プロジェクト・プロパティ」ダイアログ・ボックスを閉じます。
JDeveloperのIDEからContactDriver.javaを実行して、機能することを確認します。
この例で、Contactオブジェクトは実行時にPOFに変換されます。POFを使用すると、CPU時間と生成されるバイナリのサイズの点で、パフォーマンスが大幅に向上します。