Change to OnRequestEnd behavior in CF9 (was ColdFusion 9 Bug - Can't Reference a Request Variable in OnRequestEnd)

StackOverflow https://stackoverflow.com/questions/10260883

  •  02-06-2021
  •  | 
  •  

Question

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.

screen capture of request variable bug

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


EDIT: Okay, it's gotten weirder... I tried using evaluate() to set it to a local variable, which apparently works, because then I dump the local variable. The dump still works, even though it's on line 2 AFTER the line on which the error occurred?!!

enter image description here


EDIT 2: 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>

EDIT 3: 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 about this behavior with the CFLOCATION tag, 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.

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>
Was it helpful?

Solution

I decided to leave this question here (rather than deleting it) since it may help some other folks, though I found the source of the problem and a workaround while working with some of the comments and it wasn't what we thought. Ben Nadel also posted a blog about the change to CFABORT a while ago as well... and Adam Cameron tells me that although this change was added by-design in CF9 (without warning anyone apparently, since I saw no mention in the LiveDocs and added 2 comments about it), it was then removed in the (not yet released?) CF10. I think Adam might be in the beta, I'm not sure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top