Little things in ColdFusion 7

Pete Frietag has been blogging about a lot of great new features of ColdFusion MX 7 that haven't received much hype. I had missed many of these. I highly recommend that you read up on the new features if you are getting (or thinking about getting) ColdFusion MX 7.

Application Events: onRequest

I mentioned in a previous blog entry that I had a site (Oklahoma Medical Reserve Corps) that is XHTML 1.0 Strict and can also be served up in MS Word. As I mentioned in that entry, the two unfortunately conflict on one point:

XHTML 1.0 Strict doesn't allow an align attribute in an img tag, instead relying on CSS for positioning. MS Word, meanwhile, expects an align attribute and fails to recognize my CSS for image alignment.

I have been unable to find a way to solve the problem in CFMX 6.1 so far (If you do, please let me know). In ColdFusion MX 7, however, it would be pretty easy.

ColdFusion MX 7 comes with a new feature called Application Events which uses a new special file called "Application.cfc". If you use Application.cfc, then Application.cfm and onRequestEnd.cfm won't fire. Application.cfc allows you to capture errors, the start and (ta da!) end of a session, the start and end of an application, and the start and end of a request. It also allows you to supercede the request event (the page being called) as well.

OK. No time today to cover all of the things you can do with Application Events right now, so I will try to make this example as painfully simple as possible. Let's first replace (in the laziest way possible) our existing site structure with Application.cfc. Keep in mind, that this approach is for illustration only. I don't necessarily recommend you literally do what I am doing in practice.

Application.cfc:

<cfcomponent>
<cffunction name="onRequestStart"><cfinclude template="Application.cfm"></cffunction>

<cffunction name="onRequestEnd"><cfinclude template="OnRequestEnd.cfm"></cffunction>
</cfcomponent>

We have changed our code to use Application.cfc without changing the behavior of our site at all (keep in mind that you only need the onRequestEnd part if you site is using OnRequestEnd.cfm).

Now let's add an OnRequest event which will supercede the normal calling of the page. Note that any variables-scoped variables created in Application.cfc (or any file included by Application.cfc) will be available to the file being requested if-and-only-if it is included via the onRequest method.

<cfcomponent>

<cffunction name="onRequestStart"><cfinclude template="Application.cfm"></cffunction>

<cffunction name="onRequest">
<cfargument name="targetPage" type="string" required="true">
<cfinclude template="#arguments.targetPage#">
</cffunction>

<cffunction name="onRequestEnd"><cfinclude template="OnRequestEnd.cfm"></cffunction>
</cfcomponent>
Still no change in behavior. So far, so good. OK, now that we have changed the structure of our code, let's take advantage of that change. From now on, I am only going to look at the code in the "onRequest" event.

So, in the onRequest event, we have this:
<cfinclude template="#arguments.targetPage#">

Now let's check if this page is being served up in MS Word.
<cfif isDefined("url.format") AND url.format eq "word">
<cfinclude template="#arguments.targetPage#">
<cfelse>
<cfinclude template="#arguments.targetPage#">
</cfif>
All we have to do now is change our class="right" and class="left" to align="right" and align="left" when the document is being served in MS Word.
<cfif isDefined("url.format") AND url.format eq "word">
<cfsavecontent variable="contents"><cfinclude template="#arguments.targetPag#"></cfsavecontent>
<cfset contents = ReplaceNoCase(contents, 'class="right"', 'align="right"', 'ALL')>
<cfset contents = ReplaceNoCase(contents, 'class="left"', 'align="left"', 'ALL')>
<cfoutput>#contents#</cfoutput>
<cfelse>
<cfinclude template="#arguments.targetPag#">
</cfif>
That's it! Now, it should be noted that this code would replace all instances of class left or right with align in all tags (not just 'img') but won't get instances where more than one class is used on a single element. Perhaps a regular expression is needed, but that is a topic for another day. Nevertheless, the problem (at least in its simplest form) is solved.

That should provide a nice glimpse into Application Events. I will cover more on Application Events in future posts. Good luck!


Want to learn more about Application.cfc? Check out the Managing Requests in Application.cfc in Macromedia LiveDocs.

ColdFusion MX 7 is Released

The newest version of ColdFusion (ColdFusion MX 7) has been released today. It is a pretty exciting new release. Unfortunately, Macromedia chose to restrict event gateways to the enterprise edition which dramatically reduces the incentive to upgrade.

Even so, it is worth taking a look at:
http://www.macromedia.com/software/coldfusion/

ColdFusion Developer's Journal will be covering the new release pretty extensively.
http://www.sys-con.com/story/?storyid=48103

I will also try to discuss some of the new features in future entries. Application Events are pretty exciting and will likely be covered tomorrow.

Maintaining a Session

On the CF-Talk list, Richard Colman asked how he could keep a session alive for longer than the 30 minute limit imposed by Crystal Tech.

Michael Dawson provided a very good answer (quoted below):


I setup my intranet so that, even if the session times-out, it will be transparent to the end-user. I do this by keeping a separate session cookie.

When the session times-out, then the user accesses another page in the application, my scripts will reload the data in the session scope again. The end-users have not complained about this process.

In addition to that approach, I would suggest the following bit of JavaScript:
function keepAlive() {
var imgAlive = new Image();
var d = new Date();
imgAlive.src = '/alive.cfm?d=' + d;
}
setInterval("keepAlive()", 20*60*1000);

Before the script is added to your site, add a small alive.cfm file to the root of your site (name it whatever you wish, just be consistent). The script makes sure that a page is requested from your ColdFusion server by their browser every 20 minutes (safely less than the 30 minute time-out). Alive.cfm need not return an image - JavaScript doesn't check.

Keep in mind that this only works for users who have JavaScript enabled, so make sure to use this technique in conjuction with (not in place of) the approach suggested by Michael Dawson.

This technique actually has a great many uses that I will try to post in future entries. I have used it in the past to change database data without a form submit and also for JavaScript error handling.

Update!

Martin Perry added this suggestion to the discussion to get around the JavaScript issue:
Alternatively, to get around the JavaScript bit, create an invisible IFRAME which has it SRC set to the alive.cfm.. On Alive.cfm, add a HTTP redirect to redirect back to itself after 1200 seconds.

<META HTTP-EQUIV="Refresh" CONTENT="1200;URL=/alive.cfm?cachebuster=<cfoutput>#createUUID()#</cfoutput>">

I never think about IFRAME myself (trying to remain standards compliant). Nevertheless, it is an excellent suggestion. Good call Martin!

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.