Previous     Contents     Index     Next     
iPlanet Application Server 6.5 Programmer's Guide (C++)



Chapter 12   Sample Code Walkthrough


The following code samples are included in this chapter:



About the Online Bank Sample Application

The Online Bank sample application, which is shipped with the iPlanet Application Server, provides online banking and customer management. In this application, the user interface is HTML pages displayed in Web browsers. Customers can log in to the application over the Internet, view account information, and move funds between accounts. Representatives of the bank can display information about customers, add new customers, and update or delete existing customer data.

You should have already installed the Online Bank sample application on your development system using the iPlanet Application Server installation procedure described on the product CD. If you followed the instructions found there, you should find these files in your sample directory.

The illustration on the following page summarizes the design of Online Bank. The application consists of fourteen AppLogic objects, twelve HTML templates, and assorted additional code modules, including a custom session class.

The following sequence describes a typical user session with Online Bank:

  1. The user navigates their Web browser to the first HTML page of the application, COBLogin.html.

  2. When the user clicks the Login button, a request to run the OBLogin AppLogic is sent to iPlanet Application Server. If the user's login information is not valid, the ValidationError.html page is displayed.

  3. If the user's login information is valid, the OBLogin AppLogic creates a session for the user. A session is an object that is used to store information about a user's interaction with an application. In the Online Bank sample application, the session stores information about the user, such as user name and type. The OBLogin AppLogic then calls the OBShowMenuPage AppLogic.

  4. The OBShowMenuPage AppLogic displays the appropriate menu, depending on the type of user. For example, if the user is a customer, the AppLogic displays CustomerMenu.html.

  5. The CustomerMenu.html page contains several hyperlinks. Each hyperlink is coded to call a different AppLogic. When the user clicks one of the hyperlinks, the corresponding AppLogic is executed on the iPlanet Application Server. For example, if the user clicks Show Balances, the OBShowBalancesPage AppLogic is executed.

  6. The OBShowBalancesPage AppLogic queries a database to get the customer's account information.

  7. The result set of this query is merged with an HTML template, Balances.html, which specifies how to format the data into an output page. After the customer's account information is merged with the template, the resulting HTML page is displayed in the user's Web browser.

  8. The user can continue to use hyperlinks to view other HTML pages and execute other AppLogics in the application.

  9. Eventually, the user clicks the Logout hyperlink, which causes the OBLogout AppLogic to execute. This AppLogic destroys the user's session object and displays a farewell message to the user.


AppLogic Objects in Online Bank

The following list summarizes each AppLogic object in Online Bank:

  • OBBaseAppLogic is the base AppLogic class for the Online Bank application. It contains methods to create a user session, initiate contact with the database, handle certain types of errors, and show a success message to the user.

  • OBLogin logs the user in, starts a session, and calls the ShowMenuPage AppLogic.

  • OBShowMenuPage displays the appropriate menu page depending on the type of user. The possible menus are CustomerMenu.html, for bank customers, and RepMenu.html, for employees of the bank.

  • OBShowBalancesPage, called from the CustomerMenu, runs a query to get the customer's account information from a database. It then displays the results in the page Balances.html.

  • OBShowTransPage, called from the CustomerMenu, generates a report of transactions for the customer's accounts.

  • OBShowTransferPage, called from the CustomerMenu, displays a page in which the customer can transfer funds from one account to another. The page displayed is Transfer.html.

  • OBTransfer, called from the Transfer page, stores the funds transfer in a transaction table. The Online Bank application is written under the assumption that the database will perform a batch update of account balances on a periodic basis, based on entries in this table.

  • OBShowFindCust, called from the RepMenu, displays a page in which a bank employee can enter search criteria to find one or more customers in the database. The page displayed is FindCust.html.

  • OBFindCust, called from the FindCust page, looks up a list of customers that match the search criteria, and displays the results in ListCusts.html.

  • OBShowCustPage, called from the ListCusts page, displays detail information about a particular customer. The detail page is Cust.html. The bank employee can make changes to the customer data in this page.

  • OBUpdateCust, called from the Cust page, changes the customer data in the database. It then calls OBShowCustPage to redisplay the customer page, showing the new data.

  • OBLogout destroys the user session and displays a farewell message to the user.



The Online Bank Base AppLogic

The AppLogic base class for the Online Bank application, OBBaseAppLogic, contains methods to create a user session, initiate contact with the database, handle certain types of errors, show a success message to the user, and perform data validation and formatting. Below is an abbreviated listing of the code from this class.

// ... #include statements

// ...

// Constructor and destructor methods. These contain the



// required calls to GXDllLockInc() and GXDllLockDec().



OBBaseAppLogic::OBBaseAppLogic()

{

   // Update count of references to the AppLogic library

   GXDllLockInc();

   m_pSession=NULL;

}

OBBaseAppLogic:: ~OBBaseAppLogic()

{

   if(m_pSession) {

      m_pSession->Release();

      m_pSession=NULL;

   }

   // Update count of references to the AppLogic library

   GXDllLockDec();

}

// **********************************************

//* GetOBSession(): Return a reference to this

// application's session object

// **********************************************

STDMETHODIMP

OBBaseAppLogic::GetOBSession(OBSession **ppSession)

{

   // See if there is already a session

   if(!m_pSession) {

      // Get the session

      IGXSession2 *pSess=NULL;

      if(((hr=GetSession(0, OB_APPNAME, NULL, &pSess))

         ==GXE_SUCCESS)&&pSess) {

         m_pSession=new OBSession(pSess);

         pSess->Release();

      }

      // If Session has not been created yet, instantiate

      // it

      else if(((hr=CreateSession(GXSESSION_DISTRIB, 600,

         OB_APPNAME, NULL, NULL, &pSess))==GXE_SUCCESS)

         &&pSess) {

         m_pSession=new OBSession(pSess);

         pSess->Release();

      }

   }

   // If we now have a session, return it

   if(m_pSession) {

      *ppSession=m_pSession;

      m_pSession->AddRef();

   }

   return hr;

}

// **********************************************

//* GetOBDataConn(): Return a reference to the Online

// Bank's default database

// **********************************************

STDMETHODIMP

OBBaseAppLogic::GetOBDataConn(IGXDataConn **ppConn)

{

   HRESULT hr=GXE_SUCCESS;

   // Create a ValList for the connection parameters

   // ...

      // Attempt to create the connection

      hr=CreateDataConn(0, GX_DA_DRIVER_DEFAULT, pList,

         m_pContext, ppConn);

      // We're done with the list

      pList->Release();

   }

   return hr;

}

// **********************************************

// Error handling methods

// **********************************************

STDMETHODIMP

OBBaseAppLogic::HandleOBSessionError()

{

   return StreamResult("<HTML><BODY> You must re-log in to

      perform this action </BODY></HTML>");

}

STDMETHODIMP

OBBaseAppLogic::HandleOBSystemError(LPSTR pMessage)

{

   // ... Displays message, logs the occurrence, and

   // returns -1

}

STDMETHODIMP

OBBaseAppLogic::HandleOBValidationError(LPSTR pMessage)

{

   // ... Displays message, using ValidationError.html

   // ... logs the occurrence, and returns -1

}

STDMETHODIMP_(BOOL)

OBBaseAppLogic::IsSessionValid()

{

   HRESULT hr=GXE_SUCCESS;

   BOOL ret=FALSE;

   // There must be a user name in the session

   OBSession *pSess=NULL;

   if(((hr=GetOBSession(&pSess))==GXE_SUCCESS)&&pSess) {

      LPSTR pName=NULL;

      if((pName=pSess->GetUserName())) {

         ret=TRUE;

         delete [] pName;

      }

      pSess->Release();

   }

   return ret;

}

// **********************************************

// ShowSuccessMessage()

// **********************************************

STDMETHODIMP

OBBaseAppLogic::ShowSuccessMessage(LPSTR pMessage)

{

   // ... Displays message, using SuccessMessage.html

}

// **********************************************

// Validation methods

// **********************************************

STDMETHODIMP_(BOOL)

OBBaseAppLogic::ValidateString(LPSTR pTestString,

   LPSTR pName, BOOL isRequired, UINT len,

   BOOL useExactLength)

{

   // ... Tests a string

}

STDMETHODIMP_(BOOL)

OBBaseAppLogic::ValidateSSNString(LPSTR pTestString,

   LPSTR pName, BOOL isRequired)

{

   // ... Tests a Social Security number

}

STDMETHODIMP_(BOOL)

OBBaseAppLogic::ValidatePhoneString(LPSTR pTestString,

   LPSTR pName, BOOL isRequired)

{

   // ... Tests a phone number

}

STDMETHODIMP_(BOOL)

OBBaseAppLogic::ValidateZipString(LPSTR pTestString,

   LPSTR pName, BOOL isRequired)

{

   // ... Tests a ZIP code

}

STDMETHODIMP_(LPSTR)

OBBaseAppLogic::FormatSSNString(LPSTR pS)

{

   // ... Formats data as a Social Security number

}

STDMETHODIMP_(LPSTR)

OBBaseAppLogic::FormatPhoneString(LPSTR pS)

{

   // ... Formats data as a phone number

}

STDMETHODIMP_(LPSTR)

OBBaseAppLogic::FormatZipString(LPSTR pS)

{

   // ... Formats data as a ZIP code

}

STDMETHODIMP_(LPSTR)

OBBaseAppLogic::GetDigitString(LPSTR pSource)

{

   // ... Formats data

}



Detailed Walk Through of Funds Transfer Functionality



This section walks through the code and templates involved in a transfer of funds between customer accounts. The following application components are presented with comments:


CustomerMenu.html

After a customer logs in, the first page they see is the CustomerMenu HTML page. This page displays a list of hyperlinks which a customer of the bank can use to display various other pages in the application. The page begins with a standard heading.

<html>

<head>

<title>Customer Menu</title>

</head>

<body>

<h2>Welcome!</h2>

<h4>What would you like to do today?</h4>

<p><a

The following lines define four hyperlinks, allowing the user to choose between four AppLogic objects: CShowBalancesPage, CShowTransPage, CShowTransferPage, and COBLogout. For the purposes of a funds transfer, the user will click the hyperlink that runs the OBShowTransferPage AppLogic.



Note The names used in HTML pages are the names under which the AppLogic objects are registered in the Online Bank Registration File, not necessarily the names with which the AppLogic classes are declared in code.



The names used in HTML pages are the names under which the AppLogic objects are registered in the Online Bank Registration File, not necessarily the names with which the AppLogic classes are declared in code.

href="/cgi-bin/gx.cgi/AppLogic+CShowBalancesPage">View

Balances </a><br>

</p>

<p><a

href="/cgi-bin/gx.cgi/AppLogic+CShowTransPage">View Transactions </a></p>

<p><a

href="/cgi-bin/gx.cgi/AppLogic+CShowTransferPage"> Transfer between Accounts </a></p>

<p><a

href="/cgi-bin/gx.cgi/AppLogic+COBLogout"> Log out </a></p>

</body>

</html>


OBShowTransferPage AppLogic

The OBShowTransferPage AppLogic displays a page in which the customer can transfer funds from one account to another. The page displayed is Transfer.html.


Header File (ShowTransferPage.h)
The header file for the OBShowTransferPage AppLogic does the following:

  • Includes C++ and iPlanet Application Builder header files.

  • Declares the AppLogic object OBShowTransferPage, which is subclassed from the OBBaseAppLogic class.

The OBShowTransferPage AppLogic includes this header file at the beginning of its source file.

First, in the following code, the header file includes other header files needed for the AppLogic:

#ifndef __SHOWTRANSFERPAGE_H__

#define __SHOWTRANSFERPAGE_H__

#include <stdio.h>

#include <gxplat.h>

#include <gxutil.h>

#include <gxapplogic.h>

#include <gxdlm.h>

#include "BaseAppLogic.h"

Next, the header file declares the variable that will contain the GUID that uniquely identifies the AppLogic object in the iPlanet Application Server system.

extern GUID OBShowTransferPageGUID;

Next, the header file subclasses the OBShowTransferPage class from the OBBaseAppLogic class and declares its constructor, destructor, and Execute( ) methods. Note that the constructor and destructor methods in this subclass do not contain the required calls to GXDllLockInc( ) and GXDllLockDec( ). These calls are made in the superclass, OBBaseAppLogic.

class OBShowTransferPage : public OBBaseAppLogic

{public:

   OBShowTransferPage();

   virtual ~OBShowTransferPage();

   STDMETHOD(Execute) ();

};

Finally, the header file associates the OBShowTransferPage AppLogic with its corresponding GUID.

GXDLM_DECLARE( OBShowTransferPage, OBShowTransferPageGUID);

#endif /* __SHOWTRANSFERPAGE_H__ */


Source File (ShowTransferPage.cpp)
The source file begins by including the header files it needs, including ShowTransferPage.h.

#include <stdio.h>

#include <gxplat.h>

#include <gxutil.h>

#include <gxagent.h>

#include <gxdlm.h>

#include "ShowTransferPage.h"

#include "gxval.h"

#include "common.h"

Next, the source file defines the GUID for the AppLogic that was declared in the header file. You must use the kguidgen utility to generate a unique GUID for each AppLogic, then paste it into the .cpp file. In addition, you must create a registration file (.gxr), using a text editor, and paste the GUID information into the .gxr file as well. For more information, see

// {23F1E8F0-6388-11D1-A1AF-006008293C54}

//

GUID OBShowTransferPageGUID =

{ 0x23F1E8F0, 0x6388, 0x11D1, { 0xA1, 0xAF, 0x00, 0x60, 0x08, 0x29, 0x3C, 0x54 } };

/////////////////////////////////////////////////////////////

The code next defines constructor and destructor methods for the class.

OBShowTransferPage::OBShowTransferPage() {

};

OBShowTransferPage::~OBShowTransferPage() {

};

The code next begins implementation of the Execute( ) method, using the STMETHODIMP macro. For more information about this macro, see the iPlanet Application Server Foundation Class Reference.

STDMETHODIMP

OBShowTransferPage::Execute()

{

The code next declares and initializes the variable hr, which is used throughout the code for return values of calls to methods and functions.

HRESULT hr=GXE_SUCCESS;

The code next checks for a valid user session, using the method IsSessionValid( ) from the OBBaseAppLogic class. If the user logged in properly through the OBLogin AppLogic, this validation should return successfully.

if(!IsSessionValid())

   return HandleOBSessionError();

The code next opens a connection to a database, using the method GetOBDataConn( ) from the OBBaseAppLogic class.

// Create the data connection

IGXDataConn *pConn=NULL;

if(((hr=GetOBDataConn(&pConn))==GXE_SUCCESS)&&pConn) {

The code next retrieves the session data to get information about the user. The user's Social Security number is retrieved.

// Pull the session

OBSession *pSession=NULL;

if(((hr=GetOBSession(&pSession))==GXE_SUCCESS)&&pSession) {

LPSTR pSsn=NULL;

// Get the social security number

if((pSsn=pSession->GetSSN())) {

If the number was retrieved successfully, the code sets up parameters for the query which will retrieve information about the user's accounts. In this AppLogic, the query is stored in a query file.

// Create a vallist for loadQuery parameters

IGXValList *pList=GXCreateValList();

if(pList) {

   GXSetValListString(pList, "ssn", pSsn);

If the parameters were set up successfully, the code loads the query and runs it.

IGXQuery *pQuery=NULL;

if(((hr=LoadQuery("GXApp/OnlineBank/queries/

   SelCustAccts.gxq", "SelCustAccts", 0, pList,

   &pQuery))==GXE_SUCCESS)&&pQuery) {

   // Execute the query

   IGXResultSet *pRset=NULL;

   if(((hr=pConn->ExecuteQuery(0, pQuery, NULL,

      NULL, &pRset))==GXE_SUCCESS)&&pRset) {

If the query successfully retrieved some data, the code places the data into two template data objects. Each object contains the same data. The two template data objects are needed because the template that will be merged with the data has to display the same information twice (once under "Transfer from account" and again under "Transfer to account").

ULONG numRows=0;

if(((hr=pRset->RowCount(&numRows))==GXE_SUCCESS)&&numRows) {

   // Fill up 2 template data basics with results

   // from the same query to avoid running the same database

   // query twice

   GXTemplateDataBasic *pAcctsTempDB =

      GXCreateTemplateDataBasic("SelCustAccts");

   GXTemplateDataBasic *pAcctsTempDB2 =

      GXCreateTemplateDataBasic("SelCustAccts2");

   if(pAcctsTempDB&&pAcctsTempDB2) {

      char pAcctDesc[200];

      char pAcctNum[200];

      // Pull the column ordinals for the account

      // description and account num

      ULONG acctDescCol=0; pRset->GetColumnOrdinal(

         "OBAccountType_acctDesc", &acctDescCol);

      ULONG acctNumCol=0; pRset->GetColumnOrdinal(

         "OBAccount_acctNum", &acctNumCol);

      char tmpStr[300];

The code uses a loop to copy the data from the result set into the template data objects.

do {

   pRset->GetValueString(acctDescCol, pAcctDesc, 200);

   pRset->GetValueString(acctNumCol, pAcctNum, 200);

   sprintf(tmpStr, "acctDesc=%s;acctNum=%s", pAcctDesc,

      pAcctNum);

   pAcctsTempDB->RowAppend(tmpStr);

   pAcctsTempDB2->RowAppend(tmpStr);

} while(pRset->FetchNext()==GXE_SUCCESS);

Since the data is expected to be hierarchical, an empty template data object is created to act as parent to the other two.

GXTemplateDataBasic *pParent=NULL;

if((pParent=GXCreateTemplateDataBasic("Parent"))) {

   // One dummy row, to contain the child groups

   pParent->RowAppend("Dummy=dummy");

Then the template data objects that contain the data are added to the parent.

   // Add the first template data object to the set

   pParent->GroupAppend(pAcctsTempDB);

   // Add the second template data object to the set

   pParent->GroupAppend(pAcctsTempDB2);

The code merges the template data objects with the template Transfer.html to display a page in which the user can set up the transaction.

   if(EvalTemplate("GXApp/COnlineBank/templates/

      Transfer.html", pParent, NULL, NULL,

      NULL)!=GXE_SUCCESS)

   // If unsuccessful...

         Result("<HTML><BODY>Unable to evaluate template.

                 </BODY></HTML>");

   pParent->Release();

   }

}

// Release the template data basics, if applicable

if(pAcctsTempDB)

   pAcctsTempDB->Release();

if(pAcctsTempDB2)

   pAcctsTempDB2->Release();

If the account data query failed, the code displays an error message, using the HandleOBSystemError( ) method declared in the BaseAppLogic class.

}

else

   HandleOBSystemError("Could not retrieve account data");

pRset->Release();

Next, the code releases the objects used.

               }

               pQuery->Release();

               }

               pList->Release();

            }

            delete [] pSsn;

         }

         pSession->Release();

      }

      pConn->Release();

   }

   else

   // If data connection failed, return error

   HandleOBSystemError("Could not create data connection");

Finally, the code sets the return value of the Execute( ) method.

   return GXE_SUCCESS;

}


Transfer.html

Transfer.html is a page in which the customer can transfer funds from one account to another. The OBShowTransferPage AppLogic uses this template to return results.

<html>

<head>

<title>Account Transfer</title>

</head>

<body>

The following line is a hyperlink that runs the ShowMenuPage AppLogic, returning the user to the main menu.



Note The names used in HTML pages are the names under which the AppLogic objects are registered in the Online Bank Registration File, not necessarily the names with which AppLogic classes are declared in code.



The names used in HTML pages are the names under which the AppLogic objects are registered in the Online Bank Registration File, not necessarily the names with which the AppLogic classes are declared in code.

<p><a

href="/cgi-bin/gx.cgi/AppLogic+CShowMenuPage">Back to Main Menu</a><br>

</p>

<h2>Account Transfer</h2>

The following line sets the action of this page to run the Transfer AppLogic. This action will occur when the user clicks the Transfer button, coded later in the page.

<form action="/cgi-bin/gx.cgi/AppLogic+CTransfer" method="POST">

The following lines contain GX markup tags, which merge the user's own account information with the page.

%gx type=tile id=Parent MAX=100%

<p><B>Which account would you like to transfer from?</B><br>

%gx type=tile id=SelCustAccts MAX=100%

<input type="radio" name="fromAcct"

value="%gx type=cell id="SelCustAccts.acctNum"%%/gx%">

%gx type=cell id="SelCustAccts.acctDesc"%%/gx%: %gx type=cell id="SelCustAccts.acctNum"%%/gx% <br>

%/gx%

</p>

The following lines repeat the user's account information, so the user can choose the destination account:

<p><B>Which account would you like to transfer to?</B><br>

%gx type=tile id=SelCustAccts2 MAX=100%

<input type="radio" name="toAcct" value="%gx type=cell

      id="SelCustAccts2.acctNum"%%/gx%">

%gx type=cell id="SelCustAccts2.acctDesc"%%/gx%:

      %gx type=cell id="SelCustAccts2.acctNum"%%/gx% <br>

%/gx%

</p>

%/gx%

The following lines set up the field where the user tells how much money to transfer between the two accounts selected above:

<p><B>How much would you like to transfer?</B> <br>

<input type="text" name="amount" size="20" value="0.00">

   </p>

Finally, the template specifies the Transfer button, which sets off the page action specified earlier, running the Transfer AppLogic.

<p><input type="submit" value="Transfer" name="transfer"></p>

</form>

</body>

</html>


OBTransfer AppLogic

The OBTransfer AppLogic stores the funds transfer in a transaction table. The Online Bank application is written under the assumption that the database will perform a batch update of account balances on a periodic basis, based on entries in this table.


Header File (Transfer.h)
The header file for the OBTransfer AppLogic does the following:

  • Includes C++ and iPlanet Application Builder header files.

  • Declares the AppLogic object OBTransfer, which is subclassed from the OBBaseAppLogic class.

The OBTransfer AppLogic includes this header file at the beginning of its source file.

First, in the following code, the header file includes other header files:

#ifndef __TRANSFER_H__

#define __TRANSFER_H__

#include <stdio.h>

#include <gxplat.h>

#include <gxutil.h>

#include <gxapplogic.h>

#include <gxdlm.h>

#include "BaseAppLogic.h"

Next, the header file declares the variable that will contain the GUID that uniquely identifies the AppLogic object in the iPlanet Application Server system.

extern GUID OBTransferGUID;

Next, the header file subclasses the OBTransfer class from the OBBaseAppLogic class and declares its constructor, destructor, and Execute( ) methods. Note that the constructor and destructor methods in this subclass do not contain the required calls to GXDllLockInc( ) and GXDllLockDec( ). These calls are made in the superclass, OBBaseAppLogic.

class OBTransfer : public OBBaseAppLogic

{

public:

   OBTransfer();

   virtual ~OBTransfer();

   STDMETHOD(Execute) ();

};

Finally, the header file associates the OBTransfer AppLogic with its corresponding GUID.

GXDLM_DECLARE( OBTransfer, OBTransferGUID);

#endif /* __TRANSFER_H__ */


Source File (Transfer.cpp)
The source file begins by including the header files it needs, including Transfer.h.

#include <stdio.h>

#include <gxplat.h>

#include <gxutil.h>

#include <gxagent.h>

#include <gxdlm.h>

#include "Transfer.h"

#include "gxval.h"

#include "common.h"

Next, the source file defines the GUID for the AppLogic that was declared in the header file. You must use the kguidgen utility to generate a unique GUID for each AppLogic, then paste it into the .cpp file. In addition, you must create a registration file (.gxr), using a text editor, and paste the GUID information into the .gxr file as well. For more information, see

// {2754DA40-638C-11D1-A1AF-006008293C54}

//

GUID OBTransferGUID =

{ 0x2754DA40, 0x638C, 0x11D1, { 0xA1, 0xAF, 0x00, 0x60, 0x08, 0x29, 0x3C, 0x54 } };

/////////////////////////////////////////////////////////////

The code next defines constructor and destructor methods for the class.

OBTransfer::OBTransfer() {

};

OBTransfer::~OBTransfer() {

};

The code next begins implementation of the Execute( ) method, using the STMETHODIMP macro. For more information about this macro, see the iPlanet Application Server Foundation Class Reference.

STDMETHODIMP

OBTransfer::Execute()

{

The code next declares and initializes the variable hr, which is used throughout the code for return values of calls to methods and functions.

HRESULT hr=GXE_SUCCESS;

The code next checks for a valid user session, using the method IsSessionValid( ) from the OBBaseAppLogic class. If the user logged in properly through the OBLogin AppLogic, this validation should return successfully.

if(!IsSessionValid())

   return HandleOBSessionError();

The code next retrieves the input data which the user specified in the page Transfer.html.

// Get parms from the input form

LPSTR pFromAcct=NULL;

LPSTR pToAcct=NULL;

LPSTR pAmountString=NULL;

pFromAcct=GXGetValListString(m_pValIn, "fromAcct");

pToAcct=GXGetValListString(m_pValIn, "toAcct");

pAmountString=GXGetValListString(m_pValIn, "amount");

// Convert amount to double

double amount=0.0;

if(pAmountString)

   amount=atof(pAmountString);

The code next performs some tests on the input. This is always advisable when data comes in from outside the application, such as from end users.

// Validate input

if((!pFromAcct)||(!pToAcct))

   return HandleOBValidationError("You must specify both an

      account to transfer from and an account to transfer

      to.");

else if(!strcmp(pFromAcct, pToAcct))

   return HandleOBValidationError("You may not transfer into

   the account from which you are transferring.");

// Check the amount

if(amount<=0.0)

   return HandleOBValidationError("You must enter a positive

      non-zero amount of money to transfer.");

The code then retrieves the current date and time, so that it can time-stamp the transaction.

// Get the current date time

GXDATETIME dt;

GXGetCurrentDateTime(&dt);

char dateStr[50];

sprintf(dateStr, "%d-%d-%d %d:%d:%d", dt.year, dt.month,

   dt.day, dt.hour, dt.minute, dt.second);

Log(dateStr);

The code next opens a connection to a database, using the method GetOBDataConn( ) from the OBBaseAppLogic class.

// Create the data connection

IGXDataConn *pConn=NULL;

if(((hr=GetOBDataConn(&pConn))==GXE_SUCCESS)&&pConn) {

The code next accesses the database to retrieve a handle to the OBTransactions table, and gets the ordinal numbers of the columns in the database. The column ordinals are required in later method calls.

IGXTable *pTable=NULL;

if(((hr=pConn->GetTable("OBTransaction", &pTable))

   ==GXE_SUCCESS)&&pTable) {

   // Look up the column ordinals for the table

   ULONG transTypeCol=0; pTable->GetColumnOrdinal(

      "transType", &transTypeCol);

   ULONG postDateCol=0; pTable->GetColumnOrdinal("postDate",

      &postDateCol);

   ULONG acctNumCol=0; pTable->GetColumnOrdinal("acctNum",

      &acctNumCol);

   ULONG amountCol=0; pTable->GetColumnOrdinal("amount",

      &amountCol);

The code then starts a transaction. This ensures that both parts of the funds transfer are executed together.

IGXTrans *pTx=NULL;

if(((hr=CreateTrans(&pTx))==GXE_SUCCESS)&&pTx) {

   pTx->Begin();

The code then performs an INSERT command to add a row for the withdrawal portion of the transaction.

// Create a new row for the withdrawal half of the

// transaction

pTable->AllocRow();

pTable->SetValueString(acctNumCol, pFromAcct);

pTable->SetValueInt(transTypeCol, OB_TRANSTYPE_WITHDRAWAL);

pTable->SetValueDateString(postDateCol, dateStr);

pTable->SetValueDouble(amountCol, amount*-1.0);

// Add the row using the transaction

if(pTable->AddRow(0, pTx)==GXE_SUCCESS) {

The code then performs another INSERT command for the deposit portion of the transfer.

pTable->AllocRow();

pTable->SetValueString(acctNumCol, pToAcct);

pTable->SetValueInt(transTypeCol, OB_TRANSTYPE_DEPOSIT);

pTable->SetValueDateString(postDateCol, dateStr);

pTable->SetValueDouble(amountCol, amount);

// Add the row using the transaction

if(pTable->AddRow(0, pTx)==GXE_SUCCESS) {

If both INSERT commands were performed successfully, the code commits the transaction.

   pTx->Commit(0, NULL);

   ShowSuccessMessage("Your transfer has been completed");

}

If either INSERT command failed, the code rolls back the transaction.

      else {

         pTx->Rollback();

         HandleOBSystemError("Could not insert transaction");

      }

   }

   else {

      pTx->Rollback();

      HandleOBSystemError("Could not insert transaction");

   }

The remainder of the code handles any earlier failures in creating objects, getting connections, and so on.

         pTx->Release();

      }

      else

         HandleOBSystemError("Could not start transaction");

      pTable->Release();

   }

   else

      HandleOBSystemError("Could not access table

         OBTransaction");

   pConn->Release();

}

else

   HandleOBSystemError("Could not create data connection");

Finally, the code sets the return value of Execute( ).

   return GXE_SUCCESS;

}


Other Code

The code in the file applogics.cpp establishes to the iPlanet Application Server the entry point in a dynamically loadable, shared library module (DLM) for each AppLogic object in the Online Bank application, including OBShowTransferPage and OBTransfer.

GXDLM_IMPLEMENT_BEGIN();

GXDLM_IMPLEMENT( OBLogin, OBLoginGUID);

GXDLM_IMPLEMENT( OBShowMenuPage, OBShowMenuPageGUID);

GXDLM_IMPLEMENT( OBShowBalancesPage, OBShowBalancesPageGUID);

GXDLM_IMPLEMENT( OBShowTransPage, OBShowTransPageGUID);

GXDLM_IMPLEMENT( OBShowTransferPage, OBShowTransferPageGUID);

GXDLM_IMPLEMENT( OBLogout, OBLogoutGUID);

GXDLM_IMPLEMENT( OBTransfer, OBTransferGUID);

GXDLM_IMPLEMENT( OBShowNewCustPage, OBShowNewCustPageGUID);

GXDLM_IMPLEMENT( OBShowFindCustPage, OBShowFindCustPageGUID);

GXDLM_IMPLEMENT( OBFindCust, OBFindCustGUID);

GXDLM_IMPLEMENT( OBShowCustPage, OBShowCustPageGUID);

GXDLM_IMPLEMENT( OBCreateCust, OBCreateCustGUID);

GXDLM_IMPLEMENT( OBUpdateCust, OBUpdateCustGUID);

GXDLM_IMPLEMENT_END();

For more information, see the description of the GXDLM_IMPLEMENT, GXDLM_IMPLEMENT_BEGIN, and GXDLM_IMPLEMENT_END macros in the iPlanet Application Server Foundation Class Reference.



Online Bank Registration File



The Online Bank registration file (COnlineBank.gxr) contains the GUIDs for the AppLogics in the Online Bank sample application. Blank lines, where they occur, are significant. The names given to AppLogics in the .gxr file do not necessarily have to match the class names with which the AppLogic classes are declared in code.

For more information about .gxr files, see

AppLogic COBLogin::COnlineBank

{C1B5E720-6153-11D1-A1AE-006008293C54}

COnlineBank

AppLogic CShowMenuPage::COnlineBank

{C8899CE0-61DC-11D1-A1AE-006008293C54}

COnlineBank

AppLogic CShowBalancesPage::COnlineBank

{5AE8CE70-62D0-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CShowTransPage::COnlineBank

{B10DF490-62E7-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CShowTransferPage::COnlineBank

{23F1E8F0-6388-11D1-A1AF-006008293C54}

COnlineBank

AppLogic COBLogout::COnlineBank

{0C598E40-6389-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CTransfer::COnlineBank

{2754DA40-638C-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CShowNewCustPage::COnlineBank

{C6C91850-64F0-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CShowFindCustPage::COnlineBank

{092043B0-64F2-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CFindCust::COnlineBank

{9962F0B0-64F3-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CShowCustPage::COnlineBank

{769F1300-64FC-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CCreateCust::COnlineBank

{C9103DF0-6549-11D1-A1AF-006008293C54}

COnlineBank

AppLogic CUpdateCust::COnlineBank

{951550D0-655D-11D1-A1AF-006008293C54}

COnlineBank


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

Last Updated March 05, 2002