ColdFusion Application.cfc OnRequest() Creates A Component Mixin

Posted July 2, 2007 at 8:30 AM by Ben Nadel

Tags: ColdFusion

A lot of people have trouble wrapping their heads around the OnRequest() event method of the ColdFusion Application.cfc component. I have to admit, at first, you just accept that it works, but you don't quite understand the magic that's behind it. The truth is, the OnRequest() event method really treats the target template as a component mixin. Understanding this will really help you to see what data the requested page has access to and in what context the page is actually executing.

Let's take a look at a standard OnRequest() Application.cfc event:

  • <cffunction
  • name="OnRequest"
  • access="public"
  • returntype="boolean"
  • output="true"
  • hint="Executes the requested ColdFusion template.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • hint="The requested ColdFusion template."
  • />
  •  
  • <!--- Include the requested ColdFusion template. --->
  • <cfinclude template="#ARGUMENTS.TargetPage#" />
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>

And, let's assume that the target page being passed into the OnRequest() event method is this HTML page:

  • <html>
  • <head>
  • <title>OnRequest() Mixin</title>
  • </head>
  • <body>
  •  
  • <p>
  • This is the target page. Sweet!
  • </p>
  •  
  • </body>
  • </html>

In this event code, the user-requested page is passed in as the only argument. We then, turn around and CFInclude that target page for execution (the mixin aspect). People get so caught up on the whole newness of the Application.cfc that they forget what CFInclude does: it includes the target template into the current page of execution.

Understanding that, we can actually get rid of the CFInclude totally and rewrite the above OnRequest() event method to look like this:

  • <cffunction
  • name="OnRequest"
  • access="public"
  • returntype="boolean"
  • output="true"
  • hint="Executes the requested ColdFusion template.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • hint="The requested ColdFusion template."
  • />
  •  
  • <!--- Include the requested ColdFusion template. --->
  • <!---
  • <cfinclude template="#ARGUMENTS.TargetPage#" />
  • --->
  •  
  • <!---
  • Instead of CFIncluding the target template,
  • let's just rewrite the event method to actually
  • contain the target template code. This
  • accomplishes the exact same thing. We are just
  • skipping the middle man.
  • --->
  • <html>
  • <head>
  • <title>OnRequest() Mixin</title>
  • </head>
  • <body>
  •  
  • <p>
  • This is the target page. Sweet!
  • </p>
  •  
  • </body>
  • </html>
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>

Once you see the OnRequest() application event written in this manner, it becomes much easier to understand the context in which the page is executing. The target page is really PART OF the Application.cfc, and more specifically, it is actually PART OF the OnRequest() event code. Therefore, it has access to all local variables of the OnRequest() event method as well as all public and private variables of the Application.cfc's THIS and VARIABLES scope.

Now that we are beginning to bridge this mental gap, it becomes more clear why Application.cfc-scoped methods are available to OnRequest() included pages and why something like this:

  • <html>
  • <head>
  • <title>OnRequest() Mixin</title>
  • </head>
  • <body>
  •  
  • <p>
  • This is the target page. Sweet!
  • </p>
  •  
  • <!---
  • Output the page passed to the OnRequest()
  • event method.
  • --->
  • <p>
  • <cfoutput>
  • TargetPage: #ARGUMENTS.TargetPage#
  • </cfoutput>
  • </p>
  •  
  • </body>
  • </html>

... will not bomb out, but will in fact output the template path passed to the OnRequest() event method.

Understanding the concept of the Mixin really helped me get my head fully wrapped around the concept of the OnRequest() event method. I hope that this has cleared a few things up for you.




Reader Comments

Aug 19, 2009 at 10:56 PM // reply »
21 Comments

typo detected...
"Executes the requested ColdFusoin template"


Aug 20, 2009 at 7:48 AM // reply »
10,640 Comments

@Mike,

Thanks, fixed.


Sep 21, 2009 at 10:43 AM // reply »
29 Comments

Also cool is the ability to use CFM pages as modules, instead of includes.

<cfinclude template="#arguments.targetPage#"/>

<cfmodule template="#arguments.targetPage#"/>

You can then do some fancy stuff, like pass attributes.

<!--- <cfset uri="/blog/805-ColdFusion-Application-cfc-OnRequest-Creates-A-Component-Mixin.htm"/> --->
<cfset article=reReplace(uri, "^/blog/(\d+)-.+.htm$", "\1", "all")/>
<cfmodule template="#arguments.targetPage#" article="#article#"/>


Sep 21, 2009 at 10:53 AM // reply »
10,640 Comments

@Alex,

True, but in that you are no longer creating a Mixin (which is really what this post was about). Since custom tags exist in their own memory space, you will need to explicitly use the CALLER scope to reach back up into the Application.cfc.

Custom tags are definitely cool; but, you really have to pick one or the other as they have extremely different behaviors - you can't just swap between the two.


Sep 25, 2009 at 2:53 PM // reply »
29 Comments

You can also is Ben's technique to do page-specific mixins.

Separate your business logic from display logic!

This is similar to code behind files in ASP.NET. (Although ASP.NET provides late bind and other stuff.)

Keep in mind this is simplified to demonstrate. This just does pre-processing. Theoretically, you could also perform post-processing, late bind, et al cool tricks.

application.cfc
<cfcomponent output="false">
<cffunction name="onRequest"><
cfset var temp={}/><
cfsilent>
<cfif (fileExists(expandPath(reReplace(arguments[1], "\.cfm$", ".cfc", "all"))))>
<cfset data=createObject("component", arrayToList(listToArray(reReplace(arguments[1], "\.cfm$", "", "all"), "/"), ".")).init()/>
</cfif>
<cfsavecontent variable="temp.body"><cfinclude template="#arguments[1]#"/></cfsavecontent>
<cfset temp.body=trim(temp.body)/>
</cfsilent
><cfoutput>#toString(temp.body)#</cfoutput><
/cffunction>
</cfcomponent>

samplepage.cfc
<cfcomponent output="false">
<cffunction name="init" output="false">
<cfset var temp={}/>
<cfset temp.data="foo"/>
<cfreturn temp.data/>
</cffunction>
</cfcomponent>

samplepage.cfm
<div>data: <cfdump var="#data#"/></div>

@Ben, I guess I need my own blog, so I stop mucking up yours. :) -AH


Sep 29, 2009 at 9:27 AM // reply »
10,640 Comments

@Alex,

That's definitely a very interesting idea.

No worries about posting here - it's all good conversation!


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
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 10, 2012 at 7:21 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
Update! Instead of $(eval(options.insertAfter)).after(data['insertData']); I now use: var ajaxNode = document.createElement('span'); var parent = $(eval(options.insertAfter))[0].parentNode; ... read »
Feb 10, 2012 at 6:18 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
encountered this same, what I consider, jQuery bug last week. I'm building a site in which I load some content via AJAX. This content contains Linkedin share button placeholders which Linkedin API ne ... read »
Feb 10, 2012 at 11:30 AM
Cross-Origin Resource Sharing (CORS) AJAX Requests Between jQuery And Node.js
After you understand the concepts here, this is an awesome cheatsheet for enabling CORS in just about anything http://enable-cors.org/ ... read »
JM
Feb 10, 2012 at 9:10 AM
My Safari Browser SQLite Database Hello World Example
@Amy, Here is a very good tutorial on how to use JOIN: http://www.sqltutorial.org/sqljoin-innerjoin.aspx ... read »
Feb 10, 2012 at 4:42 AM
Building A Twitter-Inspired RESTful API Architecture In ColdFusion
This is great, very useful Ben. I spotted a small typo in the api.cgm listing: <cfthrow type="Unauthroized" /> Cheers Stefan ... read »
Feb 9, 2012 at 10:35 PM
CFDirectory Filtering Uses Pipe Character For Multiple Filters (Thanks Steve Withington)
I was wondering if there would be a filter you could apply so that you got everything but what you included in the filter. As in show me all docs that are not a .pdf. ... read »
Feb 9, 2012 at 10:29 PM
Learning ColdFusion 9: Application-Specific Data Sources
@Ben, No offence, but if people were really wanting advanced features they would be using a platform like ASP.NET MVC. CFML is so structurally compromised as a tag-based scripting language that ... read »
Feb 9, 2012 at 10:03 PM
Subversion - Cleanup Failed To Process The Following Paths
@Leviaguirre, do you still have problems with this? ... read »