Table of Contents Previous Section

How WOApplication Manages State

As with most activities in a WebObjects application, state management is organized around the request-response loop. The exact steps in a cycle of the loop depend on where state is being stored---on the application server (which is the default), or in the page. WebObjects uses an NSDictionary to store state data in the application---in other words, when you store objects in the application, they're kept intact in memory. (The NSDictionary class stores data as key-value pairs; you access a value through its key.) When state is stored in the page, however, state data is copied from the application server and archived into an NSData object whose ASCII representation is then put into a hidden field in the page. (The NSData class provides an object-oriented wrapper for byte buffers.) The corresponding state data is subsequently removed from the server. For a discussion of the advantages and disadvantages of each approach, see the section "Storing State in the Application vs. Storing State in the Page." For more information on NSDictionary and NSData, see the Foundation Framework Reference.

Figure 1 illustrates the general sequence of events that occurs when an application receives a request (for example, when a user clicks a hyperlink).

Figure 1. Handling a Request

The following steps describe in more detail how an application manages state when it receives a request:

  1. In its handleRequest: method, WOApplication asks the request for the stateID in its URL.
  2. A stateID is a value generated by WOApplication during request handling that's used to store and retrieve state information. A stateID is only present if the application has session or persistent variables---otherwise, the value returned is nil.

    A stateID is an NSString that has the format sessionIdentifier.key.extension ---for example, 12.124563322.234. WebObjects doesn't require this format (in case you want to implement your own stateID scheme). However, it may be useful to understand why WebObjects takes this approach.

    The sessionIdentifier uniquely identifies each user session. To prevent users from accessing the pages in another user's session, the stateID also includes a key field. The key is a randomly generated number; you can't access the pages in a session without the proper key. The key also ensures that if an application crashes and restarts (thereby renumbering the sessions), an existing session is not in danger of having its stateID duplicated. The extension is incremented with every transaction, which makes the URL for each transaction unique. This prevents the situation in which a user might be iterating on a single page, but the page is never refreshed since it's being cached by the browser.

  3. WOApplication checks to see if there is an NSData object embedded in the request. If there is, it means that state is stored in the page (instead of in the application).
  4. WOApplication restores the state using the method restoreToStateWithID: if the state is in the application, or restoreToStateWithID:data: if the state is in the page.
  5. The WOApplication object finds or creates an object to represent the request page---the page from which the request was made.
  6. The WOApplication object sends the request page object a prepareForRequest:inContext: message which stores user input in objects.
  7. The WOApplication object sends the request page object an invokeActionForRequest:inContext: message. This method invokes an action method if one has been triggered, and determines which object to use to generate the response. This is described in more detail in the chapter Inside the Request-Response Loop.
  8. WOApplication gets a new stateID. If no stateID existed before, an entirely new one is created. If there is an existing stateID, then the last part of the stateID (the extension) is incremented---this ensures that every transaction has a unique stateID. The first two fields of the stateID stay the same.
  9. The stateID method also snapshots the session and persistent variables and stores their state (whether in the application or in the page).

  10. WOApplication checks to see if state should be stored in the response page---that is, if the page contains a WOStateStorage element (this is described in more detail in the section "How to Store State in the Page").
  11. If so, WOApplication invokes stateDataForID:, which takes the state stored in the application, archives it into an NSData object, and returns the NSData object. The WOStateStorage element then puts an ASCII representation of this NSData object into a hidden field in the page.

  12. The WOApplication object sends a generateResponse:inContext: message to the object representing the response page. The method generateResponse:inContext: generates HTML for the page.
  13. State is frozen before a response is generated (it was frozen in Step 7, when the stateID method snapshotted session and persistent variable values and stored them). If you modify session or persistent variables during a response, those changes will be lost. The stored state will be used to restore state across your session the next time the application handles a request.

  14. If you're storing state in the page, WOApplication removes the corresponding state from the server using removeStateDataForID:. WOApplication performs garbage collection. Specifically, it removes the state for sessions that have timed out. This doesn't happen for every transaction---it's time-based.

Table of Contents Next Section