Thursday, June 27, 2002

Nifty JavaScript Menus
OK, here's an example of something not CFMX-specific, but it may be helpful anyway. Have you ever wanted more attractive drop-down menus for your site? Perhaps like these? You can have them, and pretty easily. They're also compliant with most browsers. Get the FREE code to be able to do this, called the "HV Menu" script, at http://www.dynamicdrive.com/dynamicindex1/hvmenu/index.htm. Indeed, the entire DynamicDrive site is a repository for still more cool JavaScript menuing and other interface packages.
J2EE Session Variables

I mentioned in the previous note on New URLSessionFormat() Function that CF now supports "J2EE sessions". What are they? And why would you care? Well, as a coder, it's possible that they'd only add benefit and, again, there's little reason not to use them. Again, it's a feature set in the CFMX Administrator, in the "memory variables" page, checking the "Use J2EE session variables" option and restarting the server.

As mentioned, J2EE sessions work by sending to the client a cookie not with CFID and CFTOKEN but instead JSessionID. (Actually, if CFAPPLICATION has CLIENTMANAGENT="yes", then the CFID/CFTOKEN pair are still sent, to support client variables only.)

There's more to the difference between the CFID/CFTOKEN pair and JSessionID than just the name. First, the JSessionID value is a more elaborate combination of characters (including a UUID). As mentioned in the previous note on Optional UUID for CFTOKEN, the default CFID/CFTOKEN pair are simply a few numbers each. That makes them easy to guess. That previous note showed that you can change the CFTOKEN to use a UUID, so that benefit may seem diminished.

But there are still more differences, and they can be very important to some. First, and coolest of all, is that J2EE sessions work the way most developers have long wished CF session variables would: when your user closes their browser, the session is terminated as well. Halleluiah!

Actually, to be completely accurate, it must be said that the session closes when the last browser instance open is closed. If the user has opened several Netscape windows, for instance, then only when they’ve closed them all will the session terminate. All Netscape windows share the same JSessionID.

With Internet Explorer, things are a little trickier. If multiple windows have been opened with the File>New>Window command or Ctrl-N keyboard shortcut, they'll share the same session and closing them all will terminate that session. But if you open an IE window with Start>Programs>Internet Explorer (or click the IE icon in the task bar launcher), that will open a new session.

Therefore, it's possible to have sessions for some windows terminate when closed while still having other IE windows open. But, again, closing them all will terminate any sessions with J2EE session variables enabled.

How does the mechanism work that allows the session to terminate when the browser is closed? Some may have already guessed it: the JSessionID that’s used for J2EE sessions is set as a non-persistent (or “per-session” or “temporary”) cookie. That means simply that the cookie value is not stored persistently in the browser user’s hard drive. It’s held only in the browser’s memory. So when the browser (all its instances) is closed, the JSessionID is lost. On the next visit by that user in a new browser window, they are given a new JSessionID.

This also points out that another benefit of using J2EE sessions for those organizations that are not allowed to use persistent cookies (such as the CFID and CFTOKEN cookie values set by CFMX and previous versions). These organizations can use J2EE sessions much more easily than they could CF-based sessions. There are ways in all releases of CF that they could force the CFID and CFTOKEN to be non-persistent, as outlined in the Macromedia Technote at http://www.macromedia.com/v1/Handlers/index.cfm?ID=21079&Method=Full. With J2EE sessions, they need not bother with that.

One final benefit of using J2EE sessions, which may or may not impress most CF developers, is that using them allows sharing of session variables with JSP and servlet programs also run under CFMX. That could be valuable, if you start exploring that capability.
Optional UUID for CFTOKEN
I mentioned in the previous note (New URLSessionFormat() Function that one of the challenges of CFID and CFTOKEN pairs is that if the value is displayed on the URL, it's just very easy to guess. The CFID/CFTOKEN values are just a few simple numbers. By trying different numbers, a user may be able to impersonate or "spoof" another user's session (or client) variables. (And this really isn't a concern just if you pass them on the URL. Anyone familiar with the process can simply type a CFID/CFTOKEN pair on any URL running a CF template and possibly guess an active pair.)

So another new feature of CFMX, which has nothing to do with J2EE session variables, is that you can ask the server to generate more elaborate UUIDs (universally unique identifiers) for the CFTOKEN. This is enabled in the Administrator, on the "server settings" page, by checking the option "Use UUID for cftoken". (The fact that this is not on the "memory variables" page reinforces the point that the CFTOKEN is used for both client and session variables.) You will need to restart the CFMX server for this change to take effect. You need not change any code to benefit from this new feature.

After enabling them, you may see that CFTOKEN values look more like this, as an example: 15ce46ab4e29af0a-AF695847-F92F-344A-133252991FB6C3B5. (You can see it yourself with <cfoutput>#cftoken#</cfoutput>.) Definitely a lot harder to randomly guess an active value! It's a feature that probably should be enabled by all sites, just for the added protection. The only risk is if you have any code that for some reason relies on the CFTOKEN being the simpler 8-digit number (or are storing the CFTOKEN in a database column that needs to be widened).

One side note: the ability to use a UUID for CFTOKEN isn't really new in CFMX. It's just easier to enable. In CF 4.5 and 5, it requires a manual registry change. See the Macromedia Technote at http://www.macromedia.com/v1/Handlers/index.cfm?ID=22427&Method=Full for more.
New URLSessionFormat() Function
This first new feature is a real hidden gem that's not been played much at all. To understand its value, some background may be necessary. If you've needed to support session (or client) variables, then you know that these features rely primarily on the browser supporting cookies to be able to keep track of the user's identity (using what CF calls the CFID and CFTOKEN values it generates for each visitor).

Problems arise browsers that don't support (or are by mandate not allowed to accept) cookies visit your site. In that case, you must manually append the CFID and CFTOKEN to the URL used in any HTML you send to the browser that passes the user back to your server, such as <A HREF> and <FORM ACTION>. (The <CFLOCATION> tags also had an option called ADDTOKEN="yes" that accomplished the same thing).

If you've simply not been paying attention to this issue, then you may be suffering when users visit your site who don't support cookies. They never keep session variables from page to page, for instance. That can wreak havoc on a login process! And they also can't keep client variables from visit to visit.

But the converse is that you shouldn't ALWAYS append these values to a URL, because that leaves your site open to several potential problems. If someone passed a bookmark of a URL with a given CFID/CFTOKEN pair shown, the user receiving that bookmarked URL will also now use the first user's CFID/CFTOKEN pair. Have you ever heard of two people seeming to share a session? This is one of the ways it happens.

Another challenge is that someone can just guess at CFID/CFTOKEN values when displayed this way on a URL (more on another way to solve that problem in a moment).

So the optimal way to handle this (pre-CFMX) is to somehow test if cookies are supported for the user running the template, and then only if they're not, append the CFID/CFTOKEN value. The code to do that isn't too difficult, but getting it right and then placing that CFIF logic around every instance of <A HREF>, <FORM ACTION>, or <CFLOCATION> (deciding whether to use ADDTOKEN="yes") could be challenging.

Enter the new URLSessionFormat function! With this simple function, you can now let CFMX worry about whether to append the CFID/CFTOKEN pair (and/or the JsessionID if using J2EE sessions, as discussed in a moment.) Here's a simple example:
<cfoutput>
<a href="#URLSessionFormat("MyPage.cfm?name=bob")#">some link</a>
</cfoutput>

If CFMX detects that the browser executing this template isn't passing the needed cookie (CFID/CFTOKEN for CF session and client variables, JsessionID for J2EE session variables), then it will turn that output HTML into the following:
<a href="MyPage.cfm?name=bob&cfid=xxxx&cftoken=xxxxxxxx">some link</a>

On the other hand, if CFMX detects that the needed cookies are being passed in by the browser, it leaves the identifiers off. Very cool! And note that it's smart enough to realize if the URL already has something in the query string (as it does above), in which case it uses an ampersand (&) to append the identifiers. Ta da! (In that example, I'm not yet showing what it looks like if J2EE sessions are being used.)

Now, there is one gotcha. If you also need to use a URLEncodedFormat function for some part of the query string that has embedded spaces or special characters, it could become pretty cumbersome to use both functions in a single line of code, with embedded functions and strings within those functions. The following looks butt-ugly, but will indeed work:
<cfoutput>
<a href="#URLSessionFormat("MyPage.cfm?name=#URLEncodedFormat("billy bob")#")#">some link</a>
</cfoutput>

One other observation: I've noticed that when using J2EE sessions, it's possible for the resulting URL to appear in the format: MyPage.cfm;JSESSIONID=8030949691025145133137?name=bob. Note, however, that in this case the JSEssionID is being appended to the filename separated by a semicolon, rather than appended to the query string. Still, when it's happened, the URL has functioned as expected.

It may be worth pointing out that technically, this function's name isn't completely accurate. It's needed not just for session variable handling but client variable handling as well. In other words, if you use client variables but not session variables, this is still the way to guarantee that the CFID/CFTOKEN pair needed for client variable support as well is sent to browsers that don't allow cookies. (Indeed, if Client variables are in use in that previous example showing the JSessionID, then the CFID and CFTOKEN would be appended to the query string as they were above.)

You also shouldn't dismiss browsers that don't support cookies as being antiques not worthy of your concern: there are many organizations that force users to disable cookie support in their browsers. This solution helps you support them as well.
Pre-compiling CF Templates

See my entry of 8/24/02 for important updated information and a new precompile.bat file


You may know that CFMX now compiles templates into Java classes. You may also have noticed that this means the first user to run a template after it’s created or changed will suffer a small hit (up to a couple seconds) while it’s compiled the first time.

You can help alleviate that wait by pre-compiling one or more templates. To do so, you’d want to create a file called, for instance, precompile.bat, with the following lines:
set MX_INSTALL=c:\cfusionMX
set PATH=%MX_INSTALL%\runtime\bin;%PATH%
java -classpath %MX_INSTALL%\lib\cfusion.jar
   coldfusion.tools.Compiler -webroot
   %MX_INSTALL%\wwwroot %*

(That should just be 3 lines in our batch file, 2 starting with "set" and one starting with "java".)

Save it in your \wwwroot directory. You’d also want to change that first line to point to your directory (wherever you’ve installed CFMX). Then, from the DOS command prompt, running in that \wwwroot directory, you’d simply name the directory whose files (and subdirectories of files) you want to compile, as in:

Precompile mydir

If this command is successful, you’ll see a display indicating that it’s compiling each file, one at a time, and reporting how long it takes to compile. Very nifty!

If you’re not familiar with getting to the DOS command prompt, or running .bat files from a specific directory, seek help from someone with that knowledge. It’s important, to use the command in the way I’ve described, that you place this file in the \wwwroot directory, otherwise you need to provide the complete path to the directory whose files you want to compile.

Note that if you want to precompile all the files in the entire wwwroot, you can use the command:

Precompile .

This tells it to compile the current directory (as indicated by the “.”), and it will automatically search all the subdirectories as well. Beware of this option, as this will also compile the CFDOCS and CFIDE directories that come with CFMX. That’s over 2000 files, not counting your own! (And the tool doesn’t know to skip files it’s already compiled.)

A final important note is that without some extra work, this trick will only work if you are storing your CFMX templates in the \wwwroot location. If you have chosen to configure CFMX to run code in another directory, you can’t precompile that code using the batch file above. I'll post a new entry showing how to resolve that shortly.

How About Free servlet/JSP Hosting?
OK, this isn't related to CFMX directly, but if you wanted to have free hosting for JSP/servlet on a server other than CFMX, check out http://www.mycgiserver.com. This could be useful if you wanted to compare how a servlet/JSP works in a server other than CFMX.

Just note that the FAQ for setting things up may not be as clear as it can be. I've posted a note in their "mycgiserver.suggestions" forum, titled "Some info missing from the FAQs" and dated 6-27-02 that may help you get started. It doesn't appear I'm allowed to provide a URL that you can use, but there is a search feature there. (You must be logged in as a member to see the forums.)
Welcome to my first posting on my new blog, CFMXPlus. I hope you'll enjoy the tips I have to share. Actually, I've been blogging before it was called that. Check out the tips I used to post (from 1997-2002) at: http://www.systemanage.com/cff/cftips_index.cfm

Free CFMX Hosting
Interested in trying out CFMX but don't want to (or aren't allowed to) install it? HostMySite, a hosting provider, is offering free trial (non-production) access to CFMX for a limited time. Check out the form at https://www.hostmysite.com/cfmx.hms.