Skip Headers
Oracle® Coherence Tutorial for Oracle Coherence
Release 3.5

Part Number E14527-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

3 Working with Complex Objects

In this chapter, you work with complex objects residing in the cache. Using JDeveloper, you create a new Person class that is serializable, store and retrieve Person objects in the cache, and serialize your own objects.

This chapter contains the following sections:

3.1 Introduction

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.

3.2 Creating and Caching Complex Objects

In this exercise, you create a Contact object that contains names, addresses, dates of birth, and telephone numbers for employees. An Address object type supplies the address. You will also create a program that uses PortableObject to put the object in the cache and retrieve it.

3.2.1 Creating the Data Objects

This section describes how to create two data objects that will later be incorporated another data object. The Address object will be used to provide employee address information. The Phone object will provide telephone contact information.

  1. Create an Address object to store address information for an employee.

    1. Create a new project in JDeveloper called Contacts. See "Creating a New Project in an Existing Application" if you need detailed information.

    2. Name the project Contacts. Ensure that the Default Package is com.oracle.coherence.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>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

    3. 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 Generate Main Method check box.

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

    5. Import the com.tangosol.io.pof.PofReader, com.tangosol.io.pof.PofWriter, and java.io.IOException classes required by PortableObject.

    6. Add the default public constructor for Address that is required by PortableObject.

    7. 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.coherence.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()
              {
              }
      }
      
    8. 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.

      Figure 3-1 Generate Accessors Dialog Box

      Generate Accessors Dialog Box
    9. 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.

      Figure 3-2 Generate Constructors Dialog Box

      Generate Constructors Dialog Box

      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;
          }
      
    10. Implement the readExternal and writeExternal methods as required by the PortableObject interface.

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

    12. The resulting class should look similar to the following.

      Example 3-1 Implementation of an Address Class

      package com.oracle.coherence.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();
              }
       
      }
      
  2. Create a Phone class to store telephone contact data.

    1. Create a new Java class called Phone. See "Creating a Java Class" if you need detailed information.

      Name the Java class Phone. Do not select the Generate Main Method check box.

    2. Use PortableObject for data serialization. In the JDeveloper code editor, change your generated Phone class to implement com.tangosol.io.pof.PortableObject. Add an import statement for the PortableObject class.

    3. Import the com.tangosol.io.pof.PofReader and com.tangosol.io.pof.PofWriter classes required by PortableObject.

    4. Add the default public constructor for Phone that is required by PortableObject.

    5. Enter the following private attributes for your Phone class. You can add others if you like.

      short AccessCode

      short CountryCode

      short AreaCode

      int LocalNumber

    6. 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 Phone class. All of the attributes are now automatically selected. Click OK to continue.

    7. 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 Phone(short AccessCode, short CountryCode, short AreaCode,
                   int LocalNumber) {
          super();
          this.AccessCode = AccessCode;
          this.CountryCode = CountryCode;
          this.AreaCode = AreaCode;
          this.LocalNumber = LocalNumber; 
          }
      
    8. Implement the readExternal and writeExternal methods as required by the PortableObject interface.

    9. Implement the equals, hashCode and toString object methods.

    10. The resulting class should look similar to the following.

      Example 3-2 Implementation of a Phone Class

      package com.oracle.coherence.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 Phone implements PortableObject 
      {
          
          private short AccessCode;
          private short CountryCode;
          private short AreaCode;
          private int LocalNumber;
          
          /**
          * Default constructor (necessary for PortableObject implementation).
          */
          public Phone() {
          }
       
          public Phone(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;
                  }
       
              Phone that = (Phone) 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();
              }
          
      }
      

3.2.2 Creating the Complex Object

The Contact object will provide the name, address, and telephone information of employees by incorporating the Address and Phone data objects.

  1. Create a new Java class called Contact. See "Creating a Java Class" if you need more information.

    Name the Java class Contact. Do not select the Generate Main Method check box.

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

  3. Import the com.tangosol.io.pof.PofReader and com.tangosol.io.pof.PofWriter classes required by PortableObject.

  4. Add the default public constructor for Contact that is required by PortableObject.

  5. Enter the following private attributes for your Contact class. You can add others if you like.

    String FirstNameString LastNameAddress HomeAddress

    Address WorkAddress

    Map TelephoneNumbers

    java.sql.Date BirthDate

  6. 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 Phone class. All of the attributes are now automatically selected. Click OK to continue.

  7. Create an accessor, getAge, to calculate the age of an employee:

    public int getAge()
            {
            return (int) ((System.currentTimeMillis() - BirthDate.getTime()) /  MILLIS_IN_YEAR);  
            }
    
  8. Add a definition for MILLIS_IN_YEAR

    public static final long MILLIS_IN_YEAR = 1000L * 60L * 60L * 24L * 365L; 
    
  9. 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;
    } 
    
  10. Implement the readExternal and writeExternal methods as required by the PortableObject interface.

  11. Implement the equals, hashCode, and toString object methods.

  12. The resulting class should look similar to the following.

    Example 3-3 Sample Contact Class

    package com.oracle.coherence.handson;
    
    package com.oracle.coherence.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;
     
    }
    

3.2.3 Creating the Driver Class

Create a driver class called ContactDriver to put Contact entries into the cache and retrieve them.

  1. Create a new Java class called ContactDriver in the Contacts project. See "Creating a Java Class" if you need detailed information.

    Name the Java class ContactDriver. Select the Generate Main Method check box.

  2. 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 3-4 Sample ContactDriver Class

    package com.oracle.coherence.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);
           Phone phone = new Phone ((short)11, (short)650, (short)506, 7000);
           Map map = new HashMap();
           map.put("home", phone);
                   
           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!!");
           } 
        }
    }
    

3.2.4 Creating Configuration Files and the Cache Server Executable

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 as part of the cache configuration file.

  1. Create a POF configuration file for the Contact, Address, and Phone objects.

    Create a POF configuration file for your data types. You can use the coherence-pof-config.xml file as a model. Define <user-type> elements for the Contact, Address, and Phone objects, assign them 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 home\oracle\labs directory. Save a copy of the coherence-pof-config.xml file in the labs directory as well. Example 3-5 illustrates a sample contacts-pof-config.xml file.

    Example 3-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>1002</type-id> 
          <class-name>com.tangosol.examples.model.Contact</class-name> 
        </user-type> 
        <user-type> 
          <type-id>1003</type-id> 
          <class-name>com.tangosol.examples.model.Address</class-name> 
        </user-type> 
        <user-type> 
            <type-id>1004</type-id> 
          <class-name>com.tangosol.examples.model.Phone</class-name> 
        </user-type> 
      </user-type-list>
      <allow-interfaces>true</allow-interfaces>
      <allow-subclasses>true</allow-subclasses>
    </pof-config>
    
  2. 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.

    Use ExamplesPartitionedPocScheme as the scheme-name and PartitionedPofCache as the service-name. The serializer section identifies the full path of the serializer class that will be used to transform the data. 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 examples-pof-config.xml.

    Save the file as contacts-cache-config.xml in the home\oracle\labs directory. Save a copy of the cache-config.dtd file in the labs directory as well. Example 3-6 illustrates a sample contacts-cache-config.xml file.

    Example 3-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>
    
  3. Create an executable to start the cache server.

    Add the following features to the file:

    • the location of the coherence.jar file to the classpath

    • the location of the data classes to the classpath

    • the location of the application class files

    • the location of the server configuration with -Dtangosol.coherence.cacheconfig

    • the command to start the default cache server com.tangosol.net.DefaultCacheServer

    Example 3-7 illustrates a sample cache server executable file.

    Example 3-7 Sample Cache Server Executable

    @echo off
    setlocal
    
    if (%COHERENCE_HOME%)==() (
        set COHERENCE_HOME=c:\oracle\product\coherence
    ) 
    
    set COH_OPTS=%COH_OPTS% -server -cp %COHERENCE_HOME%\lib\coherence.jar;C:\home\oracle\labs\Contacts\classesset 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
    

3.2.5 Running the Sample

  1. Stop any cache servers that may be running.

  2. Start the Contacts cache server by executing the following command:

    C:\oracle\product\coherence\examples\java>contacts-cache-server.cmd 
    

    Example 3-8 lists sample output from running contacts-cache-server.cmd.

    Example 3-8 Starting the POF Cache Server

    C:\oracle\product\coherence\examples\java>contacts-cache-server.cmd 2009-03-30 15:31:33.741/0.656 Oracle Coherence 3.5/450b (Internal) <Info> (thread=main, member=n/a): Loaded operational configuration from resource "jar:f.jar!/tangosol-coherence.xml"
    2009-03-30 15:31:33.756/0.671 Oracle Coherence 3.5/450b (Internal) <Info> (thread=main, member=n/a): Loaded operational overrides from resource "jar:file:!/tangosol-coherence-override-dev.xml"
    2009-03-30 15:31:33.756/0.671 Oracle Coherence 3.5/450b (Internal) <D5> (thread=main, member=n/a): Optional configuration override "/tangosol-coherence-ov2009-03-30 15:31:33.756/0.671 Oracle Coherence 3.5/450b (Internal) <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is
    
    Oracle Coherence Version 3.5/450b (Internal)
     Grid Edition: Development mode
    Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
    
    2009-03-30 15:31:34.350/1.265 Oracle Coherence GE 3.5/450b (Internal) <Info> (thread=main, member=n/a): Loaded cache configuration from file "C:\oracle\practs-cache-config.xml"
    2009-03-30 15:31:35.319/2.234 Oracle Coherence GE 3.5/450b (Internal) <D5> (thread=Cluster, member=n/a): Service Cluster joined the cluster with senior se
    2009-03-30 15:31:38.569/5.484 Oracle Coherence GE 3.5/450b (Internal) <Info> (thread=Cluster, member=n/a): Created a new cluster "cluster:0x2EDB" with Mem
    ddress=130.35.99.50:8088, MachineId=49714, Location=site:us.oracle.com,machine:tpfaeffl-pc,process:1204, Role=CoherenceServer, Edition=Grid Edition, Mode=
    82236332000001205982554FC2321F98
    2009-03-30 15:31:38.600/5.515 Oracle Coherence GE 3.5/450b (Internal) <D5> (thread=Invocation:Management, member=1): Service Management joined the cluster
    
    2009-03-30 15:31:39.116/6.031 Oracle Coherence GE 3.5/450b (Internal) <D5> (thread=DistributedCache:PartitionedPofCache, member=1): Service PartitionedPofember 12009-03-30 15:31:39.131/6.046 Oracle Coherence GE 3.5/450b (Internal) <Info> (thread=DistributedCache:PartitionedPofCache, member=1): Loading POF configuroherence/examples/resource/config2/contacts-pof-config.xml"
    2009-03-30 15:31:39.163/6.078 Oracle Coherence GE 3.5/450b (Internal) <Info> (thread=DistributedCache:PartitionedPofCache, member=1): Loading POF configurct/coherence/lib/coherence.jar!/coherence-pof-config.xml"2009-03-30 15:31:39.506/6.421 Oracle Coherence GE 3.5/450b (Internal) <Info> (thread=main, member=1): Started DefaultCacheServer...
    
    SafeCluster: Name=cluster:0x2EDB
    
    Group{Address=224.3.5.0, Port=35450, TTL=4}
    
    MasterMemberSet
      (
      ThisMember=Member(Id=1, Timestamp=2009-03-30 15:31:34.991, Address=130.35.99.50:8088, MachineId=49714, Location=site:us.oracle.com,machine:tpfaeffl-pc,p
      OldestMember=Member(Id=1, Timestamp=2009-03-30 15:31:34.991, Address=130.35.99.50:8088, MachineId=49714, Location=site:us.oracle.com,machine:tpfaeffl-pc
      ActualMemberSet=MemberSet(Size=1, BitSetCount=2
        Member(Id=1, Timestamp=2009-03-30 15:31:34.991, Address=130.35.99.50:8088, MachineId=49714, Location=site:us.oracle.com,machine:tpfaeffl-pc,process:12
        )
      RecycleMillis=120000
      RecycleSet=MemberSet(Size=0, BitSetCount=0
        )
      )
    
    Services
      (
      TcpRing{TcpSocketAccepter{State=STATE_OPEN, ServerSocket=130.35.99.50:8088}, Connections=[]}
      ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.4, OldestMemberId=1}
      InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1, Version=3.1, OldestMemberId=1}
      DistributedCache{Name=PartitionedPofCache, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257, BackupCount=1, AssignedPartitions=257, Bac
      )
    
  3. Set up the POF cache server to run in JDeveloper.

    Add additional CLASSPATH entries to the existing project properties. Navigate to Tools > Project Properties > Libraries and Classpath. Click Add JAR/Directory. In your project, add \home\oracle\labs to your CLASSPATH.

    Figure 3-3 Adding Labs and Configuration Files to the Classpath

    Adding Labs and Configuration Files to the Classpath
  4. Click Run/Debug/Profile to edit the runtime properties. Append the following line to the existing Java Options.

    -Dtangosol.coherence.cacheconfig=c:\home\oracle\labs\contacts-cache-config.xml
    

    Click OK to save your changes to the runtime configuration and OK again to dismiss the Project Properties dialog box.

  5. Rerun 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.

    Figure 3-4 Contacts Example Output Run from JDeveloper

    PersonExample Output Run from JDeveloper