In this chapter, you work with complex objects residing in the cache. Using JDeveloper, you create a new Contact
class, and then store and retrieve Contact
objects in the cache using POF serialization.
This chapter contains the following sections:
Until now, you have been putting and getting String
objects as the value in a NamedCache
. Many of the implementations of the get
and put
methods in the Coherence Java API define the values and keys to be of type Object
. For example:
public java.lang.Object get(java.lang.Object oKey) public void put(java.lang.Object oKey, java.lang.Object oValue)
Any object can potentially be used as a value or key. This enables you to store complex objects as values in the cache.
Because Coherence might need to send the object across the wire, the object must be serializable. Object serialization is the process of saving an object's state into a sequence of bytes, and then rebuilding (deserializing) them into a live object at some future time. For example, objects that implement the java.io.Serializable
interface are serializable.
As an alternative to using the Java Serializable
interface, you can improve performance by using Coherence's own class for high-performance serialization, com.tangosol.io.pof.PortableObject
. PortableObject
is up to six times faster than the standard java.io.Serializable
and the serialized result set is smaller.
The PortableObject
interface provides two simple methods, readExternal
and writeExternal
, that permit you explicitly read and write serialized object attributes from the provided PofReader
and PofWriter
streams respectively. By taking control over the serialization format, Coherence provides a way to dramatically improve the performance of the process. Using POF dramatically reduces the size of the resulting binary. The size of the binary is often 5 to 10x smaller, and the conversion to-or-from the binary can be between 5 and 20 times faster, depending on the size of the object.
In this exercise, you will create a Contact
object that contains names, addresses, dates of birth, and telephone numbers for employees. You will also use POF serialization to put the objects in the cache and retrieve them by implementing the PortableObject
interface.
This section describes how to create two data objects that will later be incorporated into another data object. An Address
object will provide employee address information and a PhoneNumber
object will provide telephone contact information.
Create an Address
object to store address information for an employee.
Create a new project in JDeveloper called Contacts
. See "Creating a New Project in an Existing Application" if you need detailed information.
Name the project Contacts
. Ensure that the Default Package is com.oracle.handson
, the Java Source Path is C:\home\oracle\labs\Contacts\src
and the Output Directory is C:\home\oracle\labs\Contacts\classes
.
Check the Project Properties then Libraries and Classpath value for the Coherence entry. Ensure that the full path is provided for the coherence.jar
: C:\oracle\product\coherence\lib\coherence.jar
.
In Run/Debug/Profile, edit the default configuration to disable local storage. Add the following line to the Java Options field:
-Dtangosol.coherence.distributed.localstorage=false
Create a new Java class called Address
. See "Creating a Java Class" if you need detailed information.
Name the Java class Address
. Do not select the Main Method check box.
Write the class to use PortableObject
for data serialization. In the JDeveloper code editor, change your generated Address
class to implement com.tangosol.io.pof.PortableObject
. Add an import
statement for the PortableObject
class.
Import the com.tangosol.io.pof.PofReader
, com.tangosol.io.pof.PofWriter
, and java.io.IOException
classes required by Portable
Object
.
Add the default public constructor for Address
that is required by PortableObject
.
Enter the following private attributes for your Address
class. You can add others if you like.
— String Street1
— String Street2
— String City
— String State
— String Country
At this point, the Address
class should look similar to the following
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 can generate the default get/set methods for your attributes. From the Source menu, select Generate Accessors. Select the check box next to the Address
class. All of the attributes are now automatically selected. Click OK to continue.
You can also generate the default constructor and equals methods automatically. From the Source menu, select Generate Constructor from Fields, click Select All, and then click OK.
The generated constructor should look similar to the following:
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; }
Implement the readExternal
and writeExternal
methods as required by the PortableObject
interface. For example, the following implementation of readExternal
allows the values for the street, city, state, and country to be read as POF objects.
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)); }
Implement the equals
, hashCode
, and toString
object methods.
Note:
Cache keys and values must be serializable (for example,java.io.Serializable
). Cache keys must also provide an implementation of the hashCode()
and equals()
methods, and those methods must return consistent results across cluster nodes. This implies that the implementation of hashCode()
and equals()
must be based solely on the object's serializable state (that is, the object's non-transient fields); most built-in Java types, such as String
, Integer
and Date
, meet this requirement. Some cache implementations (specifically the partitioned cache) use the serialized form of the key objects for equality testing, which means that keys for which equals()
returns true must serialize identically; most built-in Java types meet this requirement as well.To support these methods, import the com.tangosol.util.Base
and com.tangosol.util.HashHelper
classes. The following code illustrates a sample implementation of 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()); }
The following code illustrates a sample implementation of hashCode
:
public int hashCode() { return HashHelper.hash(getStreet1(), HashHelper.hash(getStreet2(), HashHelper.hash(getZip(), 0))); }
The following code illustrates a sample implementation of toString
:
public String toString() { return getStreet1() + "\n" + getStreet2() + "\n" + getCity() + ", " + getState() + " " + getZip() + "\n" + getCountry(); }
The resulting class should look similar to the following.
Example 4-1 Implementation of an Address Class
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(); } }
Create a PhoneNumber
class to store telephone contact data.
Create a new Java class called PhoneNumber
. Do not include a main
method.
See "Creating a Java Class" if you need detailed information.
Use PortableObject
for data serialization. In the JDeveloper code editor, change your generated PhoneNumber
class to implement com.tangosol.io.pof.PortableObject
. Add an import
statement for the PortableObject
class.
Import the com.tangosol.io.pof.PofReader
and com.tangosol.io.pof.PofWriter
, and java.io.IOException
classes required by Portable
Object
.
Add the default public constructor for PhoneNumber
that is required by PortableObject
.
Enter the following private attributes for your PhoneNumber
class. You can add others if you like.
—short AccessCode
—short CountryCode
—short AreaCode
—int LocalNumber
JDeveloper can generate the default get/set methods for your attributes. From the Source menu, select Generate Accessors. Select the check box next to the PhoneNumber
class. All of the attributes are now automatically selected. Click OK to continue.
You can generate the default constructor automatically. From the Source menu, select Generate Constructor from Fields, click Select All, and then click OK.
The generated constructor should look similar to the following:
public PhoneNumber(short AccessCode, short CountryCode, short AreaCode, int LocalNumber) { super(); this.AccessCode = AccessCode; this.CountryCode = CountryCode; this.AreaCode = AreaCode; this.LocalNumber = LocalNumber; }
Implement the readExternal
and writeExternal
methods as required by the PortableObject
interface.
Implement the equals
, hashCode
and toString
object methods.
The resulting class should look similar to the following.
Example 4-2 Implementation of a PhoneNumber Class
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(); } }
The Contact
object will provide the name, address, and telephone information of employees by incorporating the Address
and PhoneNumber
data objects.
Create a new Java class called Contact
. Do not include a main
method.
See "Creating a Java Class" if you need more information.
Since the class will use PortableObject
for data serialization, change your generated Contact
class to implement com.tangosol.io.pof.PortableObject
in the JDeveloper code editor. Add an import
statement for the PortableObject
class.
Import the com.tangosol.io.pof.PofReader
and com.tangosol.io.pof.PofWriter
and java.io.IOException
classes required by Portable
Object
.
Add the default public constructor for Contact
that is required by PortableObject
.
Enter the following private attributes for your Contact
class. You can add others if you like.
String FirstName
String LastName
Address HomeAddress
Address WorkAddress
Map TelephoneNumbers
java.sql.Date BirthDate
JDeveloper can generate the default get/set methods for your attributes. From the Source menu, select Generate Accessors. Select the check box next to the Contact
class. All of the attributes are now automatically selected. Click OK to continue.
Create an accessor, getAge
, to calculate the age of an employee:
public int getAge() { return (int) ((System.currentTimeMillis() - BirthDate.getTime()) / MILLIS_IN_YEAR); }
Add a definition for MILLIS_IN_YEAR
.
public static final long MILLIS_IN_YEAR = 1000L * 60L * 60L * 24L * 365L;
You can generate the default constructor automatically. From the Source menu, select Generate Constructor from Fields, click Select All, and then click OK.
The generated constructor should look similar to the following:
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; }
Implement the readExternal
and writeExternal
methods as required by the PortableObject
interface.
Implement the equals
, hashCode
, and toString
object methods.
The resulting class should look similar to the following.
Example 4-3 Sample Contact Class
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; }
Create a driver class called ContactDriver
to put Contact
entries into the cache and retrieve them.
Create a new Java class called ContactDriver
in the Contacts
project. Ensure that it includes a main
method.
See "Creating a Java Class" if you need detailed information.
In the ContactDriver
file, create a new NamedCache
called contact
and put a new instance of the Contact
object in it. Get the Contact
object from the cache and ensure that the two objects are identical.
Example 4-4 Sample ContactDriver Class
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!!"); } } }
To use POF serialization, you must register your user-defined objects in a POF configuration file. The configuration associates the class of a user-defined object with a numeric value. In addition, you must specify POF serialization and the name of the POF configuration file in the cache configuration file.
Create a POF configuration file for the Contact
, Address
, and PhoneNumber
objects.
To create a POF configuration file for your data types, use the coherence-pof-config.xml
file as a model. You can find a copy of this file in the coherence.jar
.
Define <user-type>
elements for the Contact
, Address
, and PhoneNumber
objects, assign type IDs 1001
, 1002
, and 1003
to them and provide their full class names. The file should include the coherence-pof-config.xml
file which reserves the first 1000 IDs for Coherence data types.
Save the file as contacts-pof-config.xml
in the C:\home\oracle\labs
directory. Save a copy of the coherence-pof-config.xml
file in the labs
directory as well. Example 4-5 illustrates a sample contacts-pof-config.xml
file.
Example 4-5 POF Configuration File
<?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>
Create a cache configuration file. You can use the coherence-cache-config.xml
file, which is based on the cache-config.dtd
as a model. You can find a copy of coherence-cache-config.xml
in the coherence.jar
.
Use ExamplesPartitionedPocScheme
as the scheme-name
and PartitionedPofCache
as the service-name
. The serializer
section is responsible for mapping a POF serialized object to an appropriate serialization routine which is either a PofSerializer
or by calling through the PortableObject
interface. In this case, use the com.tangosol.io.pof.ConfigurablePofContext
class. The <init-param>
section points to the name of the POF configuration file, in this case contacts-pof-config.xml
.
Save the file as contacts-cache-config.xml
in the C:\home\oracle\labs
directory. Save a copy of the cache-config.dtd
file in the labs
directory as well. Example 4-6 illustrates a sample contacts-cache-config.xml
file.
Example 4-6 Cache Configuration File
<?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>
Create an executable to start the cache server.
Name the file contacts-cache-server.cmd
and add the following information:
the location of the coherence.jar
file to the classpath: %COHERENCE_HOME%\lib\coherence.jar
the location of the application class files to the classpath: C:\home\oracle\labs\Contacts\classes
the location of the POF configuration file to the classpath: C:\home\oracle\labs
the location of the server configuration with -Dtangosol.coherence.cacheconfig
the command to start the default cache server: com.tangosol.net.DefaultCacheServer
Example 4-7 illustrates a sample contacts-cache-server.cmd
executable file.
Example 4-7 Sample Cache Server Executable
@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
Compile the Contacts
project if you have not done so already.
Right-click the Contacts
project and select Make Contacts.jpr.
Stop any cache servers that may be running.
Start the Contacts cache server by executing contacts-cache-server.cmd
on the command line.
Example 4-8 lists sample output from running contacts-cache-server.cmd
.
Example 4-8 Starting the POF Cache Server
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...
Set up the POF cache server to run in JDeveloper.
Add additional CLASSPATH
entries to the existing project properties. Navigate to Tools then Project Properties then Libraries and Classpath. Click Add JAR/Directory. In your project, add C:\home\oracle\labs
to your CLASSPATH
. Ensure that coherence.jar
is in the classpath.
Click Run/Debug/Profile to edit the run-time properties. Ensure that local storage is disabled. Add the path to the contacts-cache-config.xml
file in the Java Options field. The should contain the following:
-Dtangosol.coherence.distributed.localstorage=false -Dtangosol.coherence.cacheconfig=c:\home\oracle\labs\contacts-cache-config.xml
Click OK to save your changes to the run-time configuration and OK again to dismiss the Project Properties dialog box.
Run ContactDriver.java
from the JDeveloper IDE to ensure that it works.
In this example, the Contact
object is converted to POF at run time. Using POF should provide significant performance improvements in terms of CPU time and the size of the binary generated.