How to call OnRequestStart from Application.cfm - coldfusion

I am a new to ColdFusion. I have Application.cfm and would like to add an onRequestStart function, but it is not working. By not working I mean, when a page calls some application variables (that were set inside `onRequestStart) an error is generated because those variable don't exist.
I can't use Application.cfc. Is there a solution or another way to use onRequestStart with Applciation.cfm?

So I'm not really sure what your trying to do with the Application.cfm, but like Ageax said, the Application.cfm runs on every request ( whatever workflow you had in mind for the onRequestStart() function you can just do in the Application.cfm)
If you really want an onRequestStart function in Application.cfm you can make your own function and explicitly call it after like this
Application.cfm
<cfset Application.test = " AND IS USING AN Application Var :D!! ">
<cfscript>
function onRequestStart(){
RETURN "THIS HAPPENS AT THE START OF EVERY REQUEST! #Application.test#";
}
</cfscript>
<cfoutput> #onRequestStart()# </cfoutput>
This question and article might be an intresting read for you if your not forced to use an Application.cfm
ColdFusion: Are there any use cases where an Application.cfm is preferable to an Application.cfc
Migrating from Application.cfm to Application.cfc

If you need to using Application.cfm (not sure why this would be a requirement as Application.cfc has been around a very long time), it handles the basic onRequestStart functionality and is loaded before every *.cfm file.
You can add onRequestEnd functionality by creating a OnRequestEnd.cfm file.
Better reference: Coldfusion using onRequestEnd() with Application.cfm files

Please add requestStart.cfm file to you project, put your code in this file. It will run on every request (start).

Related

Difference between cfc and cfm

I'm trying to create basically a library of UDFs (User Defined Functions) for a web site run in ColdFusion. While doing this I am trying to find out what the differences are between cfc and cfm files. Which would be more helpful in creating this library of functions? I know that I can use
<cfinclude template="mytemplate.cfm>
to include it in a page but that will run the entire contents of that cfm on that page every time. I don't know and easier way to use cfc other than to create an object of the cfc and call the function that way.
<cfobject type="component" action="create" name="test">
Any ideas?
The way that I do it is to create all my UDF in a cfc. I then initialize that cfc on application start:
public function onApplicationStart() {
// Application settings
application.util = createObject("component","cfc.util");
return;
}
use a cfc you can call more easily from more places, if its not too huge put it into your application scope

cfc that bring in additional functions via include

My application.cfc starts with:
<cfcomponent extends="org.corfield.framework">
later on void function setupApplication() output="false" {
I have
// tools
include "initapp.cfm";
initapp.cfm has nothing but functions in it. Things like:
<!--- Helper functions --->
<cfscript>
string function stripHTML(str) output="false" {
return REReplaceNoCase(arguments.str,"<[^>]*>","","ALL");
}
application.stripHTML = stripHTML;
</cfscript>
The nature of the functions is NOT associated with a session. Is there a better way to make functions available globally?
If you're trying to put helper functions together for use in CFCs, one option may be to use the component.cfc file.
Using the component.cfc file
All CFCs automatically extend the ColdFusion
WEB-INF/cftags/component.cfc component. (The WEB-INF directory is in
the cf_root/wwwroot directory on ColdFusion configured with an
embedded J2EE server. It is in the cf_root directory when you deploy
ColdFusion on a J2EE server.) This CFC is distributed as a zero-length
file. You can use it for any core methods or properties that you want
all CFCs in your ColdFusion application server instance to inherit.
Note: When you install a newer version of ColdFusion, the installation
procedure replaces the existing component.cfc file with a new version.
Therefore, before upgrading, you should save any code that you have
added to the component.cfc file, and then copy the code into the new
component.cfc file.
If that solution is TOO global you can extend your helper cfc, but it has to be done in every cfc and doesn't answer your one-time-set-it-and-forget-it idea. See Using CFCs effectively
If your helper functions are for use in .cfm files, I'd do like Adam suggested. I usually put my helper functions in a "tools" cfc located in a CFC folder and make it an application scoped cfc.
function onApplicationStart(){
application.tools = createObject("component", "cfc.tools");
}
One of my helper functions logs the time it takes to index a solr collection. Using it looks like
<cfset application.tools.logSolrIndex('collectionName',getTickCount()-start,qFileList.recordCount)>
Last resort:
If you had to stick with an include for use outside of the application.cfc, I might simply include initapp.cfm onRequest() before you include your page.
Put the functions in a library CFC, and then put an instance of that CFC in the application scope in onApplicationStart().
That said, you'd be kinda breaking encapsulation if you then referenced this application-scoped CFC within other CFCs, which is a consideration (not necessarily a deal breaker, but a consideration).
You could look at some sort of dependency injection approach to mitigate this (eg: ColdSpring)
Whichever way I ended up doing it, I would not be doing it the way you're doing it, I'm afraid.

application.cfc in subdir not getting session variables from application.cfm in the parent directory

I have an application.cfc in folder /wwwRoot/beta/. They have an application.cfm in the root which sets bunch of session variables. When I hit one of the pages in the beta folder to dump all the session vars, I don't see the ones that were defined in the application.cfm.
I modified my application.cfc to get rid of all the code within 'onSessionStart'. That didn't help. I created a new application.cfm with a few application varibales I needed. That didn't help either.
Does anybody have any suggestions?
<cffunction name="onSessionStart" returnType="void" output="false" hint="Fires ONLY ONCE when session first created and not when session renewed/restarted.">
<cfscript>
session.startTime = Now();
</cfscript>
<cfreturn>
</cffunction>
I guess I will need to some how copy existing session vars.
I created a simple test page on the above folder.
<cfset session.mynum= 1111>
clicky
When I click on the link, the session dump does not include myNum. Something in application.cfc is screwing things around.
Application.cfc will not be affected by an Application.cfm in the parent folder. You should replace the Application.cfm with an Application.cfc and then in your child folder you should extend the parent Application.cfc. This is the way the Application framework in ColdFusion functions.
That said, if you cannot replace the Application.cfm with an Application.cfc then you could break out the session variable definition into a separate file and then cfinclude it into the Application.cfm and repeat that inclusion in the Application.cfc in the child folder. However, you may have other things in your Application.cfm that will also not be included in the Application.cfc in the child folder so this isn't really a great solution. The best solution is to get rid of the Application.cfm altogether, replace it with a proper Application.cfc in the root and then extend that from any child folders as necessary.
Found the problem! In the application.cfc I have the following at the top:
<cfscript>
this.name = "myApp";
</cfscipt>
the name of the application must be as same as the one that is being used in the tag in application.cfm. Once the name was changed, I was able to get the session vars.
thanks

Store and use ColdFusion templates outside of the web root

I have been tasked with researching the possibility of storing .cfm files outside of the web root as a further security measure. (I'm not talking about CFCs, but the files that will appear in the URL string.)
I figured that I could use the properties of OnRequest() in the Application.cfc to do this, but no luck.
I've tried this:
<cffunction name="OnRequest" access="public" returntype="void" output="true">
<cfargument name="TargetPage" type="string" required="true"/>
<cfinclude template="C:/test#arguments.TargetPage#"/>
<cfreturn/>
</cffunction>
I then put a test.cfm inside C:\test and attempted http://localhost/test.cfm. That gives me a "file not found" error.
So then I created a ColdFusion mapping to C:\test called "test" and changed my CFINCLUDE thusly:
<cfinclude template="/test#arguments.TargetPage#"/>
Unfortunately I got the same error.
So, is what I'm after even possible? (Windows Server 2008 and IIS in case it matters. ColdFusion 9.)
I know that I could put a CFINCLUDE in my index.cfm and pass around URLs like http://www.example.com/?file=test.cfm, but I'd prefer not to do that.
Well here's something: If I put an empty test.cfm in my web root then this works. Obviously I'd really rather not put empty stubs for every one of my files (which, for this project, will end up being in the hundreds).
Rather than spinning your wheels down this path, let me point you in a possible better direction which may solve the original issue, but from a more preferred/best practices standpoint:
ColdFusion Sourceless Deployment
Rather than trying to jimmy-rig the site to read files outside of root, you simply never put the source code out into the world.
I think you would have better luck using onMissingTemplate rather than onRequest. http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7d2a.html

Fusebox installation without access to webroot

Previously (and locally) I've placed the fusebox5 directory in the web root, and then applications from anywhere in the tree have been able to access it. I'd previously also used Application.cfm rather than .cfc.
In this environment I don't have access to the webroot and the FB files don't really need to be that far down anyway, so I had planned to store them alongside the applications. Am I right in thinking that index.cfm is overlooked if Application.cfc is in use (and therefore there's no point changing the cfinclude value to be eg. ../fusebox5/)? If so, how can I include the framework without having Fusebox in the root or in a mapping? Error is:
Could not find the ColdFusion Component or Interface fusebox5.Application.
No, your app is still going to need index.cfm. What you'll need is a cf application mapping for Fusebox in your Application.cfc. Look at Ray Camden's Application.cfc template for an example of setting application specific mappings.
You can run Fusebox 5+ in a subfolder of your app root. It just may not be the most obvious thing to make it work.
Unfortunately, you cannot create a dynamic mapping for extending Application.cfc because your Application.cfc has not yet been instantiated - you get a chicken vs. egg scenario. You can't create the mapping to Fusebox because your Application.cfc didn't start, you can't start your Application.cfc because it can't find the component it's supposed to extend.
THIS IS A BUG IN COLDFUSION 8. ColdFusion should look for mappings in this order:
Mapped folders from the CF Administrator
Sub directories off the current directory
Sub directories off the web root called
It does this when you use CreateObject(), but not when you use the Extends attribute on cfcomponent.
The easiest solution is to use your Application.cfc like you would for any application, then include fusebox from your index.cfm. Your folder structure would look like this:
/myapp/fusebox5/
/myapp/index.cfm
-- consists of <cfinclude template="fusebox5/fusebox5.cfm" />
Your index.cfm file will not be ignored as long as you don't intercept the request with Application.cfc's OnRequest, or if you use OnRequest, make sure you include the intended target (which will almost always be index.cfm anyway).
If you want to not require index.cfm to do the include, you can have your Application.cfc's OnRequest method do the cfinclude.
<cffunction name="onRequest">
<cfinclude template="fusebox5/fusebox5.cfm">
</cffunction>
You still may need an index.cfm so your web server won't give a directory listing or 404, but it's ok if the file is empty.
In Application.cfc:
<cfscript>
this.mappings = {}; //create a new structure to store app-specific mappings
this.mappings["Fusebox"] = expandPath('./Fusebox'); //add mapping
</cfscript>