An Interesting Case of Session State Corruption
March 21st, 2008 by JohnRecently I encountered an interesting (and very frustrating) case of session state corruption occurring in one of our ColdFusion/AJAX-based search applications. The application allows users to search for various types of listings using an interface that features AJAX pagination. This means that as users navigate through pages of search results, an entire HTML document is not reloaded; instead, asynchronous JS requests are made to pull in new result sets, and user HTML is updated dynamically on the client side.
I needed to add a feature to one part of the application that required recall of the user’s most recent search. It needed to take into account any AJAX page changes, so that the most recent page would always be recalled. After considering several options, I decided to copy the user’s latest search parameters into session data on each search request. The other component could then later read the stored data and reconstruct the user’s most recent search.
Of course, this raised the issue of preserving the integrity of session data in the presence of AJAX components. As is well documented elsewhere, when one or more asynchronous requests can occur during the course of a page load, or during the course of user interaction with a page, corruption of any shared data (such as session data) can occur. Asynchronous requests can, for example, modify such data in ways that the rest of the application ignores or does not account for. The variable timing of such requests can also create race conditions, and prevent coordination of different parts of the application.
While I recognized this and took efforts to prevent it, still something like this was exactly what seemed to be causing a problem in our application. The search parameters were being correctly stored in the session on non-AJAX requests, but with AJAX requests, the behavior was intermittent; sometimes the correct parameters were stored, and other times they would seemingly get reset to the most recent non-AJAX parameters.
But after doing some logging on the server, I noticed that in these instances two requests were actually happening on an AJAX page change–one for the newly selected page, followed by one for the page corresponding to the latest non-AJAX search. This was very bizarre. And it was not (totally) browser dependent; both Firefox and IE (6 and 7) exhibited this behavior. After enabling the Firebug request logger in Firefox, I could even see the second requests happening–right as new result sets were being loaded in. But I had no idea why they were occurring.
Of course, nothing in the AJAX code suggested that they should be. After examining a number of different things with no success in locating the problem, I thought perhaps this was some sort of obscure bug (or feature?) within either the YUI Connection Manager (which we use to initiate AJAX requests) or else the asynchronous request mechanisms implemented in both Firefox and IE. Googling for help, I initially located nothing useful until I finally stumbled across a helpful blog post…
In the post, the author describes experiencing a superfluous request on page load when an HTML IMG tag on his site contained an empty SRC attribute. And (guess what?) this just happened to be the case for some of our own images! Because some of our images were created as part of a JS-based UI component, being dynamically assigned SRC values by JS code on page load, the SRC attributes were left blank in the HTML. But this was causing both Firefox and IE to (usually) send requests to the current document’s URL–the one in the address bar–when these IMG tags were encountered. This wasn’t a critical problem for non-AJAX search requests since in those cases the document URL contained the latest search parameters; but on AJAX page changes, this was a very critical problem, as it was causing the stored AJAX search parameters to be overwritten!
The fix was, of course, to just point the offending tags to some placeholder image until the JS code updated them on page load. Once this was done, everything worked fine.
While this problem was only indirectly caused by a JS/AJAX component, it illustrates the need to take great care in preserving shared data integrity when building AJAX-enabled applications. All parts of the application must be built with AJAX in mind, accounting for the fact that shared data might be modified in unexpected ways as a result of asynchronous requests.
Tags: ajax, blank image source, blank image src, image, image source, image src, session, session corruption, session data, session state, session state corruption








