First of all, for the record client variables are evil. Everyone know this. Well, almost everyone. But I occasionally come across legacy ColdFusion applications that still use them. Usually these apps use a database to store the client vars, which is what I primarily wanted to cover in this series of posts. I have a feeling it's going to expand beyond that, but I'll just leave it at that for now. Specifically, I’d like to talk more in depth about how client variables work in Railo (as of 3.3.2) vs how they work in a traditional Adobe ColdFusion application (as of 9.0.1). I'm going to start by going over some basics and subsequent posts will get progressively deeper. Let's get started...
Session Variables vs Client Variables
I’m not going to exhaustively describe all of the differences between session variable and client variables in CFML. I’ll assume you already have a basic understanding of how client and session variables work. Having said that, a quick primer for Session vs Client variables is as follows:
Session variables generally are used for complex datatypes that are stored in server memory (the server’s RAM). Session variables tend to be somewhat short lived (the default is less than an hour) and I personally tend to find sessions appropriate for storing small bits of data (such as login information) to medium sized data (such as user specific query resultsets). I generally try not to persist sessions for much longer than an hour and try not to store larger datasets in session variables because they use server memory and you certainly don’t want to use it all up with sessions!
Railo does introduce some additional storage mechanisms for session variables, including persisting them longer term in a database (similar to Client variables). More details about this can be found on the Railo Documentation Wiki’s Session Storage page.
Client variables, on the other hand, are generally persisted into longer term storage (frequently a database), and tend to be longer lived (the default is 90 days!). Client variables tend to be simple datatypes, usually strings, numbers, or dates rather than more complex datatypes such as arrays or structs. I tend to find client variables more appropriate for smaller amounts of data since you’re serializing them into a persistent datastore with each request. There are apps I’ve seen out there that store large amounts of data in client variables, or serialize complex data into client variable strings, but their performance tends to suffer as a result.
Ralio also does support complex datatypes within client variables, but I haven’t seen many application in the wild using them yet, so it’s difficult to measure their performance. If you’ve worked on an application that uses this feature, please feel free to list any metrics you’ve gathered in the comments of this post.
More documentation regarding session and client variables in Railo can be found in the Railo Documentation Wiki’s Session Storage Page.
More documentation regarding Adobe’s ColdFusion can be found in the ColdFusion 9 Documentation under “Using Persistent Data and Locking”.
Creating the Client Variable Datastores & Administrative Differences
Now to get alittle more detailed about how Railo handles client variables and how this differs from Adobe’s ColdFusion. Here are some of the administrative differences and default settings you will find on a fresh installation of Railo as of 3.3.2 and Adobe ColdFusion as of 9.0.1:
Where are client setting located?
In Railo, global settings for the client scope are found in a couple of different areas. First, the global settings are found under the “Scope” menu item, along with settings for other scopes like session and application scope. Then, in order to enable a specific datasource for client variable storage, you must navigate to an individual datasource and then select the checkbox next to “Storage: Allow to use this datasource as client/session storage”.
Side note: It’s interesting to me that client and session variable storage is lumped together in Railo like this. To me this indicates that the underlying engines for each are co-mingled in Railo.
In ColdFusion, global client variable settings are found in a dedicated area of the administrator, under a menu item called “Client Variables”. All administrative client variable settings are consolidated in this area, including enabling a datasource for client variable storage.
Is the client scope active in applications by default?
By default, in both Railo and ColdFusion, client variables are turned off in the administrator and must be manually enabled via code. Railo also offers a setting in the administrator to turn client variables on by default. ColdFusion does not allow client variables to be turned on by default via the administrator. On both, this setting can be overridden via code in each individual application.
What is the default timeout for client variables?
The default on both servers is 90 days.
In Railo, the administrative default timeout is global for all applications on a given Railo server instance and is not set for each storage location. Also, the administrative setting for timeout in Railo is a very granular timespan configurable to the day, hour, minute, and second. This setting can be overridden via code in each application.
Unlike Railo, in ColdFusion, the default can be set per storage location. The administrative setting for timeout in ColdFusion is a less granular timespan configurable to the day (for example 90 days or 1 day, but not 1 day, 12 hours). This setting can be overridden via code in each application, where more granularity is available for the timeout, down to the second.
What is the default storage mechanism for client variables?
In Railo, the default storage mechanism is a file based storage mechanism. This means that Railo will persist client variable information to disk by default (more on where and how in a later post). Railo will always use "file" as the default unless you change the storage mechanism via code. There is no way to set a different default storage location via the Railo admin but this setting can be overridden via code in each application.
For compatibility with ColdFusion, Railo also allows you to specify “registry” (via code) as an option for storing client variable data. However, if you specify this 1) you are slightly insane, and 2) Railo will use file storage anyway. Railo will never store client variables in the registry.
According to this blog post from Gert Franz, if you are using "file" as the storage mechanism, Railo may also start deleting client data from disk once the total amount of disk space used to store client variable data reaches 100MB, starting with the oldest data.
In contrast, as of ColdFusion 9, the default storage location is still the registry. Starting with CF10, this setting will change to be “cookie”. The heinous default of “registry” is an artifact of default settings from a very early version of ColdFusion and have been kept around (too long) for backwards compatibility reasons.
Also - ColdFusion does not offer a file based storage location. However, if you are running ColdFusion on a platform other than Windows, your client variables are being saved to a “fake registry” anyway, which is file based. So, you are sort-of storing them in a file...
The default client variable location can be changed in ColdFusion via the administrator, and that default can also be overridden via code in any given application.
Note: The defaults for both servers are less than optimal so if you MUST use client variables, check your settings to make sure you’re overriding them via code.
How is a new client variable storage location created?
In Railo, as mentioned above, in order to enable a specific datasource for client variable storage, you must navigate to an individual datasource and then select the checkbox next to “Storage: Allow to use this datasource as client/session storage”. This will cause Railo to create tables in the database for use as storage (more on how these tables are structured in a later post).
In ColdFusion you create the datasource first, then enable that datasouce for use with client variables under the Client Variables menu item by choosing the datasource from the dropdown under “Select Data Source to Add as Client Store”. The table structure in ColdFusion is significantly different that Railo, and will also be covered in a later post.
How do you disable global client variable updates?
Certain client variables such as “hitcount” and “lastvisit” are updated with each pageview. Sometimes you’ll want to turn this off for performance reasons.
In Railo, you cannot disable global client variables via the admin, nor via code. These updates always occur regardless of settings.
In ColdFusion, you can use the administrator to disable global updates per datastore by checking “Disable global client variable updates” in each datasource.
Note: More about how these global variables work in both Railo and ColdFusion will be covered in a future blog post
Can client variables be stored in cookies?
In Railo, you can specify client variable storage in cookies in code only. There are no administrative options regarding this in the Railo admin.
In ColdFusion, in addition to configuring cookie storage via code, you have an administrator option for storing client data in cookies, including specifying cookies as the default stoage mechanism.
Note: Cookies are sent both directions (request and response) with each HTTP call and have a maximum size of 1024k, so cookies are generally not be the best option except for cases of very lightweight client data.
What is CFID and CFTOKEN and how to they work? This will be covered in a future blog post.
In Summary
I’ve covered a few of the basic defaults and options for client variables in both Railo and ColdFusion. In subsequent posts, I plan to also cover the following:
How Client Variables Work: how the cfid/cftoken/jsessionid are used and when in the request cycle client variables get retrieved and persisted
Storage Structures: A deep dive into the table structure and storage mechanisms in both Adobe’s ColdFusion and Railo
Client Variable Tuning: How to setup client variables for performance
Scaling Out: Special considerations for clustered environments
I welcome any questions or corrections in the comments of this post.