As illustrated in Figure 4.1, all applications on the server share the same server object. All clients accessing the same application share the same project object, and all requests by the same client share the same client object.
Using LiveWire objects
Properties of LiveWire objects are strings. You can assign numerical or Boolean values to properties, but they are always stored as strings; to retrieve such values, you must convert them from strings. The parseInt and parseFloat functions are useful for converting to integer and floating point values.
Note: For more information on these functions, see "parseInt"
and
"parseFloat" .
For example, you can create an integer project property as follows:
project.totalNumber = 17
You could then increment the value of totalNumber with parseInt as follows:
project.totalNumber = parseInt(project.totalNumber) + 1
Similarly, you can create a Boolean client property as follows:
client.bool = true
Then you can check it as follows:
if (client.bool == "true")
write("It's true!")
else
write("It's false!")
Notice that the conditional expression compares bool to the string "true"
. You can use other techniques to handle Boolean expressions. For example, to negate a Boolean property, you can use something like this:
request.bool = (request.bool == "true") ? false : true
Because of this characteristic, it may be more convenient to perform application logic using top-level JavaScript variables and then assign the final values to the appropriate object property afterward.
The request object
The request object contains data specific to the current client request. It has the shortest lifetime of any of the objects. LiveWire creates a new request object for each client request it receives. A client request for a page occurs when
When you declare top-level variables in server JavaScript, they have the same lifetime as request properties. For example, the declaration
var number = 42
will persist during the current request only.
In addition to the predefined properties and automatically initialized data, you can create request properties by using form elements and by encoding properties into the request URL, as described in the following sections.
Using form elements
Each input element in an HTML form corresponds to a property of the request object. The property name is specified by the NAME attribute of the form element. For example, the following HTML creates a request property called guess that accepts a single character of input from the user in the text field. You refer to this property in JavaScript as request.guess.
Note: LiveWire applications do not support
file upload; You
cannot submit an
INPUT element of
TYPE="file" to a
LiveWire application.
<FORM METHOD="post" ACTION="hangman.html">
<P>
What is your guess?
<INPUT TYPE="text" NAME="guess" SIZE="1">
A SELECT form element that allows multiple selections requires special treatment, because it is a single property that can have multiple values. The getOptionValue function enables you to retrieve the values of selected options in a multiple select list. For more information, see "Using select lists."
Working with image maps
The ISMAP attribute of the IMG tag indicates a server-based image map; when the user clicks the mouse when the pointer is over an image map, the horizontal and vertical position of the pointer are returned to the server.
The imageX and imageY properties return the position of the mouse cursor when the user clicks on an image map. For example:
<A HREF="mapchoice.html">
<IMG SRC="images/map.gif" WIDTH=599 WIDTH=424 BORDER=0 ISMAP ALT="SANTA
CRUZ COUNTY">
</A>
The page mapchoice.html
will have properties request.imageX and request.imageY based on the mouse cursor position where the user clicked.
Encoding request properties in URLs
You can manually encode request properties into URLs by using the following syntax:
URL?varName=value[&varName=value...]
where URL is the base URL, varName is a variable name, and value is its value. This scheme requires following the base URL by a question mark (?) that is then followed by pairs of variable names and their values. Separate each pair with an ampersand (&). This creates a request property named varName for each variable listed.
For example, the following HTML defines a hyperlink to a page that instantiates the request properties i and j to 1 and 2, respectively. The JavaScript file refpage.html can then reference these variables as request.i and request.j.
<A HREF="refpage.html?i=1&j=2">Click Here</A>
If you encode properties in server-side JavaScript, use addClient to ensure that client property values are maintained, in case the application uses URL-encoding for client maintenance.
Note: See "Maintaining
client properties with
URL encoding."
The escape and unescape functions are provided for encoding in a URL names or values that may include special characters. In general, if an application needs to generate its own name/value pairs in an URL request, you should use escape and unescape, to ensure that all values are interpreted properly. For more information, see "Encoding values in URLs."
Values of URL-encoded request properties are not reset when the user reloads a page (for example, by clicking the Reload button). In the previous example, if the user reloaded refpage.html, then i and j would remain 1 and 2, respectively.
The client object
Because many clients can access an application simultaneously, the client object provides a method for dealing with each client individually. It provides a technique for tracking each client's progress through an application across multiple requests.
LiveWire creates a new client object each time a new (unknown) client accesses an application. LiveWire provides the same client object each time the client returns to the application with a subsequent request. Hundreds or thousands of client objects can be active at a single time.
Properties
There are no predefined property values in the client object, because it is intended to contain any data required by the application. JavaScript statements can assign application-specific values to the client object, as in the following example:
client.name = "Alligator, Inc."
This statement assigns the value "
Alligator, Inc."
to the client property name. LiveWire automatically maintains these user-defined property values using the technique you specify when you install the application.
LiveWire does not save client objects that have no property values. Therefore, if an application does not need client objects and does not assign any client object property values, it incurs no additional overhead.
A good example of a client object property is a customer ID number. A user might enter the ID number when first accessing the application, or the application might assign a dynamic customer ID, for example,
client.custID = assignID(client.ip)
Once the customer ID has been established, it would be inconvenient to require the user to re-enter the ID. However, without a facility like the client object, there would be no way to associate the correct customer ID with subsequent requests from a client.
The client object lifetime
The client object has a built-in expiration mechanism, because once a client accesses an application, there is no guarantee that it will request further processing or will continue to a logical end point. This mechanism allows LiveWire to occasionally "clean up" old client objects that are no longer necessary. Each time the server receives a request for a page in an application, LiveWire sets the lifetime of the client object.
By default, the client object expires after ten minutes. An application can control the expiration of a client object to make it longer or shorter than the default. An application can change the expiration of a client object with the expiration method, as follows:
client.expiration(seconds)
where seconds is the number of seconds until the client object expires.
You must use expiration in each page of an application for which you want a client expiration other than the default. Any page that does not specify an expiration will use the default of ten minutes.
Note: Expiration does not
apply if using client
URL maintenance;
See "Techniques for
maintaining the client
object."
Using destroy
An application can explicitly destroy a client object with the destroy method, as follows:
client.destroy()
When an application calls destroy, LiveWire removes all properties from the client object.
If you are using client-cookies to maintain the client object, destroy eliminates all client property values, but it does not affect what is stored in the Navigator's cookie file. To eliminate property values from the cookie file, use expiration with an argument of zero seconds.
When using client URL to maintain the client object, destroy will remove all client properties after the method call. However, any links in a page before the call to destroy will retain properties in their URLs. Therefore, you should generally call destroy either at the top or bottom of the page when using client URL maintenance. For more information, see the next section.
When using server IP address to maintain the client object, all requests from the same client machine will use the same client object; therefore destroy will eliminate all client properties for all applications on the server.
Techniques for maintaining the client object
A LiveWire application can use several techniques to maintain the client object. You select the technique to use when you install or modify the application with the LiveWire Application Manager, as explained in "Installing a new application."
There are two basic approaches for maintaining the client object: maintain it on the client or use an addressing scheme to maintain it on the server. The client-side techniques use either cookies or URL encoding to maintain client property values. The server-side techniques use either cookies, URL encoding, or IP addresses to refer to a data structure on the server that contains client property values.
Client-side techniques
There are two client-side maintenance techniques:
Each client object property is encoded in the cookie file as follows:
NETSCAPE_LIVEWIRE.propName=propValue;
where propName is the name of the property and propValue is its value. Each name/value pair is limited to 4,096 characters.
There can be at most twenty client properties using this technique. If you create more than twenty properties, the oldest (first created) properties will be eliminated.
When using client cookies, the expiration time you specify should be large in comparison to the time it takes for clients to get a response from the server, so that client properties do not expire before the user can respond. For example, if you anticipate that it may take at least ten seconds for clients to receive a response from the server, expiration should be ten minutes (the default) or more.
Note: For information on
using the expiration
method, see "The
client object lifetime."
When using client cookies, destroy eliminates all client property values, but does not affect what is stored in the Navigator's cookie file. Instead, use expiration with an argument of zero seconds.
Using client URL encoding
In the client URL encoding technique, the server transfers all object information to the client as name/value pairs appended to URLs that reference other portions of the application. This scheme requires that all URLs be dynamically generated by the server. The object information must be transmitted multiple times for pages that refer to multiple URLs.
The size of an URL string is limited to 4 Kbytes; therefore, when using client URL encoding, the total size of all the name/value pairs of client object properties is somewhat less than 4 Kbytes. Any information beyond the 4 Kbyte limit is truncated.
When using client URL encoding, you must use the addClient function to maintain property values to generate URLs dynamically or use the redirect function.
Note: For more information, see "Maintaining
client properties with
URL encoding."
When using this technique, the client object does not expire, because it exists solely in the URL string residing on the client. Therefore, the expiration method does nothing.
Also, when using the client object's destroy method, you should use it either at the beginning or end of your page, so that all links in the page are given the same set of client property values. If you use destroy in the middle of a page, then the links that come before the method call will have property values appended to their URLs, but those that come after the method call will not have any values appended; therefore, client property values will be propagated to some pages but not others. This is generally undesirable.
Another drawback of client URL encoding is that when you submit a form, you lose all client properties. This is because of the way Navigator requests URLs when submitting forms. A workaround to this limitation is to encode all client properties into hidden form elements when generating the page.
Preserving client properties
When an application uses client-side maintenance techniques, properties of client are encoded into the server's response to a client request, either in the HEAD of the response (for client cookies) or in server-generated URLs (for client URL encoding). Therefore, you cannot change client object properties after performing a flush previously on the same page. LiveWire performs an automatic flush after generating 64 Kbytes of output.
Note: For more information on flush, see
"Flushing the output
buffer."
Important:
To prevent losing any information, you should assign all client property values early in the scripts on each page. In general, you should ensure that client properties are set before the application generates 64 Kbytes of content, when it automatically flushes the output buffer.
Server-side techniques
There are three server-side maintenance techniques:
The project object
The project object contains global data for an application and provides a method for sharing information among the clients accessing the application. LiveWire creates a new project object when an application is started, and each client accessing the application shares the same project object.
LiveWire automatically destroys the project object when the application is stopped. A typical project object lifetime is days or weeks.
LiveWire creates a set of project objects for each distinct Netscape HTTP process running on the server. LiveWire creates a project object for each application running on each distinct server. For example, there may be a server running on port 80 and a server running on port 142 on the same machine; LiveWire will create a distinct set of project objects for each of these processes.
Properties
There are no predefined properties for the project object, because it is intended to contain application-specific data accessible by multiple clients. A good example of a project object property is the next available customer ID. An application could use this property to track sequentially assigned customer IDs. Any client that accesses the application without a customer ID would be assigned an ID, and the value would be incremented for each initial access.
Locking the project object
When an application reads or sets a project property, LiveWire implicitly locks the property being accessed for the instant the application is reading or setting the value. This ensures that if an application is just reading or setting the value of the property, there will be no conflicts with other users. However, if an application attempts to read a property value, then assign a new value to it based on that value (for example, incrementing it), implicit locking is not sufficient.
LiveWire provides a locking facility to ensure that different clients do not change project object properties simultaneously. Use the lock method to lock project, preventing any other clients from modifying it, and then use unlock to remove the lock.
When an application locks the project object, other users accessing the application must wait until the application is unlocked before they can get or set any project properties or lock project themselves. Client requests to access a locked project object will wait until it is unlocked or until the request times out, whichever comes first.
Note: Because locking the project object blocks other users from accessing it, potentially delaying execution of their tasks, it is good practice to lock project only as much as necessary.
The following script shows how to use lock and unlock for the project object while the application is modifying the customer ID property:
project.lock()
project.next_id = 1 + project.next_id
client.id = project.next_id
project.unlock()
In general, the lock and unlock methods should be balanced. However, LiveWire automatically unlocks the project object after the completion of each client request to prevent accidental deadlock.
The server object
The server object contains global data for the entire server and provides a method for sharing information between several applications running on a server. The server object is also automatically initialized with information about the server.
LiveWire creates a new server object when the server is started and destroys the server object when the server is stopped. Every application that runs on the server shares the same server object.
LiveWire creates a server object for each distinct Netscape HTTPD process (server) running on a machine. For example, there might be a server process running for port 80 and another for port 8080. These are entirely distinct server processes, and LiveWire creates a server object for each.
Properties
This table describes the properties of the server object. In addition to these automatically initialized properties, you can create properties to store data to be shared among multiple applications.
Locking the server object
To ensure that different users or applications do not change server object properties simultaneously, there are lock and unlock methods that work exactly the same as the methods of project, described in "Locking the project object." When an application has locked the server object, other applications (or instances of the same application) cannot get or set server object properties or lock the server object.