OnRequestEnd behavior changed in CF9 (was Request Variable Bug in ColdFusion 9)

Here's a weird one. I haven't had any luck finding any information about this on Google, so I'm wondering if any of you have seen this before?

I've got a CFC in the request scope and then in the onRequestEnd event I grab that CFC out of the request scope and do some end-of-request stuff with it. The problem is I can't reference the variable in my onRequestEnd event because it produces an error that says it's not defined in the scope... but here's where it gets really weird and why I KNOW this is a bug (it's not just a suspicion)... If I DUMP the variable, the cfdump tag successfully displays the CFC and all its stuff... and then produces the same "is undefined in scope" error. Here's a screen-capture.

So... anybody seen this before? 'Cause I'm totally stumped. I've already installed the 9.0.1 updater and both of the cumulative hot fixes.

p.s. Yeah, I know it says OnRequestEnd.cfm, but this is actually inside the Application.cfc onRequestEnd method -- it's a legacy from the framework dating back originally to CF5, just go with it. ;P


Okay, it just got weirder... I tried using evaluate() to set it to a local variable, which apparently works because then I dump the local variable and the dump still works even though it's now on line 2 AFTER line 1 where the error is still occurring.


EDIT: Here's the code from the Application.cfc that includes the file where the error occurs:

<cffunction name="onRequestEnd" access="public" output="true">
<cfinclude template="OnRequestEnd.cfm">
</cffunction>

It appears to have something to do with the combination of the method and the include file.

It still fails if I execute the method in the onRequestStart like this:

<cffunction name="onRequestStart" access="public" output="true">
<cfset onRequestEnd() />
</cffunction>

But it works fine if I include the file in onRequestStart like this.

<cffunction name="onRequestStart" access="public" output="true">
<cfinclude template="OnRequestEnd.cfm">
</cffunction>

HOWEVER! There's obviously more to this because I can't create a simple test case. If I create a new project with a very simple application.cfc in it and replicate all these details, it works fine. So there's something else in the framework that's contributing to it beyond just the method names and file names.

And the file name doesn't seem to actually contribute, since it still fails in the same way if I change the name of the file like this:

<cffunction name="onRequestEnd" access="public" output="true">
<cfinclude template="reqend.cfm">
</cffunction>

Okay it has nothing to do with the file... well it does, but not with the file name... At the bottom of the onRequestEnd.cfm is this code

<!--- this seems to help resolve a leaky-memory issue in CF/JRun --->
<cfset structClear(variables) />
<cfset structClear(request) />
<cfabort />

If I comment out those StructClear statements, then the error goes away, which told me that it was executing the OnRequestEnd.cfm twice... and I THINK that means that CF9 changed the behavior of the CFABORT tag and it now executes the onRequestEnd event when the tag is used... it didn't in previous versions of cf...

I didn't find documentation of this, but I did find this blog from Ben Nadel that mentions it also occurring with CFLOCATION, so it seems to be more generally about the onRequestEnd event. It seems now in CF9, no matter how a page finishes executing, the onRequestEnd event is executed at the end... That's a change from all the previous versions and so it mucks with code I had created in order to actually cause this to happen on previous versions. Since I was causing execution of the onRequestEnd and then aborting the page early, CF now executes the onRequestEnd, aborts and then executes the onRequestEnd again because of the abort. (I tested to see if this happens with an OnRequestEnd.cfm and it doesn't -- it's just the Application.cfc method.)

Luckily, this fairly simple bit of code at the top of the template seems to fix the problem:

<cfif structIsEmpty(request)>
   <cfexit method="exittemplate" />
</cfif>

Comments
Sean Corfield's Gravatar My guess is that onRequestEnd() and OnRequestEnd.cfm are *both* firing so request.tap is present as expected in onRequestEnd() but is missing by the time OnRequestEnd.cfm fires. Add some output in OnRequestEnd.cfm and I bet you'll see it twice.
# Posted By Sean Corfield | 4/21/12 11:26 AM
Sean Corfield's Gravatar (I assume onRequestEnd() is including OnRequestEnd.cfm yes?)

You need to show more code for folks to be able to help you!
# Posted By Sean Corfield | 4/21/12 11:27 AM
Sean Corfield's Gravatar Yay! I was right! What do I win? :)
# Posted By Sean Corfield | 4/21/12 4:56 PM
Ike's Gravatar A free trip to a timeshare! ;P
# Posted By Ike | 4/21/12 5:52 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress