Posted 09/18/2006 in coldfusion

[DISCLAIM -> This is a draft writeup on the manifestation of a Coldfusion Memento Pattern]

There are several cases that can provide the need for a memento pattern in any web application - here are a few examples Need 1: An E-Commerce Wishlist or saved sale/plan Need 2: The ability to use "session" variables within a true clustered environment

My manifestation of a memento pattern was brought from the need to facilitate the use of session variables in a clustered environment. With that need and following manifestation, we were able to facilitate more "plush" features. The need comes from the fact that conventional "session" variables are stored in local volatile memory on the specific server machine the single request was originated from. With a true load-balanced cluster without session-persistence we had a problem.

True load-balanced clusters do not set persistant connections. This means that every single incoming request is directed to the machine with the lowest load that is in the pool of availible servers. A persistent cluster takes the first incoming request from a specific IP address and routes it to the lowest load server in the pool. That IP address is then directed to the same server in the cluster for the duration of their visit. Their visit is usually determined by a timeout per the last request. This timeout always matches the timeout of the session variable information. This is not a true load-balancing environment but needed in the case of using stock ColdFusion "session" variables. The HUGE caveat of this is those users on a series of caching web proxy servers - case in point: ANY AOL user. A single AOL user's visit to a specific site can easily be come from numerous IP addresses - each of which point to a completely different caching web proxy server. This means that a single AOL user's experience can potentially come from numerous IP addresses hence rendering IP-based persistance in a cluster useless. This opens the door to the need to avoid ColdFusion's "session" variable storage methods.

Since we cannot use the stock ColdFusion "session" variables - because of what we outlined above - this opens the door to the need for the use of ColdFusion's "client" variables. What is the difference between the two? Here's the list: The simple fact that "client" variables can be stored in the database instantly proves it to be the only viable option when in use with a non-persistant true cluster. The only limitation is how to store comlex data in a simple data storage facility such as a client variable. This is where I open another door to a memento pattern that allows for the use of "session" information via the "client" variable storage facility allowing for full-use in a true clustered server environment.

[memento Application.CFC initialization and storage]
	<cfset THIS.clientManagement="Yes">
	<cfset THIS.sessionManagement="Yes">
	<cfset THIS.sessionTimeout="#CreateTimeSpan(0, 0, 20, 0)#">

	<cffunction name="onRequest">
		<cfargument name = "targetPage" type="String" required=true>
		<!--- with this code - arguments.targetPage is ignored 
		and all requests go to the index.cfm "handler" --->
		<cfinclude template="index.cfm">

	<cffunction name="onRequestStart" returntype="boolean" output="No">
		<cfset ShopCart = createObject("component", "Cart")._init()>
		<cfreturn true>

	<cffunction name="onRequestEnd" output="No">
		<cfif IsDefined('ShopCart')>
			<cfset ShopCart._save()>

[memento CFOBJECT instantiation]
<cfcomponent displayname="Cart" output="No">

	<!--- Fuax Pax Constructor --->
	<cffunction name="_init" access="public" returntype="Cart" output="No">
		<!--- init the default cart variables --->
		<cfset THIS.Cart = StructNew()>
		<cfset THIS.Cart.SubtotalPrice = 0>
		<cfset THIS.Cart.TotalTax = 0>
		<cfset THIS.Cart.TotalPrice = 0>

		<cfif IsDefined('client.Cart') and IsWDDX(client.Cart)>
			<cfwddx action="wddx2cfml" input=#client.Cart# output="THIS.Cart">

	<!--- Save Cart function - being called from Application.CFC::OnRequestEnd --->
	<cffunction name="_save" access="public" returntype="struct" output="yes">
		<cfargument name="storage" type="string" required="no" default="client">

		<!--- save the Cart object --->
		<cfif IsDefined('THIS.Cart')>
			<cfwddx action="cfml2wddx" input=#THIS.Cart# output="">

	<!--- And the rest of your "shopping cart" functionality... --->


NOTE: It is imperitive that you do NOT use CFABORT because it will prohibit the call to the Application.CFC's onRequestEnd function. This is a HUGE caveat for this methodology. Watch out for other code used calling for a CFABORT. I found with an older version of CFAJAX that the main handler calls a cfabort by default throwing the entire application off.

[DISCLAIM -> This is a draft writeup on the manifestation of a Coldfusion Memento Pattern]
new comment
EMAIL (hidden)
MESSAGE TAGS ALLOWED: <code> <a> <pre class="code [tab4|tabX|inline|bash]"> <br>