I have a sessionTimeout for my project like this
<cfset this.sessionTimeout = "#createTimeSpan(0,5,0,0)#">
for some reason pages on a deeper level inside of other folders are timing out before the 5 hours within like 20 minutes... Do I need to insert this in all application.cfc's to make it work correctly? I thought they all trickle down from the top level.
A template or component file will use the first Application file it finds moving backward through the folder structure until it reaches the root. So as long as there is not an application.cfc or application.cfm between your template and the root the timeout should work.
Unless you are extending the previous Application.cfc, or possibly using the same application name, your previous setting will no longer exist. You could also increase it in the CF Admin to make it global.
Related
Using: CF10 and IIS7.5
I have a section within my website called "Bookings". It is located like this:
c:\inetpub\wwwroot\mysite\bookings
Within this folder will be sub-folders and eventually webpages themselves. Heres an example:
c:\inetpub\wwwroot\mysite\bookings\holidays\new.cfm
c:\inetpub\wwwroot\mysite\bookings\carhire\edit.cfm
I include (using <cfinclude>) another page within each webpage that displays different links depending on which page is calling it. All I want to know is the directory up to the "bookings" folder. Something like this (pseudo code):
<cfset whereAmI = #GetDirectoryFromPath(GetBaseTemplatePath())#>
<cfif #whereAmI# EQ "C:\inetpub\wwwroot\mysite\bookings">
<h1>Booking Section Links</h1>
</cfif>
The above code works only if the user visits the bookings/index.cfm page of the "bookings" folder. But if they go to the bookings/holidays/new.cfm page, it is now in the holidays folder so the <h1> content will not appear. I really only want to check for any page that is in the bookings folder, even if it is within a subfolder within the bookings folder. A bit like in SQL where I could say IF #GetDirectoryFromPath(GetBaseTemplatePath())# LIKE 'c:\inetpub\wwwroot\mysite\bookings%' so it has a wildcard on the end.
I know this question is going to irritate the MVC framework advocates but please excuse me on this!
Here is a quick, easy way to solve your problem (may not work as system expands - but should get you started down the right path).
<cfset whereAmI = GetDirectoryFromPath(GetBaseTemplatePath())>
<cfif whereAmI CONTAINS "C:\inetpub\wwwroot\mysite\bookings">
<h1>Booking Section Links</h1>
</cfif>
Note, I removed the # from inside the cfset and cfif you do not need them there.
You could even scale back the path to use just 'mysite\bookings'.
Ideally, this should be wrapped up into a function so that you can easily pass different paths into it to determine if you are on a given page. Or, possibly, even determine the 'parent' folder in onRequestStart in Application.cfc and set it as a request scope variable.
This will need to be tweaked if you run the code on a *nix based system.
It is more easier with CGI variables. You can use "CF_TEMPLATE_PATH". Try this
<cfoutput>The value of CF_TEMPLATE_PATH is: </cfoutput><cfdump var="#CF_TEMPLATE_PATH#">
I was charged with making some modification to an old application, and I created a new page which was being passed a URL parameter page_name, which is a you guessed it a name of a page with .cfm appended. So, in my haste, I continued using it, and was building out my CFC and using the page_name as the identifier for a record. Then I realized that there is a possibility of that name being duplicated in the table, and changed that url parameter to use the page_id, which is unique. I modified my CFC to use the new key, and nothing worked. So I started going through my code and figured I made a typo, started commenting things out, and finally dumped out my CFC object and voila, none of the edits I made were actually being used. This was fairly obvious, since page_name was a string, and page_id was numeric.
So I started googling,The first thing I saw as adjust things in the CFAdmin. I don't have access to it, and restarting the server isn't an option since I'm using an RDS to live code. The next thing I tried was to add applicationStop(), onApplicationStart(), to my Application.cfc. Well the problem is that the Application.cfc, is actually an Application.cfm. So after fiddling with the <cfapplication ... > tag, and nothing being updated, I'm here asking for help.
So is there a quick fix for this? Should I go ahead and create an application.cfc? I hope I explained myself, and sorry for all the text.
Confirm that your cfc is bound to either the session or application scope.
If it is, then you can rename the application in application.cfm and it will reset the object.
If your cfc is NOT bound to session or application scope, you have a cacheing issue. You need to go the the CF admin -> Server Settings -> Cache tab and uncheck component cache and possibly some others.
For further recommendations, ColdFusion Components Inheriting Functions Of Others
Sounds like you have been painted into a corner. Last option IF you have access the the server it self and can get into the C:\ or whatever drive that ColdFusion have been installed on, you can just manually delete the generated Java Class files that the server is using that has the old code. When ColdFusion sees there is no Class file it will recompile the newly changed file and whoa black betty go bam-a-lam your changes will be in production.
For more information here is an posting you can read up on: http://kalyan-coldfusion.blogspot.com/2010/08/how-coldfusion-works-and-its-key.html
Cheers
In my application I have all my CFC's in a cfc folder. From the site root I can access them without any trouble by simply referring to them in my <cfinvoke> tag as component=cfc.mycomponent method=mymethod
The trouble is, when I want to access the cfc from another page that's not in the root I can't use component=../.cfc.mycomponent to get in touch with that cfc.
What am I doing wrong here?
There are a handful of options for getting this to work. Unfortunately, learning them has taken me a good amount of trial and error. Let me share what I've learned.
First, you can use the classic method of creating a mapping in your CF Administrator. Specify the exact path to your components (e.g. c:\wwwroot\cfc), and the mapping (pseudo-folder) that you want to call it by (e.g. MyCFCs). Now from anywhere in your application, you can reference create a new MyCFCs.mycomponent() (using CF9+'s new keyword, you can substitute for createObject("component","MyCFCs.mycomponent") to be compatible back to CF6).
The downsides to using a server mapping are that you have to configure this on every server your application runs on. I typically have a local development server which has a radically different configuration from my production servers, and making changes on production servers is a pain for me, so I try to avoid server mappings whenever possible.
Second, you can reference your CFCs from a web-root-relative path, meaning that if your application is in the root of your server and the /cfc path is directly off of the web root, you can always do new cfc.mycomponent() from anywhere in your application. ColdFusion 6.1 and up will correctly map to the root of your web site. This is like referencing an image using /images/mypicture.jpg, anywhere in your web site, /images will will go straight to the same directory.
The downside of using the web-root-relative path is that if your application will ever be in a different folder off of the web root, or will ever be in a subdirectory and sometimes be at the web root, the relative path from the web root will change, breaking these links.
Third, you can create an application-specific mapping. This was introduced in CF8 and requires that you have an Application.cfc file. It is simple to add. Raymond Camden has a great reference. The syntax is essentially like this.
<cfset this.name = "MyAppName"/>
<cfset this.mappings = structNew() />
<cfset this.mappings["/cfc"] = getDirectoryFromPath(getCurrentTemplatePath()) & "cfc/" />
The only downside to this method is that your Application.cfc can't extend a CFC in a mapped folder. It's an obscure problem, which probably won't affect you. Also, you will need to have an Application.cfc, which is good practice, but I don't know if you are doing that yet.
Fourth, you can instantiate your CFC into your application scope, probably from within the aforementioned Application.cfc, inside an OnApplicationStart() method. This moves any compile/instantiation time into your application's first hit, and removes it from subsequent hits. The code is very simple.
<!--- from Application.cfc, inside onApplicationStart() --->
<cfset application.myComponent = new cfc.myComponent() />
<!--- from anywhere else in your application --->
<cfset application.myComponent.callMyMethod() />
The downside to this one is that once your component is in Application memory, any changes you make to it while you are developing your application will not be reflected until you clear the application memory or call onApplicationStart() again. It's not hard to get around, but it's just more code, and more to manage.
One final note, you may want to think about moving from <cfinvoke> to createObject("component",...) or, if you are on CF9, new. The cfinvoke syntax is fine, but every time you invoke a component from a path, you are re-instantiating it, and it also is not a very object-oriented way to call your components. Food for thought, take it or leave it :)
You can't use relative paths with components.
What you need is a ColdFusion mapping. There are two ways to do this.
The first is to go into your ColdFusion administrator, go into the mappings section and add a /cfc mapping that points to your cfc folder.
The other way is to use application specific mappings;
In the Application.cfc for your application you can add application mappings as you would under the ColdFusion administrator mapping. At the top of your application cfc add a cfset of this.mappings as an array. In this array set the mapping with the directory path.
<cfset this.mappings["/cfc"] = GetDirectoryFromPath( GetCurrentTemplatePath() )&"cfc">
with the mapping of /cfc to your cfc folder any component calls to cfc.objectname will load the appropriate component in your cfc folder.
You absolutely can extend a cfc with mappings. I had to do it myself.
One of the most frustrating things that I have had to deal with in ColdFusion is trying to create an external application that is open to the general public and having to secure a portion of that site with an application within a subfolder and extending the logic from base application.cfc. I'll walk you through the current approach that developers use to solve this as well as showing you how to additionally use mapping when there may be a hosting provider that uses virtual directories.
This is a rather long article, if you want to jump to the condensed summary, scroll down to the bottom of this page.
Many years ago, the first time that I tried to perform this, I received the following message no matter what I tried: "Could not find the ColdFusion component or interface xxx'. In a nutshell, the problem using this approach is that both the root and the subfolders have the same name, i.e. Application.cfc, and ColdFusion can't properly identify what component to extend. Finally, after some serious investigation, someone came up with the idea to create a proxy.cfc that resides in the same root directory as the root Application.cfc, and the Application.cfc in the subfolder extends an empty proxy.cfc that extends the root cfc like so:
root directory: Application.cfc
This root Application.cfc does not extend anything
Also in the root directory: Proxy.cfc
Proxy.cfc has the following code, it's essentially empty. The only thing that the Proxy.cfc does is to extend the Application.cfc that is in the same directory:
<cfcomponent extends="Application">
</cfcomponent>
Subdirectory such as a folder named admin.
This subdirectory has another Application.cfc. Let's say that this component is responsible for securing the application and has login logic as well as debugging settings for example. This Application.cfc will extend the Proxy.cfc to gain the methods and properties of the Application.cfc in the root directory like so:
<cfcomponent displayname="Admin" extends="Proxy.cfc">
This approach was a godsend and it was heavily blogged about. Ben Nadel has made a number of very helpful posts which I will share at the bottom of this article.
This works quite well unless you're on a hosted domain or a server that uses virtual directories. In this case, we are in the same original boat in which we started from. Now we are back into the "Could not find the ColdFusion component or interface xxx' hell!
There is a solution for this tricky problem though, we need to also use mapping!
It is a common misnomer that you can't use mapping to extend components. I am not quite sure where this misconception originally came about, but it has been proven that this is just not true. There are occasions where we must use mapping to solve some annoying problems, like here.
This particular site is hosted by hostek.com. They are a fine company to deal with, but the server that my site is hosted on has some idiosyncrasies due to the directory structure. Here, when I use the Proxy.cfc method to extend the logic from the base Application.cfc to the Application.cfc in the admin folder I receive the dreaded 'could not find the ... component' error. When I first saw it I was dismayed thinking not this again, so I turned to ColdFusion CFC mapping. Mapping tells ColdFusion where to find the file and what the file relationships are.
Let's review CFC structure that was just discussed. For example, imagine the following directory structure:
root directory: i.e. www.gregoryalexander.com/
subdirectory: www.gregoryalexander.com/admin/
As discussed, we have an Application.cfc and the Proxy.cfc in the root directory, and we have the Application.cfc in the 'admin' subdirectory.
The Proxy.cfc extends the Application.cfc, also in the root directory, and the Application.cfc in the subdirectory (admin) extends the Proxy.cfc in the root directory.
root directory: contains both Application.cfc and Proxy.cfc (that extends the root Application.cfc).
subdirectory: Application.cfc (that extends Proxy.cfc).
Now we need to also add the following mapping in the root Application.cfc. This mapping logic should be near the top of the root Application.cfc, and it should not be within any of the Application.cfc event handlers (onApplicationStart, onApplicationRequest, etc). This mapping code does not need to be anywhere else other than the root Application.cfc:
<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />
I used rootCfc to identify the Application.cfc in the root directory, whereas adminCfc applies to the Application in the admin directory. These variables can be named anything. Note that the "/admin" string at the end of the adminCfc mapping points to the 'admin' folder, which is a subdirectory.
Now that we have the mappings in the root Application.cfc, we need to apply them to the extends statement in Application.cfc located in the subdirectory. In the /admin/Application.cfc template use:
/admin/Application.cfc
<cfcomponent displayname="xxx" sessionmanagement="xx" clientmanagement="xx" extends="rootCfc.Proxy">
Of course, rootCfc tells the Application.cfc in the subdirectory to look for the Proxy.cfc template in the root directory. Like other 'extend' statements, you don't need to specify '.cfc' at the end of Proxy.
You don't need to use this 'extend' mapping in either the root Proxy.cfc or Application.cfc templates. They can already find each other as they are both in the same root directory.
/Proxy.cfc
<cfcomponent extends="Application">
</cfcomponent>
Summary
For the sake of absolute clarity:
root Application.cfc
Contains the mapping logic. Has the mappings for both of the root and subdirectory.
Does not use an 'extend' statement
<cfset this.mappings = structNew() />
<cfset this.mappings["rootCfc"] = getDirectoryFromPath(getCurrentTemplatePath()) />
<cfset this.mappings["adminCfc"] = getDirectoryFromPath( getCurrentTemplatePath() & "/admin" ) />
root Proxy.cfm
A simple 'extends="Administrator" works.
No mapping logic.
<cfcomponent extends="Application">
</cfcomponent>
subdirectory Application.cfc
The extends statement must be the mapping variable name of the folder (rootCfc), a dot (.), and finally the name of the Proxy.cfc template without the .cfc prefix (Proxy)
<cfcomponent displayname="Admin" sessionmanagement="yes" clientmanagement="yes" extends="rootCfc.Proxy">
My apologies for being so verbose. I annoyed myself while writing this- but not as annoyed when I was while trying to solve this problem!
Take care!
Make sure if your components extend other components the full path is used.
ie a Products controller
<cfcomponent displayname="Products" hint="Handles all product requests" extends="core.controller.controller" output="false">
Note: If you wish to use an absolute template path (for example,
template="/mypath/index.cfm") with CFINCLUDE, you must create a
mapping for the path using the ColdFusion Administrator.
I went to the administration page but not sure what to put in here.
I'm pretty new to coldfusion. anyone got any ideas why this would be happening.
CFINCLUDE uses relative paths in relation to the file where the cfinclude is, so if want to include a file in another directory, 1. it has to be inside your wwwroot (or the root directory, or subdirectories) of your site, 2. you can go to other directories by doing ... hope this helps a little bit. If you want to include a file that is outside of your wwwroot, then you'll need to map that directory in Coldfusion Administrator using the same syntax above when you do include it.
To add a mapping, open your coldfusion administrator.
Server Settings > Mappings
There are 2 paths. Logical and Directory.
Logical can be anything you want, and directory is where it maps to.
eg. you might have a folder below your web root which stores email templates mapped as:
logical path: /emails
directory path: /var/www/mycfapp/content/includes/emails
You can <cfinclude template="/emails/forgotPass"> from any cf template and the mapping would get picked up.
You can use the mappings for new object creation too. Lets pretend forgotPass is a cfc.
fp = new emails.forgotPass();
// if you have funky characters in there, eg dash, just quote it.
fp = new "emails.forgot-pass"();
Mappings also work when extending cfcs. With one small exception. No leading slash.
component extends="emails/forgotPass" {
// ...
}
Im pretty sure mappings are detected first, so if you have a folder with the same name it might not get picked up.
In cf9 you can also specify your mappings in your Application.cfc, instead of coldfusion administrator, which affects all applications on your server. eg.
this.mappings["/emails"] = "/var/www/mycfapp/content/includes/emails";
You'll need to tick the Enable Per App Settings option on the cfadmin Settings page.
http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSc3ff6d0ea77859461172e0811cbec0b63c-7fd5.html
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>