Using the LiveWire object framework


iveWire comes with predefined objects for application development, collectively referred to as the LiveWire object framework: request, client, project, and server. These objects provide an easy way to maintain persistent data using HTTP, which is a stateless protocol.

Some of these objects contain predefined properties set by LiveWire. You can also define properties of these objects for application-specific uses.

The LiveWire object framework

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

Properties

The request object has four predefined properties, described in the following table.

Property

Description

Example value

agent

Name and version of the client software. Use this information to conditionally employ advanced features of certain browsers.

Mozilla/1.1N (Windows; I; 32bit)

ip

The IP address of the client; may be useful to authorize or record access.

198.217.226.34

method

The HTTP method associated with the request. An application can use this to determine the proper response to a request.

For HTTP 1.0, method is either GET, POST, or HEAD

protocol

The HTTP protocol level supported by the client's software.

HTTP/1.0

imageX

The horizontal position of the mouse cursor when the user clicked over an image map.

45

imageY

The vertical position of the mouse cursor when the user clicked over an image map.

132

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:

Using client cookie
Netscape cookies are a mechanism by which the client stores information in small files, called cookie files. In the client cookie technique, the server transfers all object information as name/value pairs to the client using the Netscape cookie protocol.

This approach is recommended for most high-volume consumer applications, because it is client-based but does not have the drawbacks of client URL encoding. However, it works only with clients that support the Netscape cookie protocol.

Another advantages of this technique is that you can use it for client-server communication. For more information, see "Using cookies for client-server communication."

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:

Because all of these techniques are server-based, all client properties will be lost when you restart the server. Restarting the application has no effect. In contrast, the client-side techniques maintain client properties, regardless of what happens on the server.

One disadvantage of server-based techniques is that they all require a database on the server, and therefore consume server disk space. For applications that are accessed by a large number of clients, this space could become significant.

When using server-based techniques, LiveWire briefly "checks out" the client object from the database when the server receives a request. If the server receives another request from the same client during this time, the second request will not get any client values. For this reason, server-based techniques can be problematic for applications that use frames. The solution is to download client property values in the parent FRAMESET document, assign them to client JavaScript variables, and then refer to them as necessary in the child frames. For information on using client JavaScript with frames, see the JavaScript Guide.

Using IP address
The IP address technique uses a data structure on the server based on the client's IP address. This approach works well in situations where all clients have fixed IP addresses; it will not work reliably if the client is not guaranteed to have a fixed IP address; for example, if using DHCP (Dynamic Host Configuration Protocol) or an Internet service provider that dynamically allocates IP addresses). This technique also will not work for clients that use a proxy server, because all users of the proxy will report the same IP address.

Another drawback of using IP address is that if a single user runs more than one LiveWire application on the same server, they will all share the same client object. If any of the applications have properties with the same name, then the applications may not work properly.

Using server cookies
The server cookies technique uses a data structure on the server based on a generated name. The first time the client accesses the application, it stores the generated name in the cookie file. The client then uses the Netscape cookie protocol to store and return this name in subsequent requests.

Using server URL encoding
The server URL encoding technique uses a data structure on the server based on a generated name. The server appends the name to URLs that reference the application. In this scheme, LiveWire dynamically generates all URLs used in the application.

Advantages and disadvantages of techniques

Each of the different techniques has various advantages and disadvantages, as summarized in the following table. You should select the technique that is most appropriate for your application.

Technique

Location

Advantages

Disadvantages

client cookies

client

Preserves properties after server restart.

Maximum of twenty properties per application, 4K per property.

Modest increase in network traffic.

client URL encoding

client

Works with all clients.

Preserves properties after server restart.

Lose client properties when submit a form.

Cannot control client expiration.

Requires using addClient for dynamic links or redirects.

Largest increase in network traffic.

IP address

server

Works with all clients.

No increase in network traffic.

Does not support dynamic IP access providers, DHCP, or users behind proxy servers.

Properties lost when server restarted.

Consumes server disk space.

All applications on one client machine share one client object

server cookies

server

Little increase in network traffic.

Properties lost when server restarted.

Consumes server disk space.

server URL encoding

server

Works with all clients.

Little increase in network traffic.

Lose client properties when submit a form.

Requires using addClient for dynamic links or redirects.

Properties lost when server restarted.

Consumes server disk space.

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.

Property

Description

Example

hostname

The full hostname of the server, including the port number.

www.acme.com:85

host

The server name, subdomain, and domain name.

www.acme.com

protocol

The communications protocol being used.

http:

port

The server port number being used; default is 80 for http.

85

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.