Previous     Contents     Index     Next     
iPlanet Market Maker 4.5 Customization Guide



Chapter 3   Customizing Modules


This chapter contains the following sections:



What You Can Customize

This section describes the two general methods you can use to customize iPlanet Market Maker modules.

Module properties let you customize the messages and configurations of modules. Each module has a set of associated property files that provide access to the properties.

Event handlers control the communication between any user activity in a Java server web page (JSP) and the resulting action taken by the module. You can extend the module event handlers to create new functions and capabilities.



Configuring Module Properties



To edit messages and configure the modules, you edit the proper files in the classes directory. You edit property files in a text editor. Each module has four property files, as shown in Table 3-1. The module name is the prefix (not shown in the table) for each of the property files. The property files are in the <ias_server_root>/ias/APPS/imm40/imm40/WEB-INF/classes directory.

The property files have the following characteristics.

  • Changes to property files apply only after you restart iPlanet Market Maker.

  • The "#" character specifies a comment. You use this character at the beginning of each line in the property file that you want to be ignored.

  • Each property key and value must be on one line.

    Table 3-1    Property Files

    Property File Name

    Description

    <Module Name>Messages.properties  

    Contains parameterized messages, usually error and notification messages.

    This file must be localized.  

    <Module Name>Strings.properties  

    Contains non-parameterized messages.

    This file must be localized.  

    <Module Name>Display.properties  

    Contains parameterized messages that are only displayed in JSPs. Not every module has this type of property file.

    This file must be localized.  

    <Module Name>Configuration.properties  

    Contains configuration parameters.  


Property Keys and Values

In property files, each property has a property key and property value specified as a name-value pair, separated by an equal sign ("="). Property keys are usually integer values. Each module is assigned a block of 10,000 property key numbers. Property keys cannot contain the "+", "=", or "*" characters. Key numbers are unique for each module. Do not change existing property keys. To do so might disable some functionality.

There are three types of name-value pairs:

  • Simple name-value pairs.

    This most common type of name-value pair has a property key and a property value, such as 7=false.

  • Arrays

    An array name-value pair can contain multiple values. For example:

    status[0]=closed
    status[1]=open

    Defines a property named status with values of closed and open.

  • Hash table structures

    A hash table can contain multiple values with unique names. For example:

    field[size]=10
    field[description]=Enter the address of the sender

    Defines a property named field with sub-values of size, with a value of 10, and description, with a value of Enter the address of the sender.


Parameters In Messages

Some properties in the property files have parameterized messages. For example,

123=Exception {0} on database {1}

defines a parameterized message with 2 parameters. Usually the parameters passed to the messages are localized strings. Do not change or remove these values.

See java.text.MessageFormat documentation in JDK for details about parameterized messages.


Localizing Property Files

As mentioned in Table 3-1, the Messages, Strings, and Display property files must be localized. For each language supported by iPlanet Market Maker, there is a property file. Property files are Java Resource Bundles, which are discussed in detail in java.util.PropertyResourceBundle and java.util.ResourceBundle. Consult the JDK documentation for more details.

Each iPlanet Market Maker locale has a language code and a country code. Property files are named based on the supported locale. For example, AuctionMessages_en.properties is the name of the English property files (en is the language code for English). AuctionMessages_fr.properties is the name of the French translation of the property file.

It is important to note that at this time, all property files (for all modules and their localizations) are in a single shared directory that must be part of the CLASSPATH.


Encrypting Property Files

Because many properties contain sensitive information, an encryption mechanism is necessary to protect their values. Currently only VortexConfiguration.properties contains encrypted values. But any of the module configuration properties can be encrypted by the technique described in this section. Keep in mind that only the Configuration property file (and not the Messages, Strings, or Display files) can be encrypted.

There are two special purpose markers used within property keys to denote encrypted values:

  • The "+" character denotes an obfuscated property. Obfuscation is a process of byte swapping an XORing, which makes a property value unreadable.

    Obfuscation is not encryption. It is used to make properties that cannot be encrypted (because they drive the encryption process itself) hard to read.

  • The "*" character denotes an encrypted property. All encryption in iPlanet Market Maker is done with JCE 1.2.1, using DES encryption with a key chosen at install time.

It is important to remember that encrypted and obfuscated properties can only be edited after being decrypted. The process of editing an encrypted property file (for example,VortexConfiguration.properties) is as follows:

  1. Decrypt the property file using the encrypt.sh shell script. The syntax for this command is

    encrypt.sh decrypt <filename>

    You are prompted to enter the password protecting the encryption key. This password was chosen at install time.

  2. Edit the property file using a text editor.

    Remember that if you remove the "*" character from the property key, the property is not encrypted.

  3. Re-encrypt the property using the encrypt.sh shell script. The syntax for this command is

    encrypt.sh encrypt <filename>

  4. Again, you are prompted for the encryption password. It is very important that you enter the same password chosen at install time.



Extending Event Handling

Event handling refers to the process of communicating from the user interface (JSPs) to the modules, then back to update the JSPs. A user interaction in a page, such as clicking on a button, needs to call the appropriate module functionality and return the results to the JSP. Event handling provides the mechanisms to complete these processes.

A user interaction in a JSP generates an action code. Each module has an XML file called Events.xml (prefixed with the module name) that maps each action code to a corresponding event handler. The event handler communicates with the back-end processes and creates an instance of a class called PresentationBean to update the JSP accordingly. This flow is shown in Figure 3-1.

In the iPlanet Market Maker back-end architecture, modules have components called "Managers" and "Remotables". Managers are the point of access to the "fine-grained objects" within a module (a catalog, a catalog item, a community member, and so on). Remotables act on behalf of the fine-grained objects to provide efficient communication back and forth between the databases.

Note that event handlers are not managers or remotables, but communicate with them. Details about the iPlanet Market Maker architecture are not covered in this guide.

Figure 3-1    Overview of the Event Handling Flow



Interpreting Event Handlers

Before you can extend the capabilities of event handlers, you need to understand how they work. This following list describes the events that take place when click on a link or button in the iPlanet Market Maker user interface.

  • Each user action in a JSP generates an action code.

  • Each action code invokes a corresponding event handler.

  • The event handler implements the IEventHandler interface, which invokes the execute() method. For more information about the execute() method, see the "Using the execute() Call" section.

  • The execute() method returns a DisplayBean Java object. This object specifies which JSP is to be displayed.

  • The JSP contains HTML and Java code that defines how to display the elements in the DisplayBean.

To customize functionality, you need to identify the action codes, event handlers, DisplayBeans, and JSPs. To identify all these elements, you can turn on a tracing and debugging capability. To activate this capability, follow these steps.

  1. In the VortexConfiguration.properties file, find the following lines.

    #CFG_DEBUG_LEVEL (off=3, terse=7, verbose=15, vverbose=31 debug window=40)

    # - Debug level for the Market Maker system.

    5=3

  2. To turn on the debug window capability, change 5=3 to 5=40.

  3. In the VortexConfiguration.properties file, find the following lines.

    #CFG_DEBUG_MODULES_TO_DEBUG. These are defined as follows: MODULE_BASE=0,

    #MODULE_RFX=1, MODULE_AUCTION=2, MODULE_CATALOG=3, MODULE_PRICING=4,

    #MODULE_COMMUNITY=5, MODULE_DISPLAY=6, MODULE_OMS=7, MODULE_CATALOG_IMPORT=8

    # - Enable/Disable module level debugging.

    #27[0]=0

    #27[1]=1

    #27[2]=2

    #27[3]=3

    #27[4]=4

    #27[5]=5

    #27[6]=6

    #27[7]=7

    #27[8]=8

  4. Change 27[0] = 0 to 27[0] = 6.

    Note that the value on the right side of the equal sign specifies the module to debug. The array index on the left side is just a placeholder to read in multiple values.

  5. Restart the iPlanet Application Server (iAS) and the iPlanet Web Server (iWS).

    The debugging window is now enabled.

When you restart the iPlanet Market Maker software and click on a link or button, information about action codes, event handlers, DisplayBeans, and JSPs is displayed in the debug window.

Here is an example of a New Requisition form in the Order Management module.

The following debug window output results when the Create Requisition JSP is displayed.

Note that the numbers in the left column are for documentation purposes and do not actually appear in the debug window.

-----------------------------------------------------------------------

1. PARAMETER 'FilterByKeyword' = ''

PARAMETER 'FilterByEnum' = '-1'

PARAMETER 'FilterBySelector' = '0'

PARAMETER 'VDSP_PAGEID' = '63'

PARAMETER 'VDSP_UID' = '5b6abf:de3f060a01:-2222'

PARAMETER 'VDSP_ACTION'[0] = 'top,60012,4'

PARAMETER 'VDSP_ACTION'[1] = 'top,60012,4,top_c_Requisitions,70004,0'

2. Handler for code

com.iplanet.ecommerce.vortex.oms.display.OMSDisplayModule ACT REQ ADD REQ(70004)

com.iplanet.ecommerce.vortex.oms.display.ReqAddReqEventHandler

outgoing actionCode:

com.iplanet.ecommerce.vortex.oms.display.OMSDisplayModule ACT REQ ADD REQ(70004), index = 0

3. JSP being displayed: oms/ReqAddReq.jsp

4. Display Bean:

       ReqAddLink class com.iplanet.ecommerce.vortex.display.NVPLinkGen

       ReqCancelLink class com.iplanet.ecommerce.vortex.display.NVPLinkGen

       Requisition class com.iplanet.ecommerce.vortex.display.DisplayBean

            Creator

            Owner

            SourceType

-----------------------------------------------------------------------

  1. The PARAMETER lines indicate the CGI name/value pairs that can be accessed by the execute() method of the event handler. They are not relevant in this example.

  2. Action code 70004 for the New Requisition button triggered the generation of the Create Requisition page. The execute() method of the ReqAddReqEventHandler event handler was invoked to produce the DisplayBean.

  3. ReqAddReq.jsp is the name of the JSP for the Create Requisition page. If you wanted to customize the Create Requisition page, ReqAddReq.jsp is the name of the file to edit.

  4. The DisplayBean contains the following elements used by the JSP.

    • ReqAddLink of type NVPLinkGen corresponds to the Create URL.

    • ReqCancelLink of type NVPLinkGen corresponds to the Cancel URL.

    • Requisition is itself a DisplayBean with the following sub-elements. Note that indentation represents a nested DisplayBean object (a DisplayBean that contains as an element a display bean).

      Creator is the requisitions creator and corresponds to Ebbs, Ken.

      Owner is the requisitions owner and corresponds to Ebbs, Ken.

      SourceType is the source type of the requisition and corresponds to Other.

The DisplayBean with the contents shown in step 4 are passed to oms/ReqAddReq.jsp. This JSP contains the HTML and Java code that renders the contents of the DisplayBean.


Customizing JSPs

Before you customize the iPlanet Market Maker JSPs, it is important to understand how to edit and deploy them under iAS. The guidelines for customizing JSPs are as follows.

  1. Do not edit JSPs directly in your production web server. Instead make and test changes in a development environment.

  2. Make a backup copy of the JSP.

  3. Edit the JSP with any HTML or text editor. Typically HTML editors do not work well for JSPs because of the amount of embedded Java code. In general when editing a JSP, be careful not to edit Java code.

  4. After completing you edits, you can optionally compile the JSP. Because the JSP contains both HTML and Java code, this compilation ensures that you have not introduced syntax errors in the JSP. If you do not compile the JSP manually, iAS compiles it the first time it is accessed in a browser. The disadvantage of this approach is that you must view the iAS error log to see compilation errors.

  5. Access the JSP in the browser. In most cases, you do not have to restart the application server, but if your changes do not appear, you try restarting iAS.

The following example shows the ReqAddReq.jsp JSP discussed in the "Interpreting Event Handlers" section:



<!-- Copyright © 2002 Sun Microsystems, Inc. All rights reserved.-->
<%@ include file="../include/OMSInclusionHeader.jsp"%>
<%PresentationBean bean = (PresentationBean)request.getAttribute("DisplayBean");%>
<%DisplayBean rbean = bean.getDisplayBean(DF_REQUISITION_BEAN);%>
<%String requiredField = "<FONT CLASS=\"REQUIRED\">*</FONT>";%>
<FORM method=POST action="<%=bean.getPortalURL()%>" name="<%=bean.getFormName()%>">
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" WIDTH="95%" ALIGN="center">
<TR>
<TD Class="mainTitle" ALIGN="left">OMS : Create Requisition<BR>&nbsp;</TD>
</TR>
<TR>
<TD>


   <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" HEIGHT="33" WIDTH="100%">
   <TR>
   <TD Class="pagetitle" ALIGN="left" VALIGN="top" WIDTH="1%"><IMG HEIGHT="15" SRC="/@IMM_DOCROOT@/images/curve_left.gif"></TD>
   <TD Class="pagetitle" ALIGN="left" VALIGN="middle">&nbsp;</TD>
   <TD Class="pagetitle" ALIGN="right" VALIGN="middle">

      <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" HEIGHT="19">
      <TR>
       <TD NOWRAP Class="dark"><IMG
SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"left.gif"%>" BORDER="0"></TD>
   <TD NOWRAP Class="dark"><A Class="buttonText" href="JavaScript:document.<%= bean.getFormName() %>.action =
   <%=bean.getNavigation(REQ_CANCEL_LINK) %>';
formSubmit(document.<%= bean.getFormName() %>, 'REQ_CANCEL_LINK');">Cancel</A></TD>
    <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"right.gif"%>" BORDER="0"></TD>
    <TD NOWRAP WIDTH="8" Class="medium">&nbsp;</TD>
    <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"left.gif"%>" BORDER="0"></TD>
    <TD NOWRAP Class="dark"><A Class="buttonText" href="JavaScript:document.<%= bean.getFormName() %>.action =
'<%=bean.getNavigation(REQ_ADD_LINK) %>';
formSubmit(document.<%= bean.getFormName() %>, 'REQ_ADD_LINK');">Create</A></TD>
    <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"right.gif"%>" BORDER="0"></TD>
    </TR>
   </TABLE>
</TD>
   <TD Class="pagetitle" ALIGN="right" VALIGN="top" WIDTH="1%"><IMG HEIGHT="15" WIDTH="17" SRC="/@IMM_DOCROOT@/images/curve_right.gif"></TD>
   </TR>
   </TABLE>
</TD>
</TR>
<TR>
<TD>
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" WIDTH="100%" ALIGN="center">
   <TR><TD width="3%">&nbsp;</TD><TD COLSPAN="2"><FONT Class="required">*</FONT>Indicates Required Field.</FONT></TD><TD
width="3%">&nbsp;</TD></TR>
<TR><TD width="3%">&nbsp;</TD>
<TD ALIGN="center" COLSPAN="2">
<%@ include file="OMSError.jsp" %>
</TD><TD width="3%">&nbsp;</TD></TR>
  <TR>
  <TD width="3%">&nbsp;</TD>
  <TD Class="fieldtag" WIDTH="20%" HEIGHT="24" NOWRAP>Creator:&nbsp;
  </TD>
   <TD Class="fieldvalue" NOWRAP><%=rbean.getStringValue(DF_CREATOR)%>
   </TD>
   <TD width="3%">&nbsp;</TD>
     </TR>
        <TR><TD width="3%">&nbsp;</TD>
           <TD Class="fieldtag" WIDTH="20%" HEIGHT="24" NOWRAP>
             Owner:&nbsp;
            </TD>
           <TD Class="fieldvalue" NOWRAP>
             <%=rbean.getStringValue(DF_OWNER)%>
           </TD>
   <TD width="3%">&nbsp;</TD>
          </TR>
          <TR>
        <TD width="3%">&nbsp;</TD>
          <TD Class="fieldtag" WIDTH="20%" HEIGHT="24" NOWRAP>
                Source:&nbsp;
          </TD>
          <TD Class="fieldvalue" NOWRAP>
            <%=rbean.getStringValue(DF_SOURCE_TYPE)%>
          </TD>
        <TD width="3%">&nbsp;</TD>
          </TR>
          <TR>
        <TD width="3%">&nbsp;</TD>
              <TD Class="fieldtag" WIDTH="20%" HEIGHT="24" NOWRAP">
            <%=requiredField%>Description:&nbsp;<%=checkError(rbean, DF_DESCRIPTION)%>
            </TD>
            <TD Class="fieldvalue" NOWRAP>
                    <INPUT TYPE=TEXT size="25" NAME="<%=rbean.getRealKey(DF_DESCRIPTION)%>">
    </TD>
    <TD width="3%">&nbsp;</TD>
       </TR>
       </TABLE>
<BR>
   <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" HEIGHT="33" WIDTH="100%" ALIGN="center">
       <TR>
        TD Class="pagetitle" ALIGN="left" VALIGN="bottom" WIDTH="1%"><IMG HEIGHT="15"
SRC="/@IMM_DOCROOT@/images/curve_bottom_left.gif"></TD>
       <TD Class="pagetitle" ALIGN="left" VALIGN="middle">&nbsp;</TD>
       <TD Class="pagetitle" ALIGN="right" VALIGN="middle">
           <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0" HEIGHT="19">
       <TR>
        <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"left.gif"%>" BORDER="0"></TD>
       <TD NOWRAP Class="dark"><A Class="buttonText" href="JavaScript:document.<%= bean.getFormName() %>.action =
'<%=bean.getNavigation(REQ_CANCEL_LINK) %>';
formSubmit(document.<%= bean.getFormName() %>, 'REQ_CANCEL_LINK');">Cancel</A></TD>
       <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"right.gif"%>" BORDER="0"></TD>
  <TD NOWRAP WIDTH="8" Class="medium">&nbsp;</TD>
        <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"left.gif"%>" BORDER="0"></TD>
  <TD NOWRAP Class="dark"><A Class="buttonText" href="JavaScript:document.<%= bean.getFormName() %>.action =
'<%=bean.getNavigation(REQ_ADD_LINK) %>';
formSubmit(document.<%= bean.getFormName() %>, 'REQ_ADD_LINK');">Create</A></TD
        <TD NOWRAP Class="dark"><IMG SRC="<%="/@IMM_DOCROOT@/images/buttons/"+FILE_PREFIX+"right.gif"%>" BORDER="0"></TD>
     </TR>
      </TABLE>
   /TD>
       <TD Class="pagetitle" ALIGN="right" VALIGN="bottom" WIDTH="1%"><IMG HEIGHT="15" WIDTH="17"
SRC="/@IMM_DOCROOT@/images/curve_bottom_right.gif"></TD>
     </TR>
      </TABLE>
</TD>
</TR>
<TR><TD NOWRAP WIDTH="760" BGCOLOR="#FFFFFF"><!--this row is to force the minimum table width to 760-->&nbsp;</TD></TR>
</TABLE>
<%=bean.getButtonInfo()%>
</FORM>


Here is a list of conventions and comments about this JSP that is relevant to customization.

  • Characters surrounded by <!-- ...--> characters are comment.

  • Characters surrounded by <%= ... %> indicate Java code.

  • .HTML cannot be embedded in Java code blocks (<%= ... %>).

  • <%PresentationBean bean = (PresentationBean)request.getAttribute("DisplayBean");%> is Java code that sets up a variable called bean. This variable contains the DisplayBean created by the event handler invoked prior to rendering the JSP. In this case, looking at the debugging output shown in the "Interpreting Event Handlers" section, the event handler is ReqAddReqEventHandler. This pattern is common to all iPlanet Market Maker JPSs.

  • <%DisplayBean rbean = bean.getDisplayBean(DF_REQUISITION_BEAN);%> creates a variable called rbean, which is a nested DisplayBean nested within bean. The DF_REQUISITION_BEAN field is a Java String constant.

  • <%=rbean.getStringValue(DF_CREATOR)%> shows an example of fetching a String field from a DisplayBean.

  • .It is possible to subclass the ReqAddReqAddEventHandler event handler, override the execute() method, add your own fields to the DisplayBean (using DisplayBean.put("myField", "myValue")). This data can then be rendered in the JSP using bean.getStringValue("myField").

  • Be very careful when editing Java code within the JSPs.

A JSP compilation tool is provided with iPlanet Market Maker. This tool requires iAS to do its compilation:

com.iplanet.ecommerce.vortex.tools.JspCompiler.IMMJspCompiler

The arguments are as follows.



-d <jsp directory> is the fully qualified path to the directory for the JSP.

-u <jsp url> is the URL to compile

-t 3

-h <ias host> is the host on which iAS is running (for example, localhost).

-p <iws port> is the iWS http port (for example, 80)




Community Custom Fields


Attributes in the iPlanet Market Maker Community Module

The Community module in iPlanet Market Maker 4.0 SP1 (and onward) has fifty custom attributes for the company and user object. The schema and backend API's are now supporting the custom0..49 attributes. The DataBeanCompany & DataBeanUser also includes these custom attributes.

To use these custom attributes, the following steps must be performed:

To add a new field called Company Notification Fax for company, select one of these fifty custom attributes.

For example, if you choose custom0:

  1. Edit the CompanySub.jsp and uncomment the first attribute Custom0.

  2. Change the text Custom0 to your Company Notification Fax to show this in the UI.

  3. Deploy it again on iAS and restart the server.

When you login as immhost or company admin you see the new field Company Notification Fax in the Company Profile fax. If you update this new attribute, it is stored in LDAP, under the attribute immCustom0, under the company name. For example, if you updated this attribute for the company sun then you can see the value for sun in the attribute immCustom0 in LDAP server.

Similarly, for the user you need to make changes in the you can make changes userProfile.jsp, userDetail.jsp, and registerUser.jsp.

The following JSP's are already modified and have custom0..9 attributes. These custom0..9 attributes are commented out and you need to uncomment them to use them. If you need more than ten custom attributes, add your custom attributes in these JSP's, similar to the way you have already added custom0..9 attributes.

For the company, you need to modify only CompanySub.jsp, and for the user, you need to modify the remaining three JSP's.

    1. userProfile.jsp

    2. userDetail.jsp

    3. CompanySub.jsp

    4. registerUser.jsp

All of the other changes for these custom attributes are already done and you do not need to change anything other than JSP's.


Mapping Action Codes to Event Handlers

The mapping between the action codes and event handlers described in the "Interpreting Event Handlers" section is defined in the module Events.xml file. ModuleJSP uses the following method to return the XML file.

protected String getMapFile();

This method returns the name of the XML file, such as AuctionEvent.xml. Here is a mapping from the AuctionEvents.xml file.

<EventMap class="com.iplanet.ecommerce.vortex.auction.display.AucJSP">
...
<EventHandler symcode="ACT_INITIATOR_VIEW_BROWSE" class="com.iplanet.ecommerce.vortex.auction.display.EventHandlerInitiatorViewB rowse" />


The AuctionEvent.xml file is enclosed in an <EventMap> tag. This tag can have a class attribute and an offset attribute (not shown in this example). The class attribute specifies the class used to look up all the symbolic names used inside that class. The OFFSET attribute is a numerical offset added to the integer values of action codes (not the symbolic names) referred to in the AuctionEvent.xml file. For an example of how OFFSET values are added to action code values, see "Defining a New Action Code and Event Handler" in Chapter 4.

You can use an <Include> tag to share common events between modules. This tag has a single attribute, file, that points to another XML file containing another set of action codes and event handlers. This file is read into the XML file during processing.

The Event.xml file is processed sequentially, so that subsequent <EventHandler> and <Include> tags that specify the same actions override earlier settings. This sequencing lets you include a set of actions and selectively override them.

The <EventHandler> ACT_INITIATOR_VIEW_BROWSE attribute is the symbolic name for the action code. EventHandlerInitiatorViewBrowse is the event handler. You can map different action codes to the same event handler, but you cannot map an action code to more than one event handler.

The event handler implements an interface called IEventHandler that constructs an instance of a class called a PresentationBean. This class is a look-up table that provides the data and link information needed to determine the next JSP to be displayed.

The IEventHandler interface implements a method called execute() that returns a PresentationBean that is passed an instance of an interface called IEventContext. The execute() method call uses IEventContext to obtain information such as parameters from the request, session information, profile data, interfaces to construct the appropriate portal-based URLs, and so on.

The ModuleJSP class maps an incoming action code to the right event handler, calls its exectue() method, and dispatches the appropriate JSP as content to be displayed. The PresentationBean returned by the event handler is placed into the request under a standard name, allowing the right channel in the JSP to obtain it. The channel information appears in the AVAILITEM of a display profile for the portal. Display profiles are XML documents that define the contents of the iPlanet Market Maker portal. For information about display profiles, see the iPlanet Market Maker online help.


Using Event Handlers

Each module has a single derivation of the ModuleJSP subclass. For each action you define in a portal JSP, you need a corresponding action code. It is important to make each of your action code numbers unique. You usually define these action codes in a single "constants" class. Consider the following entry in the CatalogEvents.xml file.

<EventHandler symcode="ACT_CATALOG" class="com.iplanet.ecommerce.vortex.catalog.display.ViewsDataEventHandler" />

The action code integer definition for the ACT_CATALOG symbolic action code name is in the IDisplayConstants.java file for the Catalog module:

/**

* Field

* @audience

*/

public static final int ACT_CATALOG = OFFSET + 1;

You can edit the Event.xml files and "constants" classes to substitute your own event handlers for iPlanet Market Maker implementations or add new event handlers to implement new actions in a portal JSP. For an example of an implementation, see Chapter 4.


Using the execute() Call

An event handler uses an execute() call to pass information to a DisplayBean, which in turn passes information to a PresentationBean to represent that information in the JSP. The execute() call uses a public interface called IEventContext to pass this information. A typical code line for the execute() call is as follows.

public DisplayBean execute(IEventContext ctx) throws VortexException {

The code for the IEventContext public interface is as follows.

package com.iplanet.ecommerce.vortex.display;

import com.iplanet.ecommerce.vortex.arch.VortexException;

import com.iplanet.ecommerce.vortex.arch.Context;

import com.iplanet.ecommerce.vortex.display.Session;

import java.util.Enumeration;

/**

* This class represents the interface which defines the methods an event

* context object must contain. This class is used by the IEventHandler.execute().

* Currently JSPEventContext implements this Interface.

*/

public interface IEventContext extends IParameterMap

{

     /**

     * This method retrieves the session.

     * @return the session.

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public IVxDspSession getSession() throws VortexException;

     /**

     * Method getDisplayBeansFromSession

     * safely get an array of DisplayBeans from session

     * @param key

     * @return the array of DisplayBeans from session or null

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public DisplayBean[] getDisplayBeansFromSession(String key)

         throws VortexException;

     /**

     * This method safely retrieves a DisplayBean from a session.

     * @param key

     * @return the DisplayBean from session or null

     * @throws VortexException

     *

     * @audience user

     * @audience vortex-logic

     */

     public DisplayBean getDisplayBeanFromSession(String key)

     * @throws VortexException;

     /**

     * This method puts a DisplayBean array in session.

     * @param key

     * @param beans

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void putDisplayBeansInSession(String key, DisplayBean[] beans)

       throws VortexException;

     /**

     * This method puts a DisplayBean in session.

     * @param key

     * @param bean

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void putDisplayBeanInSession(String key, DisplayBean bean)

     } throws VortexException;

     /**

     * This method retrieves the context.

     * @return the context.

     * @audience user

     * @audience vortex-logic

     */

     public Context getContext();

     /**

     * This method retrieves the underlying portal display element. Essentially,

     * the "escape valve" back to the portal framework from the more specific

     * Market Maker implementation. Expected common uses of this method are

     * covered by some of the other methods which should be used instead.

     *

     * @return the element.

     * @audience user

     * @audience vortex-logic

     */

     public DisplayElement getSource();

     /**

     * This method retrieves the action code.

     * @return the action code.

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public int getActionCode() throws VortexException;

     /**

     * This method retrieves the action code index.

     * @return the action code index.

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public int getActionCodeIndex() throws VortexException;

     /**

     * This method retrieves the portal URL.

     * @return the portal url.

     * @audience user

     * @audience vortex-logic

     */

     public String getPortalURL();

     /**

     * This method refreshes the information display profile.

     * @return true, if this is a refresh case.

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public boolean isRefreshable() throws VortexException;

     /**

     * This method retrieves an object from the display profile

     * @param key the lookup key.

     * @return object or null

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public Object getProfile(String key) throws VortexException;

     /**

     * This method removes an object from the display profile.

     * @param key the object to remove

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void removeProfile(String key) throws VortexException;

     /**

     * This method places an object in the display profile.

     * @param key the lookup key.

     * @param value the object to place in the profile

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void setProfile(String key, Object value) throws VortexException;

     /**

     * This method sets the action code.

     * @param code the code.

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void setActionCode(int code) throws VortexException;

     /**

     * This method sets the action code index.

     * @param code the code index.

     * @param index

     * @throws VortexException

     * @audience user

     * @audience vortex-logic

     */

     public void setActionCodeIndex(int index) throws VortexException;

     /**

     * This method forwards the request to the EventHandler that is mapped to the

     * given code. Processing will continue as normal inside the

     * EventHandler that is targeted. When processing is returned, the

     * DisplayBean has been set for the forwarded EventHandler. The setting of

     * the DisplayBean a second time will override the setting made

     * by the forwarded EventHandler.

    *

    * @param code The action code to which you should forward the request.

    * @return The DisplayBean created by the forwarded EventHandler

    *

    * @throws VortexException

    * @audience user

    * @audience vortex-logic

    */

    public DisplayBean forward(int code) throws VortexException;

    /**

    * This method obtains an NVPLinkGen for use in constructing navigation.

    * @return

    * @audience user

    * @audience vortex-logic

    */

    public NVPLinkGen makeLinkGenerator();

    /**

    * This method retrieves the attribute access.

    *

    * @param name the attribute key

    * @return the desired attribute, or null.

    * @audience user

    * @audience vortex-logic

    */

    public Object getAttribute(String name);

    /**

    * This method sets the attribute setting.

    * @param name the attribute key

    * @value the attribute object

    * @param value

    * @audience user

    * @audience vortex-logic

    */

    public void setAttribute(String name, Object value);

    /**

    * This method retrieves attribute names.

    * @return the attribute names

    * @audience user

    * @audience vortex-logic

    */

    public Enumeration getAttributeNames();

    /**

    * This method obtains the remote IP address

    * @return remote address

    * @throws VortexException

    * @audience user

    * @audience vortex-logic

    */

    public String getRemoteAddr() throws VortexException;

}


Invoking and Redisplaying Event Handlers

As stated earlier, the ModuleJSP class invokes an event handler based on an action code setting. The action code might represent one of three things:

  • An initial setting driven from the display profile the first time the channel was displayed. If defaulted, it is -1.

  • An explicit code driven from the submit button or href placed in the JSP.

  • Redisplay.

Redisplay requires some explanation. Certain portal actions, like tabbing onto a display for a channel, or handling an action for another channel displayed on the page along with your channel, might result in an exectue() call with no explicit action code for the channel in the URL. In this case, execute() is called with the same action code it had the last time it was invoked.

Three mechanisms aid the execute() method in handling the situation:

  • The IEventContext passed to the exectue() mechanism includes a method isRefreshable(), which returns boolean true if the channel is being redisplayed. This allows the event handler to behave appropriately by restoring data cached in the session, not performing a requested DB update for a redisplay.

  • The IEventContext contains a setActionCode() method that allows the event handler to control the recorded code that is invoked if a specific code was not specified through the URL. This, for instance, allows event handlers for transitional state to ensure that those transitional states are never reinvoked unless explicitly requested.

  • For channels displayed in tabbed containers, there is a special property called autohoming that can be set for a channel in the display profile. If the channel is autohomed, whenever it is freshly tabbed onto, it is reset to its default action code.


Relating Event Handlers to JSPs

As stated earlier, the PresentationBean returned by the execute() method is made available to the JSP under a standard name registered as an attribute on the request. The module JSPs generally contain an initial scriptlet with a line like:

PresentationBean presBean = (PresentationBean) request.getAttribute(DISPLAY_BEAN);

This line lets information from the PresentationBean, which is a descendant of the DisplayBean, be displayed in the JSP. For a JSP code example, see "Displaying the Added JSP" in Chapter 4.

Further beans, as well as many other types of data, can be registered in this object, allowing the JSP access to it.

Currently, there is not an explicit listing of the JSP displayed for a given action code. Part of the reason for this is that because the event handler determines the JSP to be displayed, it could be switched dynamically on the basis of the logic in the handler, so there is not always a one-to-one correspondence (there usually is, but not always).

You can determine the relationship between the event handlers and JSPs in two ways:

  • Examine the JSP and the names used in them to generate the presentation. The action code appears in the URL after you perform an action in the JSP. For example, the following action code number appears after you log in as a buyer and select Catalog - Browse (the iPlanet Market Maker URL has been omitted and replaced by "...").



  • Turn on terse debugging for the display module (debug level 7 for module 6). For details about how to turn on terse debugging, see the "Interpreting Event Handlers" section.


Other Resources for Customizing Event Handlers

The JavaDoc's for the following classes are also help good resources for understanding event handlers.

  • IEventHandler - The interface implemented by an event handler.

  • IEventContext and superclass IParameterMap - The context interface passed to the event handler's execute() method.

  • Context -The context object for backend operations, setup by ModuleJSP and made available to the execute() method.

  • DisplayBean and subclass PresentationBean -The data packager used to transfer data between the execute() method and the JSP.

  • LinkGen (superclass of NVPLinkGen) -The helper class used to create URL's within the Portal Framework.

  • Session - The session abstraction used inside iPlanet Market Maker.

  • Date, Price, LocalizedEnum - Specialized datatypes used in conjunction with the DisplayBean.

  • DisplayField, FieldType - Classes used in conjunction with field validation in DisplayBean.



Configuring the Debug Channel

When you go to iPlanet Market Maker in your browser, a popup window is launched. Every time you click a link in an iPlanet Market Maker window, a popup window gives you the following information:

  • A list of all the http request parameters and values.

  • The symbolic and numeric action code associated to this link.

  • The name of the event handler that is invoked, with a link to the javadoc for that Event Handler. This works if the javadoc is installed on your iPlanet Market Maker instance in the doc/userdocs directory. The event handler javadoc is where all the information related to customization of this event handler is located, namely the produced DisplayBean and its content.

  • Eventually, the name of the event handler to which the action is forwarded.

  • The name of the JSP invoked to render the content created by the event handler.

  • A serialization of the display bean, with all the fields, their types and values.

To enable the debug channel:

  1. Set the DebugLevel to 40 (instead of the default of 3) in the following file:

    <ias_install_dir>/ias/APPS/imm40/imm40/classes/VortexConfiguration.properties

    For example:

    # - Debug level for the iPlanet Market Maker system
    5=40W

  2. After you have edited this file, restart your web server.

    When you go to the iPlanet Market Maker site in your browser, a popup should be launched with all the information you need.


Previous     Contents     Index     Next     
Copyright © 2002 Sun Microsystems, Inc. All rights reserved.

Last Updated March 25, 2002