|
Introduction
This technical note presents a sample "to-do" list application written in WML1.1 and Perl. The application source code demonstrates various techniques for managing the Openwave Mobile Browser cache. NOTE: The example code included with this technical note uses the Perl application utilities from the Openwave SDK 4.1. How the Mobile Browser Cache Works The Openwave Mobile Browser caching model is similar to the HTML web browser caching model. The biggest difference is that with the Openwave Mobile Browser, more responsibility is placed on the application developer to keep the cache in sync with the server. In traditional wired networks, the cost of asking the web server if an HTML page has changed since it was last downloaded is usually far less than the cost of reloading the page. This is not the case in wireless networks, where it may take several seconds just to establish a server connection. For this reason, the Openwave Mobile Browser does not do the if-modified-since negotiation. The Openwave Mobile Browser provides other means by which a developer can maintain cache coherency. Why Should You Care?The main goal of the cache is to reduce round trips to the server. This is important not only because of the high latency of wireless networks, but also because the user may incur a cost for every request. Making efficient use of the cache will not only make the application faster, but it could also save the user money! The trick in dealing with the cache is that you want to store decks in the cache for as long as possible, but you never want to show the user stale data. For example, a real-time stock quote service would probably not want to cache a deck containing volatile quote information. Another example is managing a list of data (e.g. a to-do list). You want list decks to be cached for as long as possible. However, when you delete or add an item to the list, you no longer want to navigate to an out-of-date list. For more information on managing the Openwave Mobile Browser cache, please refer to Chapter 2 of the UP.SDK Developer's Guide. Source Code The sample source code implements four different versions of a to-do list application. Each version builds upon the previous version and implements a better approach to managing the cache:
NOTE: Each example CGI script is written in Perl, and depends on the sample Perl utility libraries installed with the Openwave SDK in the examples/apputils subdirectory.
IMPORTANT: Change the $dataDir variable in this file to point to the path of the data directory on your web server. The directory must be writable by the web server process. This is the directory where the to-do list data files will be stored (per subscriber).
http://www.myserver.com/todo/todo1.cgiWhen the user modifies an entry in the to-do list, they will invoke a new URL similar to: http://www.myserver.com/todo/todo1.cgi?NS=SETSTATUS&sts=P&index=1There will now be two list decks in the browser's cache. Since we ignore the "Cache-Control" in this version of the to-do list, both of these decks are valid in the cache. If the user re-navigates to the main URL (todo1.cgi), they will see the older list data, since the Openwave Mobile Browser will get a cache hit on the first URL and not reload it from the server. To solve the problem, we need a way to instruct the Openwave Mobile Browser to reload the deck whenever it is navigated to...
While this solves the problem of cache consistency, it does so in a very brute force manner and does not make efficient use of the cache. Another important thing to remember about Cache-Control is that the browser will ignore a deck's Cache-Control value if a TASK=PREV is used to navigate to the deck (typically from the user pressing the Back key). This is particularly important to keep in mind when using Cache-Control. It means that a Cache-Control=must-revalidate deck can generate a cache hit. Cache-Control is also ignored if you navigate to a card in the same deck. To solve the problem, we need a way to alter the cache ID of the to-do list deck that gets returned after we modify an entry...
By removing Cache-Control=must-revalidate and adding a cache ID to the addDeck function, we now get good cache behavior. The addDeck call now looks like this: $digest->addHDMLDeck("?", sprintf($TODOLIST));
Note the use or "?" as the first parameter. The first parameter is a relative URL that will become the deck's cache ID. By setting this to "?" the cache ID will be the same as the requesting URL, only without the query arguments. So, when the user modifies a to-do list entry, a URL like this will get requested:
http://www.myserver.com/todo/todo1.cgi?NS=SETSTATUS&sts=P&index=1This resulting deck will get added to the digest and because of the "?" it will get added with a cache ID of http://www.myserver.com/todo/todo1.cgiThis is exactly what we want since this is the same URL that is used to view the to-do list. This solves the problem for the main to-do list but not for the Finished Items list. If we remove the Cache-Control=must-revalidate from that list, we still have a cache coherency problem. To make the Finished Items list have good caching behavior we need to use a cache operation...
$digest->addCacheOp($Digest::InvalURL, "?NS=FINISHED");The cache operation tells the browser to invalidate the cache entry specified by the given relative URL. This is added to the response digest. Now, the next time the user goes to the Finished Items list, it will get reloaded from the server. Before we're done, we need to add the same cache operation to the EraseFinishedItems function. This invalidates the Finished Items deck whenever the user erases an item from the list. |