Internet Technologies:waa

Session management Professional

A major drawback of HTML based applications is that an HTML page is stateless. There is no state information available that would tell if an address form, for example, has been filled in already by a user so that the Web application can present the form with the correct data when the user reloads this particular HTML page. In the Klondike Computer Shop, there are two places where address data is required: the address entry form, and the purchase order form. It would be annoying for a user to have to type the same data twice in two places, so this is something a Web application must take care of and we are going to see how this is done most easily.

When you recall the discussion of the BuildAddressTable() function, you remember that the record pointer of the Customer database is moved "somehow" to the appropriate record before input controls are filled with data from the database. This is accomplished in the following way. When address data is submitted for the first time and stored in the Customer database, a session is opened by the Context object and data identifying the record is attached to this object. This data can be retrieved later from a Context object until either the session is closed or the Web browser on the remote station is terminated by the user.

The PRG code relevant for managing the session follows. From the logical point of view, it begins in the SaveAddress() function when address data is stored for the first time. It continues with BuildAddressTable() when the address table is built (at least) for the second time. All lines of code are omitted below which are not required for the logic of session handling:

01: FUNCTION SaveAddress( oHTML, oContext ) 
02:    LOCAL cLastName  := oHtml:getVar( "F_LASTNAME"  ) 
03:    LOCAL dDate      := Date() 
04:    LOCAL cTime      := Time() 
05: 
06:    REPLACE Cust->FIRSTNAME WITH oHtml:getVar( "F_FIRSTNAME" )  
07:    REPLACE Cust->ENTRYDATE WITH dDate 
08:    REPLACE Cust->ENTRYTIME WITH cTime 
09: 
10:    oContext:openSession()
11:    oContext:setCargo( "ADDRESS_DATA", { Recno(), dDate, cTime } )
12: 
13: RETURN ViewShowRoom( oHtml, oContext, ... ) 
14: 
15: PROCEDURE BuildAddressTable( oHtml, oContext ) 
16:    LOCAL aAddress 
17: 
18:    oContext:openSession()
19:    aAddress := oContext:getCargo( "ADDRESS_DATA" )
20: 
21:    IF aAddress == NIL 
22:       GOTO Lastrec()+1 
23:    ELSE 
24:       GOTO aAddress[1] 
25: 
26:       IF aAddress[2] <> Cust->ENTRYDATE .OR. ; 
27:          aAddress[3] <> Cust->ENTRYTIME 
28:    
29:          GOTO Lastrec()+1 
30:       ENDIF 
31:    ENDIF 
32: 
33:    oHtml:SLE( 'First Name:'   , 'F_FIRSTNAME', Trim( Cust->FIRSTNAME ) ) 
34: RETURN 

Each record of the Customer database gets a date/time stamp when data retrieved from the HTML object is stored (lines #3-8). The date/time stamp serves as unique identifier so that records could be deleted by another application during a session (this could be the case when a purchase order is processed by another program, but is out of scope here). Immediately after data is written to the file, the session is opened in line #10 and the record number plus date/time stamp is attached to the Context object using the :setCargo() method in line #11. The data identifying this record is saved as an array along with the symbolic name ADDRESS_DATA.

The name ADDRESS_DATA is used for retrieving the array from the Context object when the address table is requested again from the remote station. This is done in line #18 and #19 where the session is opened again. If the array exists, the record pointer of the Customer database is positioned accordingly and the input controls are filled with data that are submitted already. If the array does not exist or if the date/time stamp does not match, the record pointer is moved to the ghost record, so that input controls are filled with empty data.

When a session is opened by the Context object with :openSession(), all values attached to the object with :setCargo() can be retrieved with :getCargo() at a later point in time in your Web application. They remain accessible until the session is closed by calling the :closeSession()method. This way, the state of an HTML page edited on a remote computer can be maintained easily while a session is open. Note that there is a 1:1 relationship between a session and a Web browser. For example, if 100 remote clients connect to your Web application at the same time, there will be 100 different sessions. However, only one session can be open for one connection, or Web browser, at any point in time. This means that the method :openSession() creates either a new session or re-opens an existing one if a Web browser requests an HTML page more than once.

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.