Skip Headers
Oracle® Application Server Personalization Programmer's Guide
10g Release 2 (10.1.2)
B14051-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

B REProxyBatch Sample Program

The sample program for REProxyBatch consists of a Java program and a property file. The sample program, property file, and the tables required to run it are installed when you install OracleAS Personalization.

B.1 RE Batch Sample Program Overview

The Java program REBatchTest.java and the property file batchtest.txt are in the TBS directory on the system where you have installed OracleAS Personalization.

REBatchTest.java REProxyBatch allows you to execute a subset of recommendation functions in bulk. (REProxyRT scores one user/item at a time.) REProxyBatch reads a list of items/customers to be scored from an input table and writes the result to a new output table. This program reads its input from the property file batchtest.ini.

B.1.1 RE Batch Sample Program Output

The input item details (for rateItem and crossSellForItem) are derived from the OracleAS Personalization demo data. But in OracleAS Personalization, the model built on the same data is not guaranteed to produce the same rules each time that it is run. Therefore, it is possible that the item being rated cannot be rated with the current set of rules. The output tables will either be empty (zero rows) or will contain fewer than expected records (for example, if only some of the items are valid cross-sell candidates.).

B.2 Executing the RE Batch Sample Program

Follow these steps to execute the sample program:

  1. Install OracleAS Personalization.

  2. The code and data for the sample program is installed into the following directories when you install OracleAS Personalization:

    • The following code is installed in ${ORACLE_HOME}/dmt/reapi/batch/

      • batchtest.txt

      • README.txt

      • REBatchTest.java

    • The following items associated with the data used by the sample program are installed in ${ORACLE_HOME}/dmt/reapi/batch/sampleData

      • create_batch_demo_input_tables.sql

      • customer_list_in.ctl

      • customer_list_in.txt

      • item_list_in.ctl

      • item_list_in.txt

      • load_batch_demo_data.sh

  3. Run the shell script load_batch_demo_data.sh to load the following tables:

    • customer_list_in — Used for loadCustomerProfile. (The output of loadCustomerProfile is used by recommendTopItems and rateItem.)

    • item_list_in — Used by crossSellForItem.

  4. Compile the sample code. Your CLASSPATH variable should include the following zip/jar files:

    • ${ORACLE_HOME}/dmt/opreapi-batch.jar

    • ${ORACLE_HOME}/dmt/oputil.jar

    It also needs to include JDBC related jar/zip files:

    • ${ORACLE_HOME}/jdbc/lib/classes12.zip

  5. Change the property file to point to the appropriate entities. The comments in the property file and the file README.txt describes the exact changes that must be made.

  6. Run REBatchTest, with the property file name as an input parameter.

B.3 RE Batch Sample Program Code

This section contains the code for the sample program and its property file.

B.3.1 batchtest.txt

The properties file for the sample program follows. Note that you must replace RE details and input/output table details to reflect your installation.

###
### Input file for REProxyBatch sample program
### Before Running, you will need to replace the following dummy strings with actual information:
### 1. RE* details ( Url,Username,Password) to point to the RE.
### 2. Input and Output (Result) table details for each of the calls.

#A unique name for proxy
ProxyName=REB_1

#Recommendation Engine details
REUrl=jdbc:oracle:thin:@myDBUrl
REUsername=REUser
REPassword=REPassword

#Input customer table location
Input.Url=jdbc:oracle:thin:@myDBUrl
Input.Alias=myDBAlias
Input.Schema=User1
Input.Table=customer_list_in
Input.Username=User1
Input.Password=Password1

#Customer profile table
# This table is created in RE by loadCustomerProfile. Once created
# it is used for recommendTopItems and rateItem
CustProfile=MY_CUSTOMER_PROFILE

#
# Details for recommendTopItems
#
# Number of items to be recommended per customer
TopN.NumberOfItems=10
#TuningSettings details
#valid DataSourceTypes are ALL, DEMOGRAPHIC, PURCHASING, RATING, NAVIGATION
TopN.DataSourceType=ALL
#valid InterestDimension: PURCHASING, RATING, NAVIGATION
TopN.InterestDimension=PURCHASING
#valid PersonalizationIndex: LOW, MEDIUM, HIGH
TopN.PersonalizationIndex=MEDIUM
## ProfileDataBalance needs to be specified as part of the TuningSettings object
## but its value is not used by REProxyBatch
#valid ProfileDataBalance: HISTORY, CURRENT, BALANCED
TopN.ProfileDataBalance=HISTORY
#valid ProfileUsage:INCLUDE, EXCLUDE
TopN.ProfileUsage=INCLUDE
# FilteringSettings details
TopN.Taxonomy=1
#Category list is a series of numbers separated by "-"
TopN.CategoryList=1-2-3-4-5
#Valid CategoryMembership: ExcludeItems, ExcludeCategories, IncludeItems, IncludeCategories,
#       level, SubTreeItems, SubTreeCategories, AllItems, AllCategories
TopN.CategoryMember=AllItems
# Result table details
TopNResult.Url=jdbc:oracle:thin:@myDBUrl
TopNResult.Alias=myDBAlias
TopNResult.Schema=User2
TopNResult.Table=TopN_RESULTS
TopNResult.Username=User2
TopNResult.Password=Password2

#
# Details for rateItem
#
#TuningSettings details
RateI.ItemID=417
RateI.ItemType=MOVIE
RateI.DataSourceType=RATING
RateI.InterestDimension=RATING
RateI.PersonalizationIndex=LOW
## ProfileDataBalance needs to be specified as part of the TuningSettings object
## but its value is not used by REProxyBatch
RateI.ProfileDataBalance=HISTORY
RateI.ProfileUsage=INCLUDE
RateI.Taxonomy=1
# Result table details
RateIResult.Url=jdbc:oracle:thin:@myDBUrl
RateIResult.Alias=myDBAlias
RateIResult.Schema=User3
RateIResult.Table=RATEITEM_RESULTS
RateIResult.Username=User3
RateIResult.Password=Password3

#
# Details for crossSellForItem
#
#Input items table details
ItemTable.Url=jdbc:oracle:thin:@myDBUrl
ItemTable.Alias=myDBAlias
ItemTable.Schema=User4
ItemTable.Table=item_list_in
ItemTable.Username=User4
ItemTable.Password=User4
# Number of items to be recommended per input item
XSell.NumberOfItems=10
#TuningSettings details
XSell.DataSourceType=NAVIGATION
XSell.InterestDimension=NAVIGATION
XSell.PersonalizationIndex=HIGH
## ProfileDataBalance needs to be specified as part of the TuningSettings object
## but its value is not used by REProxyBatch
XSell.ProfileDataBalance=HISTORY
XSell.ProfileUsage=EXCLUDE
#FilteringSettings details
XSell.Taxonomy=1
XSell.CategoryList=1-3-5-7-9
XSell.CategoryMember=AllItems
# Result table details
XSellResult.Url=jdbc:oracle:thin:@myDBUrl
XSellResult.Alias=myDBAlas
XSellResult.Schema=User4
XSellResult.Table=XSELL_RESULTS
XSellResult.Username=User5
XSellResult.Password=Password5

B.3.2 REBatchTest.java

The sample program follows. Note that you must replace RE details and input/output table details to reflect your installation.

// Copyright (c) 2001, 2002, Oracle Corporation.  All rights reserved.  

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.sql.SQLException;

import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;

import oracle.dmt.op.re.base.Enum;
import oracle.dmt.op.re.base.FilteringSettings;
import oracle.dmt.op.re.base.Item;
import oracle.dmt.op.re.base.TuningSettings;
import oracle.dmt.op.re.reapi.batch.Location;
import oracle.dmt.op.re.reapi.batch.REProxyBatch;
import oracle.dmt.op.re.reexception.BadDBConnectionException;
import oracle.dmt.op.re.reexception.InvalidIDException;
import oracle.dmt.op.re.reexception.NullParameterException;
import oracle.dmt.op.re.reexception.StringTooLargeException;

/**
 * Class REBatchTest
 * This class demonstrates the use of REProxyBatch API included with Oracle
 * Personalization. REProxyBatch allows you to execute a subset of 
 * recommendation functions in bulk. (REProxyRT scores one user/item at a time.)
 *
 * REProxyBatch reads a list of items/customers to be scored from an input table
 * and writes the result to a new output table. This program reads its input
 * from a property file supplied as input. The tags used in the input file are
 * listed here as static constants in CAPITAL LETTERS.
 *
 * Before you execute the program, you must edit the property file batchtest.ini
 * to reflect your environment.
 *
 * @author Oracle Corporation
 */
public class REBatchTest
{

  static private Properties m_Props;

  static private boolean m_Verbose;
  static private final String s_Title = "REBatchTest";
  static final boolean debug = true;

  // These tags appear in the input property file.
  static String TOPN = "TopN";
  static String XSELL = "XSell";
  static String RITEM = "RateI";
  static String DSTYPE = "DataSourceType";
  static String INTDIMENSION = "InterestDimension";
  static String PDBALANCE = "ProfileDataBalance";
  static String PUSAGE = "ProfileUsage";
  static String PINDEX = "PersonalizationIndex";
  static String NUMOFITEMS = "NumberOfItems";
  static String PROXYNAME = "ProxyName";
  static String REURL = "REUrl";
  static String REUSERNAME = "REUsername";
  static String REPASSWORD = "REPassword";
  static String URL = "Url";
  static String ALIAS = "Alias";
  static String USNAME = "Username";
  static String PSWORD = "Password";
  static String SCHEMA = "Schema";
  static String TABLE = "Table";
  static String INPUT = "Input";
  static String CUSTPROFILE = "CustProfile";
  static String ITEMID = "ItemID";
  static String ITEMTYPE = "ItemType";
  static String RESULT = "Result";
  static String TAXONOMY = "Taxonomy";
  static String ITEMTAB = "ItemTable";
  static String CATEGORYS = "CategoryList";
  static String CATNODE = "CategoryMember";
  static String DOT = ".";

  // These variables are initialized from the property file.
  static private String m_proxyName; // Name of the REProxyBatch instance
  // Recommendation Engine Details
  static private String m_reUrl;
  static private String m_reUserName;
  static private String m_rePassword;

  // Location of the customer table; the customer table must be created before
  // this program can be run.
  // Refer to the REProxyBatch document for the expected schema.
  static private Location m_inCustTable;
  // Location of the items table; the itemstable must be created before this
  // program can be run.
  // Refer to the REProxyBatch document for the expected schema.
  static private Location m_inItemTable;

  // Name of the customer profile table created in RE after loadCustomerProfile
  // is invoked.
  static private String m_custProfile;

  /**
  * main Entry point
  * @param args
  **/
  public static void main(String[] args)
  {
    long lStart;
    long lTotal = 0;
    REProxyBatch proxy;
    // Name of the property file should be passed as an input.
    if (args.length < 1) {
      System.out.println("Usage: REBatchTest FullpathToPropfile");
      System.exit(-1);
    }
    // Initialize class variables using the property file.
    try {
      new REBatchTest(args[0]);
    } catch (Exception ioe) {
      System.out.println("Error in main(): " + ioe.getMessage());
      ioe.printStackTrace();
      System.exit(-1);
    }
    // Start a timer.
    lStart = System.currentTimeMillis();
    try {
      // Initialize a REProxyBatch object
      proxy = new REProxyBatch(m_proxyName,
                                m_reUrl,
                                m_reUserName,
                                m_rePassword);

      // Invoke loadCustomerProfiles.
      System.out.println("Loading customer profile.");
      proxy.loadCustomerProfiles(
        m_inCustTable, // Name of the input customer IDs table 
        m_custProfile); // Name of the profile table from loadCustomerProfiles
      System.out.println("Completed loading customer profile, in the table: " 
                          + m_custProfile + " in current RE schema.");

      // Initialize inputs needed for recommendTopItems
      // Number of items to recommend (per customer)
      int nRec = getNumOfItems(TOPN);
      // Initialize TuningSettings object from the property file
      TuningSettings tuningT = getTuning(TOPN);
      // Initialize FilteringSettings object from the property file
      FilteringSettings filterT = getFilter(TOPN);
      // Location of the result table
      Location resLocT = getLoc(addStr(TOPN, RESULT));
      System.out.println("Recommending top items. Customer profile table name:" 
                          + m_custProfile );

      // Invoke recommendTopItems
      proxy.recommendTopItems(
        m_custProfile, // Customer profile table name, from loadCustomerProfiles
        nRec, // Number of recommendations per customer.
        tuningT, // TunningSettings to be used for recommendations
        filterT, // FilteringSettings to be used for recommendations
        resLocT); // Location of the result table
      System.out.println("Completed recommendTopItems.");
      System.out.println("Result table details: Schema: " + 
                          resLocT.getSchemaName() + ", Table Name: " 
                          + resLocT.getTableName() + ", Database: " 
                          + resLocT.getDBAlias());

      // Initialize inputs needed for rateItem
      // Read the item to be rated. This single item is rated for all the 
      // customers in the customer profiles table.
      Item item = getItem(RITEM);
      // Taxonomy to be used for rating
      int nTaxID = Integer.parseInt(m_Props.getProperty(addStr(RITEM, DOT, 
                                    TAXONOMY)));
      // Initialize TuningSettings object from the property file
      TuningSettings tuningR = getTuning(RITEM);
      // Location of the result table,
      Location resLocR = getLoc(addStr(RITEM, RESULT));
      System.out.println("Rating item.");
      System.out.println("Rating item: " + item.getID() + "," + item.getType() +
                          ". Customer profile table name:" + m_custProfile );
      // Invoke rateItem
      proxy.rateItem(
        m_custProfile, // Customer profile table name, from loadCustomerProfiles
        item, // Item to be rated
        nTaxID, // Taxonomy to be used for rating
        tuningR, // TunningSettings to be used for rating
        resLocR); // Location of the result table
      System.out.println("Completed rateItem.");
      System.out.println("Result table details: Schema: " + 
                          resLocR.getSchemaName() + ", Table Name: " + 
                          resLocR.getTableName() + ", Database: " + 
                          resLocR.getDBAlias());

      // Invoke purgeCustomerProfiles
      // Cross sell is an item based recommendation call. Hence it does not need
      // the loaded customer profile table.
      System.out.println("Purging customer profile: " + m_custProfile + 
                        " from current RE.");
      proxy.purgeCustomerProfiles(m_custProfile);

      // crossSellForItem
      // Initialize inputs needed for rateItem
      // Number of cross sell items to be recommended (per input item)
      nRec = getNumOfItems(XSELL);
      // Initialize TuningSettings object from the property file
      TuningSettings tuningX = getTuning(XSELL);
      // Initialize FilteringSettings object from the property file
      FilteringSettings filterX = getFilter(XSELL);
      // Location of the result table
      Location resLocX = getLoc(addStr(XSELL, RESULT));
      System.out.println("Recommending cross sell for item. Input table " +
                        "details: Schema: " + m_inItemTable.getSchemaName() + 
                        ", Table Name: " + m_inItemTable.getTableName() + 
                        ", Database: " + m_inItemTable.getDBAlias());

      // Invoke crossSellForItem
      proxy.crossSellForItem(
        m_inItemTable, // Name of the input items table created by the end user
        nRec, // Number of cross sell items to be recommended per input item
        tuningX, // Tunning settings to be used for recommendations
        filterX, // Filtering settings to be used for recommendations
        resLocX); // Location of the result object
      System.out.println("Completed crossSellForItem.");
      System.out.println("Result table details: Schema: " + 
                          resLocX.getSchemaName() + ", Table Name: " + 
                          resLocX.getTableName() + ", Database: " + 
                          resLocX.getDBAlias());

      // Destroy the proxy object (to free up the database connections).
      System.out.println("Completed REProxyBatch operations. " +
                        "Destroying the proxy.");
      proxy.destroy();
      proxy = null;
    } catch (NullParameterException npe) {
      System.out.println(npe.getMessage());
      npe.printStackTrace();
    } catch (BadDBConnectionException bde) {
      System.out.println(bde.getMessage());
      bde.printStackTrace();
    } catch (SQLException se) {
      System.out.println(se.getMessage());
      se.printStackTrace();
    } catch (Exception e) {
      System.out.println(e.getMessage());
      e.printStackTrace();
    }
  }

  /**
   * Constructor
   * Read the property file.
   */
  public REBatchTest(String sProp)
  throws FileNotFoundException, IOException, StringTooLargeException
  {
    getConfig(sProp);
  }

  /**
  ** All the remaining code in this file deals with reading different values
  ** from the property file and initializing class variables.
  **/

  /*
  * A helper function returning appended string
  */
  static private String addStr(String s1, String s2) {
    StringBuffer sb = new StringBuffer(s1);
    sb.append(s2);
    return (sb.toString());
  }
  /*
  * A helper function returning appended string
  */
  static private String addStr(String s1, String s2, String s3) {
    StringBuffer sb = new StringBuffer(s1);
    sb.append(s2).append(s3);
    return (sb.toString());
  }
  /*
  ** Read recommendation engine details from the property file.
  **
  */
  static private void getConfig(String propFile)
  throws FileNotFoundException, SecurityException, IOException, 
        StringTooLargeException {
    FileInputStream is = new FileInputStream(propFile);
    String RE = "RE";

    try {
      m_Props = new Properties();
      m_Props.load(is);
      // RE achema access info
      m_proxyName = m_Props.getProperty(PROXYNAME);
      // Recommendation Engine database details
      m_reUrl = m_Props.getProperty(addStr(RE, URL));
      m_reUserName = m_Props.getProperty(addStr(RE, USNAME));
      m_rePassword = m_Props.getProperty(addStr(RE, PSWORD));

      // Input customer table
      m_inCustTable = getLoc(INPUT);
      // Input items table
      m_inItemTable = getLoc(ITEMTAB);
      // Customer profile table name
      m_custProfile = m_Props.getProperty(CUSTPROFILE);
    } catch (SecurityException se) {
      System.err.println("Can't read the property file: " + propFile + "!");
      m_Props = null;
    }
  }
  /*
  ** Read number of items from the property file.
  **
  */
  static private int getNumOfItems(String sPrix) {
    return (Integer.parseInt(m_Props.getProperty(addStr(sPrix, DOT, 
                                                        NUMOFITEMS))));
  }
  /*
  ** Read location object from the property file.
  **
  */
  static private Location getLoc(String sPrix)throws StringTooLargeException{
    String sUrl = null;
    String sAlias = null;
    String sTable = null;
    String sSchema = null;
    String sPsword = null;
    String sUsname = null;
    Enumeration propNames = m_Props.propertyNames();
    boolean bFound = false;

    while (propNames.hasMoreElements()) {
      String name = (String)propNames.nextElement();
      if (name.startsWith(sPrix)) {
        // Url
        if (name.endsWith(URL)) {
          sUrl = m_Props.getProperty(name);
          bFound = true;
        }
        // Alias
        if (name.endsWith(ALIAS))
          sAlias = m_Props.getProperty(name);
        // Schema
        if (name.endsWith(SCHEMA))
          sSchema = m_Props.getProperty(name);
        // Table
        if (name.endsWith(TABLE))
          sTable = m_Props.getProperty(name);
        // Username
        if (name.endsWith(USNAME))
          sUsname = m_Props.getProperty(name);
        // Password
        if (name.endsWith(PSWORD))
          sPsword = m_Props.getProperty(name);
      }
    }
    return (bFound ? new Location(sAlias, sUrl, sSchema, sTable, sUsname, 
                                  sPsword) : null);
  }
  /*
  ** Read item details from the property file.
  **
  */
  static private Item getItem(String sPrix) throws StringTooLargeException, 
                                                    InvalidIDException, 
                                                    NullParameterException{
    String sType = null;
    long lID = 0;
    Enumeration propNames = m_Props.propertyNames();
    boolean bFound = false;

    while (propNames.hasMoreElements()) {
      String name = (String)propNames.nextElement();
      if (name.startsWith(sPrix)) {
        // ID
        if (name.endsWith(ITEMID)) {
          lID = Long.parseLong(m_Props.getProperty(name));
          bFound = true;
        }
        // Type
        if (name.endsWith(ITEMTYPE))
          sType = m_Props.getProperty(name);
      }
    }
    return (bFound ? new Item(sType, lID) : null);
  }
  /*
  ** Read tuning settings from the property file.
  **
  */
  static private TuningSettings getTuning(String sPrix) throws 
                                                        NullParameterException {
    Enumeration propNames = m_Props.propertyNames();
    Enum.DataSourceType dsType = null;
    Enum.InterestDimensionType iDimension = null;
    Enum.PersonalizationIndexType pIndex = null;
    Enum.ProfileDataBalanceType pdBalance = null;
    Enum.ProfileUsageType pUsage = null;

    while (propNames.hasMoreElements()) {
      String name = (String)propNames.nextElement();
      if (name.startsWith(sPrix)) {
        // datasource type
        if (name.endsWith(DSTYPE)) {
          String sDsType = m_Props.getProperty(name);
          dsType = Enum.DataSourceType.getType(sDsType);
        }
        // interest dimension
        if (name.endsWith(INTDIMENSION)) {
          String sIntDim = m_Props.getProperty(name);
          iDimension = Enum.InterestDimensionType.getType(sIntDim);
        }
        // personalization index
        if (name.endsWith(PINDEX)) {
          String spIndex = m_Props.getProperty(name);
          pIndex = Enum.PersonalizationIndexType.getType(spIndex);
        }
        // profiledata balance
        if (name.endsWith(PDBALANCE)) {
          String sPdBalans = m_Props.getProperty(name);
          pdBalance = Enum.ProfileDataBalanceType.getType(sPdBalans);
        }
        // profile usage
        if (name.endsWith(PUSAGE)) {
          String spUse = m_Props.getProperty(name);
          pUsage = Enum.ProfileUsageType.getType(spUse);
        }
      }
    }
    return (new TuningSettings(dsType, iDimension, pIndex, pdBalance, pUsage));
  }
  /*
  ** Read list of categories from the property file.
  **
  */
  static private long [] getCatList(String str) {
    StringTokenizer stz = new StringTokenizer(str, "-");
    int nE = stz.countTokens();
    if (nE < 1)
      return null;

    long [] lAry = new long [nE];
    int n = 0;

    while (stz.hasMoreTokens()) {
      String tmp = stz.nextToken();
      tmp.trim();
      lAry[n++] = Long.parseLong(tmp);
    }
    return lAry;
  }
  /*
  ** Read filtering settings from the property file.
  **
  */
  static private FilteringSettings getFilter(String sPrix)
  throws Exception {
    boolean bFound = false;
    Enumeration propNames = m_Props.propertyNames();
    int nTaxoID = 0;
    long [] catList = null;
    Enum.CategoryMembershipType cmType = null;

    while (propNames.hasMoreElements()) {
      String name = (String)propNames.nextElement();
      if (name.startsWith(sPrix)) {
        // Taxonomy
        if (name.endsWith(TAXONOMY))
          nTaxoID = Integer.parseInt(m_Props.getProperty(name));
        if (name.endsWith(CATEGORYS)) {
          String sCList = m_Props.getProperty(name);
          catList = getCatList(sCList);
        }
        if (name.endsWith(CATNODE)) {
          bFound = true;
          String sCmType = m_Props.getProperty(name);
          cmType = Enum.CategoryMembershipType.getType(sCmType);
        }
      }
    }
    return bFound ? FilteringSettings.setFilteringSettings(nTaxoID, catList, 
                                                          cmType) : null;
  }

  protected static String getFunctionName(String trace) {
   // now go through the string to find what you want
   trace = trace.substring(trace.indexOf('\n')).trim();
   trace = trace.substring(trace.indexOf(' ') + 1);
   //trace = trace.substring(0, trace.indexOf(')'));
   return (trace);
  }

}