この演習では、キャッシュ内にある複合オブジェクトを操作します。ここでは、Coherence APIのPofReader、PofWriterおよびPortableObjectの使用について取り上げます。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の各オブジェクト・メソッドを実装します。
|
注意: キャッシュのキーと値は、シリアライズ可能(たとえば、 |
これらのメソッドをサポートするには、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.GregorianCalendar;
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 java.sql.Date(new GregorianCalendar(2011, 05, 01).getTime().getTime());
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ファイルが含まれている必要があります。
ファイル名を変更し、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 http://xmlns.oracle.com/coherence/coherence-pof-config/1.2/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としてExamplesPartitionedPofSchemeを、service-nameとしてPartitionedPofCacheを使用します。
serializerセクションでは、POFシリアライズ・オブジェクトの適切なシリアライズ・ルーチンへのマッピングを管理します。POF構成ファイルの場所は、次の項で宣言します。
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">
<defaults>
<serializer>pof</serializer>
</defaults>
<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>
<thread-count>5</thread-count>
<backing-map-scheme>
<local-scheme>
<!-- each node will be limited to 32MB -->
<high-units>250MB</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プロジェクトが表示されていることを確認します。表示されていない場合は、「Add Projects」ボタンをクリックしてContactsプロジェクトを追加します。
「Common」タブで、「Shared file」を選択し、\Contactsプロジェクトを参照します。
「Run」をクリックして、Contactsキャッシュ・サーバーを起動します。出力は例4-7のようになります。
例4-7 Contactsキャッシュ・サーバーの出力
java version "1.7.0_25" Java(TM) SE Runtime Environment (build 1.7.0_25-b17) Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) 2013-11-21 11:04:21.818/0.312 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence.xml" 2013-11-21 11:04:21.912/0.406 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml" 2013-11-21 11:04:22.006/0.500 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "file:/C:/home/oracle/workspace/Contacts/build/classes/tangosol-coherence-override.xml" 2013-11-21 11:04:22.006/0.500 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-config.xml" is not specified 2013-11-21 11:04:22.006/0.500 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-builder-config.xml" is not specified 2013-11-21 11:04:22.006/0.500 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified Oracle Coherence Version 12.1.3.0.0 Build 48392 Grid Edition: Development mode Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 2013-11-21 11:04:22.631/1.125 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a):Loaded cache configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-cache-config.xml"2013-11-21 11:04:23.691/2.185 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a): Created cache factory com.tangosol.net.ExtensibleConfigurableCacheFactory 2013-11-21 11:04:24.457/2.951 Oracle Coherence GE 12.1.3.0.0 <D4> (thread=main, member=n/a): TCMP bound to /130.35.99.28:8088 using SystemDatagramSocketProvider 2013-11-21 11:04:28.294/6.788 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0x47DB" with Member(Id=1, Timestamp=2013-11-21 11:04:24.769, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:1344, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=4, SocketCount=4) 2013-11-21 11:04:28.294/6.788 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0x47DB Group{Address=224.12.1.0, Port=3155, TTL=4} MasterMemberSet( ThisMember=Member(Id=1, Timestamp=2013-11-21 11:04:24.769, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:1344, Role=CoherenceServer) OldestMember=Member(Id=1, Timestamp=2013-11-21 11:04:24.769, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:1344, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=1 Member(Id=1, Timestamp=2013-11-21 11:04:24.769, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:1344, Role=CoherenceServer) ) MemberId|ServiceVersion|ServiceJoined|MemberState 1|12.1.3|2013-11-21 11:04:24.769|JOINED RecycleMillis=1200000 RecycleSet=MemberSet(Size=0 ) ) TcpRing{Connections=[]} IpMonitor{Addresses=0} 2013-11-21 11:04:28.295/6.789 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster with senior service member 1 2013-11-21 11:04:28.328/6.822 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=1): Loaded Reporter configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/reports/report-group.xml" 2013-11-21 11:04:28.718/7.212 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=NameService:TcpAcceptor, member=1): TcpAcceptor now listening for connections on 130.35.99.28:8088.3 2013-11-21 11:04:29.061/7.555 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=1):Loaded POF configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-pof-config.xml"2013-11-21 11:04:29.076/7.570 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=1): Loaded included POF configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/coherence-pof-config.xml" 2013-11-21 11:04:29.123/7.617 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Service PartitionedPofCache joined the cluster with senior service member 1 2013-11-21 11:04:29.139/7.633 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=1): Services ( ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=12.1.3, OldestMemberId=1} InvocationService{Name=Management, State=(SERVICE_STARTED), Id=2, Version=12.1.3, OldestMemberId=1} PartitionedCache{Name=PartitionedPofCache, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257, BackupCount=1, AssignedPartitions=0, 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」タブで、「User Entries」に「Contacts (default classpath)」が表示されていることを確認します。
「Run」をクリックして、ContactDriverの構成を実行します。Contactsの出力例は例4-8のようになります。
この例では、Contactオブジェクトが実行時にPOFに変換されます。POFを使用すると、CPU時間と生成されるバイナリ・ファイルのサイズにおいて、パフォーマンスが大幅に向上します。
例4-8 Eclipse IDEでのContactsの出力例
2013-11-21 11:26:44.085/0.312 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence.xml" 2013-11-21 11:26:44.163/0.390 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/tangosol-coherence-override-dev.xml" 2013-11-21 11:26:44.256/0.483 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "file:/C:/home/oracle/workspace/Contacts/build/classes/tangosol-coherence-override.xml" 2013-11-21 11:26:44.256/0.483 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-config.xml" is not specified 2013-11-21 11:26:44.256/0.483 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-builder-config.xml" is not specified 2013-11-21 11:26:44.256/0.483 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified Oracle Coherence Version 12.1.3.0.0 Build 48392 Grid Edition: Development mode Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 2013-11-21 11:26:44.897/1.124 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a):Loaded cache configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-cache-config.xml"2013-11-21 11:26:45.942/2.169 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a): Created cache factory com.tangosol.net.ExtensibleConfigurableCacheFactory 2013-11-21 11:26:47.004/3.231 Oracle Coherence GE 12.1.3.0.0 <D4> (thread=main, member=n/a): TCMP bound to /130.35.99.28:8090 using SystemDatagramSocketProvider 2013-11-21 11:26:47.816/4.043 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Cluster, member=n/a): Member(Id=1, Timestamp=2013-11-21 11:26:21.557, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:7096, Role=CoherenceServer) joined Cluster with senior member 1 2013-11-21 11:26:47.817/4.044 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=Cluster, member=n/a): This Member(Id=2, Timestamp=2013-11-21 11:26:47.66, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver, Edition=Grid Edition, Mode=Development, CpuCount=4, SocketCount=4) joined cluster "cluster:0x47DB" with senior Member(Id=1, Timestamp=2013-11-21 11:26:21.557, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:7096, Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=4, SocketCount=4) 2013-11-21 11:26:48.067/4.294 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a): Started cluster Name=cluster:0x47DB Group{Address=224.12.1.0, Port=3155, TTL=4} MasterMemberSet( ThisMember=Member(Id=2, Timestamp=2013-11-21 11:26:47.66, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver) OldestMember=Member(Id=1, Timestamp=2013-11-21 11:26:21.557, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:7096, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=2 Member(Id=1, Timestamp=2013-11-21 11:26:21.557, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:7096, Role=CoherenceServer) Member(Id=2, Timestamp=2013-11-21 11:26:47.66, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver) ) MemberId|ServiceVersion|ServiceJoined|MemberState 1|12.1.3|2013-11-21 11:26:21.557|JOINED, 2|12.1.3|2013-11-21 11:26:47.66|JOINED RecycleMillis=1200000 RecycleSet=MemberSet(Size=0 ) ) TcpRing{Connections=[1]} IpMonitor{Addresses=0} 2013-11-21 11:26:48.068/4.295 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Invocation:Management, member=2): Service Management joined the cluster with senior service member 1 2013-11-21 11:26:48.099/4.326 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=2): Loaded Reporter configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/reports/report-group.xml" 2013-11-21 11:26:48.505/4.732 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=NameService:TcpAcceptor, member=2): TcpAcceptor now listening for connections on 130.35.99.28:8090.3 2013-11-21 11:26:48.848/5.075 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=2):Loaded POF configuration from "file:/C:/home/oracle/workspace/Contacts/appClientModule/contacts-pof-config.xml"2013-11-21 11:26:48.879/5.106 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=DistributedCache:PartitionedPofCache, member=2): Loaded included POF configuration from "jar:file:/C:/Oracle/Middleware/Oracle_Home/coherence/lib/coherence.jar!/coherence-pof-config.xml" 2013-11-21 11:26:48.910/5.137 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=2): Service PartitionedPofCache joined the cluster with senior service member 1They are the same!!
キャッシュ・サーバーの出力をもう一度参照すると、Contactsキャッシュ・クライアントがクラスタに参加し、処理を完了した後にクラスタから離脱したことを示すメッセージを確認できます。例4-9を参照してください。
例4-9 Contactsクライアントの参加と離脱を示すContactsキャッシュ・サーバー
... Started DefaultCacheServer... 2013-11-21 11:26:25.942/7.726 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): This member has become the distribution coordinator for MemberSet(Size=1 Member(Id=1, Timestamp=2013-11-21 11:26:21.557, Address=130.35.99.28:8088, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:7096, Role=CoherenceServer) ) 2013-11-21 11:26:47.816/29.600 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2013-11-21 11:26:47.66, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver) joined Cluster with senior member 1 2013-11-21 11:26:48.099/29.883 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Invocation:Management, member=1): Member 2 joined Service Management with senior member 1 2013-11-21 11:26:48.941/30.725 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Member 2 joined Service PartitionedPofCache with senior member 1 2013-11-21 11:26:49.114/30.898 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Cluster, member=1): TcpRing disconnected from Member(Id=2, Timestamp=2013-11-21 11:26:47.66, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver) due to a peer departure; removing the member. 2013-11-21 11:26:49.114/30.898 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Cluster, member=1): Member(Id=2, Timestamp=2013-11-21 11:26:49.114, Address=130.35.99.28:8090, MachineId=47251, Location=site:,machine:TPFAEFFL-LAP,process:6432, Role=OracleHandsonContactDriver) left Cluster with senior member 1 2013-11-21 11:26:49.114/30.898 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=Invocation:Management, member=1): Member 2 left service Management with senior member 1 2013-11-21 11:26:49.114/30.898 Oracle Coherence GE 12.1.3.0.0 <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Member 2 left service PartitionedPofCache with senior member 1