ColdFusion Application.cfc Wish - OnCommitStart() Event Method

Posted June 13, 2007 at 12:15 PM by Ben Nadel

Tags: ColdFusion

Last night at the New York ColdFusion User Group, Michael Dinowitz was talking about Application.cfc and what features were added in ColdFusion 8. Lots of good stuff that I am very excited about. After the presentation, I was telling him that I would like one more event method to be available in the Application.cfc:

OnCommitStart()

The idea is that this method would fire right before the page headers were flushed to the browser (signifying that page content was following close behind). I figure it would look pretty much just like the Application.cfc OnRequestStart() method:

  • <cffunction
  • name="OnCommitStart"
  • access="public"
  • returntype="void"
  • output="false"
  • hint="Fires right before headers are flushed to the client.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • />
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>

Now, you might be thinking, why the hell would anyone use this? Why not just use the OnRequestStart() or put something in your header includes? I am not saying that this is the most essential method, but there are some things that I think you could use it for. Before I explain, let's take a quick look at the page event method life cycle:

  • OnRequestStart()
  • OnRequest()
  • OnRequestEnd()

That's how it exists right now. But more than just the event chain, let's expand this to include the server-client communication life cycle as well (I am assuming that it is poor form to flush to the client from within OnRequestStart() since template execution decisions have not yet been made):

  • OnRequestStart()
  • -- Pre-page processing
  • OnRequest()
  • -- Pre-page-flush processing
  • -- Content processing / flushing
  • OnRequestEnd()
  • -- Final content flushing

Maybe my break down here is not correct, but to me, OnRequest() seems to cover two distinct parts of the page process. I am not saying that one of those two sub-steps should be moved to its own Application.cfc event method - that simply wouldn't make sense since both sub-steps are determined by the ColdFusion template you included in the OnRequest() method. I am saying that in between those two sub-steps, there should be one more application level event:

  • OnRequestStart()
  • -- Pre-page processing
  • OnRequest()
  • -- Pre-page-flush processing
  • -- [ Hook into OnCommitStart() ]
  • -- Content processing / flushing
  • OnRequestEnd()
  • -- Final content flushed

Ok, so why would I even bother doing this? Again, not the most important functions, but here are some things that might be useful:

  1. Notice that OnCommitStart() returns a boolean. Like OnRequestStart(), a "false" return here would signal the page to halt processing and not let content be flushed. There might be information presented in the processing template that was not available at the point of OnRequestStart() that would determine how the page should be rendered (in a centralized fashion).
  2. This would give you the ability to update the FORM scope to prepare it for display. For example, most form-submission-validation cycles output FORM data back into the HTML form (ex. <input value="#FORM.name#" />). If FORM.name contains a quote, this would break the HTML (closing the attribute prematurely). This would be a good place to replace quote characters in the FORM scope with &quot;. Of course, you don't want to do this before page processing as quote is a valid database entry, but once you have validated the FORM data and know you are going to display the page again - the quote character has no place being there.
  3. This would give you the opportunity to set flags regarding the page commitment (ie. you can no longer set page headers / cookies, etc.).
  4. This would be a perfect place to reset the content buffer to remove unnecessary white space.
  5. This would give you an opportunity to have content-specific CFSetting tags. For example, you might have EnableCFOutputOnly=true in the Application.cfc to kill extra white space, but then right before the content gets flushed, you can switch to EnableCFOutputOnly=false so that you don't have to wrap your entire HTML in CFOutput tags.

That's just off the top of my head; my gut tells me that this could be even more useful.

Now, you might look at that list and just say that all of that stuff can be accomplished already by putting tags and functions and directives in various other templates that get executed. Take for example the idea of resetting the content buffer - I could accomplish this by putting a CFContent tag (reset = true) at the top of my header files. Yes, I could do that, but that means I have to put that at the top of every single header template. Now, granted, I don't have a 100 different header templates to deal with, but if I have even more than one (ex. standard vs. print), why duplicate it at all? You could just put content reset in the OnCommitStart() and then every header you ever make will be able to execute without worrying about extra white space.

Am I crazy? Thoughts? Counter arguments?



Reader Comments

Jun 13, 2007 at 10:08 PM // reply »
12 Comments

Your Crazy.

That would come into my bottom 10% of all things i'd like to see in CF.


Jun 14, 2007 at 7:14 AM // reply »
11,246 Comments

@Dale,

I am fine with that, but out of curiosity, is it bottom 10% because the ideas discussed are not a priority OR bottom 10% because they simply don't make any sense?


Jun 14, 2007 at 8:33 AM // reply »
92 Comments

What kind of smart alec question is that Ben? Its obviously because it makes no sense whatsoever! ..Sheesh wasting our time and the Adobe CF developers as well. :) Did Michael Dinowitz post his presentation files online by any chance??


Jun 14, 2007 at 8:41 AM // reply »
1 Comments

Dale, nothing crazy. All is explained


Jun 14, 2007 at 11:23 AM // reply »
42 Comments

I'm not quite sure how I feel about it. On one hand it seems like it could provide some useful functionality (as described, and I've thought of a couple other uses).

But, on the other hand something just doesn't smell right about it. Now I could be off on this, but it seems like it would create some "gotchas" for some frameworks out there. I use Mach-ii for some projects I manage, and I'll occasionally toss a cfheader in some views that can be cached for an extended period of time. I also have a catch-all for events that don't exist and I'll put a cfheader with a 301 status code and re-direct to the default event.

But then again, I know for sure I'm crazy. ;)

Hrmm, on a side note would CF toss an error if you try to use cfheader after OnCommitStart() is ran (similar to cfflush)? Or would they change cfheader to be more like cfsetting and have it affect the whole request?


Jun 14, 2007 at 12:55 PM // reply »
11,246 Comments

@Javier,

Check out http://www.nycfug.org/ If Michael posts his stuff, it will be there. But no promises.

@Dustin,

I am like 99% sure that if you try to set a CFHeader value after the headers have been flushed, ColdFusion will throw an error. Check this out:

http://www.bennadel.com/index.cfm?dax=blog:317.view

I actually used the ColdFusion error to determine this (Before I learned how to do it via GetPageContext()).


Jun 14, 2007 at 1:27 PM // reply »
42 Comments

Yeah I knew that CF would throw an error if you used cfheader after cfflush. The same is true for cfhtmlhead.

OTOH, I suppose you might still be able to use cfhtmlhead after OnCommitStart() since it would be before the html head was sent, but after the http header was sent.

I guess you would just have to be careful about what sort of processing you were trying to preform inside OnCommitStart(), and make sure you don't place cfheader inside any templates. But! then again maybe I've just got a case of oral diarrhea (hey it happens...). :)


Jun 14, 2007 at 3:19 PM // reply »
11,246 Comments

@Dustin,

To be honest, I would advise against CFHtmlHead. I have only found that it causes more confusion than benefits. But, my experience is probably different than other people's.


Jun 14, 2007 at 4:45 PM // reply »
12 Comments

It makes sense and I understand where you could use it.

But I can't see myself ever using it and have never come across a scenario where I thought, I wish I has something here. Thus bottom 10%

I'd much rather see better OO features or complete cfscript support


Feb 7, 2008 at 12:08 PM // reply »
49 Comments

@Ben,
I am not getting what function would be performed by an OnCommitStartEvent(). We could certainly build one in but need to know exactly what the event is so we can tell when to call the method. Could you give me a little more on that request?


Feb 7, 2008 at 12:16 PM // reply »
11,246 Comments

@John,

Basically, at some point, ColdFusion begins to flush the generated content to the browser. This can either be done automatically, or via the use of a CFFlush tag. At that point, the response is considered "committed", meaning that the headers have been flushed and they can no longer be set. But really, to me, this represents the start "page content" streaming.

I figured it would be cool to have a hook into this.

I had some example of things I could do, but as my style of programming has evolved, I am not sure that all of this would be necessary anymore. But, at the time, I definitely saw some use for it.

Anyway, don't spend too much time thinking about this as I don't think m(any) people would see value in it.


Feb 7, 2008 at 12:37 PM // reply »
49 Comments

@Ben,

There is an OnPageEnd() method that gets called after processing and mark-up has been processed. I was thinking of using this for logging and stuff like that at this time. If you come up with additional use case scenario let me know and we will see how it works in.


Feb 7, 2008 at 12:40 PM // reply »
49 Comments

@Ben,

Perhaps you might be interested in our sosContent.cfc as a way to do the stuff you were thinking of for the onCommitStart() method. The CFC is up on RiaForge also. :) It is a big key to achieving success in our ICE libraries without conflict.


Feb 7, 2008 at 12:43 PM // reply »
11,246 Comments

@John,

I am gonna take a closer look at your stuff in general. At this point, I have really only watched presentations and seen blog posts. Thanks.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 24, 2013 at 5:39 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Adam Oops! My mistake! I hadn't gotten that far in my testing - I'm still baby stepping my way through the process. ... read »
May 24, 2013 at 5:13 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
Hi Jason, Thanks for checking up on that, but I still stand firm on my position. :) There are actually two listLast()'s in use, and you're right that the one using a space as a delimiter is fine. ... read »
May 24, 2013 at 4:45 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Ben I have been lurking your site for quite some time, and haven't stepped up to comment until today. Thanks for all the great info - keep it up! @Adam I believe you are mistaken... as the commen ... read »
May 24, 2013 at 11:21 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, Ha ha, let's us never speak of justifying "##" notation again :P ... read »
May 24, 2013 at 11:18 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Ah, so it was indeed how I vaguely remembered it to be: A direct assignment value = users.id[ i ] causes value to retain the sticky datatype of the query column. Although unnecessary in ... read »
May 24, 2013 at 9:11 AM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Brandon, Hi, No, I haven't been able to do that. I have just kept it as it is. ... read »
May 23, 2013 at 9:52 PM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Muhmmadibn Did you figure out a solution to launching PDFs? I am running into the same issues myself. There is no way to close the PDF or go back once you launch it. Thanks in advance! ... read »
May 23, 2013 at 6:06 PM
The Girl Who Broke My Heart, And Made Me A Better Person
Good day,ladies and gentle men, my name is Dr AMADI the great spell caster in Africa, i have help so many people for different kind of problems,who say there is no solution to problems on earth, that ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools