ColdFusion users have long wanted a way to define settings per application, rather than server-wide. In truth, this is doable right now, just install multiple instances of ColdFusion an each instance gets its own CF Admin and own settings. But, if that is not an option, then Scorpio will help, as I explained last night in Seattle.
ColdFusion MX7 introduced Application.cfc as an alternative to Application.cfm. Application.cfc does everything that Application.cfm does, and added important new features (like methods that get executed OnSessionStart and OnSessionEnd). To set application settings using Application.cfc, variables are set in the THIS scope. THIS.name to set the application name, THIS.sessionManagement to enable session state management, and so on.
In Scorpio, Application.cfc and the THIS scope can be used to define per application settings. For example, THIS.mappings is a structure which contains the currently defined ColdFusion mappings. To set a mapping you just modify that structure like this:
<cfset THIS.mappings["MyStuff"]="c:\inetpub\MyStuff">
Or like this:
<cfset StructInsert(THIS.mappings, "MyStuff", "c:\inetpub\myStuff")>
To set the Custom Tag path you can update THIS.customtagpaths which is a simple ColdFusion list. You can set the path like this:
<cfset THIS.customtagpaths="c:\inetpub\wwwroot\ben\tags">
Or use ListAppend() to add a path, like this:
<cfset THIS.customtagpaths=ListAppend(customtagpaths, "c:\inetpub\wwwroot\ben\tags")>
You get the idea. It's clean, simple, and highly intuitive.
Which means you now have yet another reason to use Application.cfc.
So this directory uses the base application settings (say, DSNs), which in turn could have inherited settings from its parent, and so on, while also adding a few of it's own.
Any way to do this with application.cfc's? Can one application.cfc "extend" another?
--- Ben
http://www.corfield.org/blog/index.cfm/do/blog.ent...
Create Applicationproxy.cfc in the root beside your Application.cfc. Set extends="Application" in that proxy component, nothing else needed. Then in a sub directory Application.cfc, set extends="Applicationproxy". Without the proxy, it can't find the extended component or something like that.
I've also found it useful in some cases to use 'super' in reference to the parent methods if needed. Don't forget that it's available.
(Hey Ben, is that a CAPTCHA cfimage? If not, will you be using it when you turn Scorpio?)
Remember that if you're running a multi-homed server or your app is not located in the CFMX wwwroot directory you'll still need a mapping to the ApplicationProxy.cfc location. This is because Application.cfc doesn't "walk up" the directory structure like the old Applciation.cfm does to find the first existence of the file.
dickbob
CFMX *will* "walk-up" the directory structure to find an Application.cfc if there is no Application.cfc in the directory of the page being requested just like Application.cfm does.
What I *meant* to say is that the extends attribute in cfcomponent won't find your ApplicationProxy.cfc unless you give it a explict path to the ApplicationProxy.cfc with a mapping in a mult-homed or non-CFMX wwwroot situation.
Example...
<cfcomponent extends="someMapping.ApplicationProxy"></cfcomponent>
dickbob
How about datasources?
They don't have anything like this for 404 errors by any chance? That would be sweeeet!
My ONE concern... will the ColdFusion server search the application mappings and customTagPaths as first priority?
Calvin, Ben, Tom, I don't have the final list yet, Scorpio is a work in progress. Just out of interest, which are the most important ones for you?
--- Ben
--- Ben
Do you mean that these settings aren't only being fired when you run OnApplicationStart?
I'd like to be able to deploy a ColdFusion application as a developer, with all necessary dependencies, WITHOUT requiring admin access or admin settings.
--- Ben
Ben, I'm not buying your comments. (1) You say these settings would be executed in Application.cfc on every request. Why? That makes no sense when there is structure in place to execute code or set values on application start. (2) Why are Per-Application Settings good for mappings and custom tag paths, buth not datasources? What's good for the goose is good for the gander...? What is it ok to get excited about setting those settings in Application.cfc, but datasources should use the Admin API?
And FWIW, having to get admin access just to deploy an app sends me into an OCD fit. It's just not right! :-)
Not trying to argue, just sharing my feelings, and I feel strongly about this..
Joshua, sorry, maybe I was not clear. I agree that we need a way to be able to create data sources for those who do not have Admin access. I just don't like having all those options in a per Application file, I just don't think it belongs there. Data sources are not tied to applications necessarily, and they should exist even between applications and across applications. If one is created in Application.cfc should it show up in RDS? Should it be controllable by sandbox security? And there are lots more gotchas with this. So, yes, there needs to be a way to do this, but I'd like to find the right solution, not shoehorn it in. CAR file deployment is a very good option. In shared hosting environments the hosters should allow you to do this with a app they create, that is what the Admin API is for, not foor developers as much as for admins to create custom controllable Admin UIs. And not having Admin access is indeed a problem, but we have addressed this in Scorpio with multiple and configurable CF Admin logins.
--- Ben
--- Ben
When it comes to sandbox security, putting DSN abilites in Application.cfc is fine. You just add a setting to sandbox to allow or disallow that feature. At first your point made sense to me also, but after thinking it through it has lost it's strength. I would like to see a method added to the Application.cfc (a constructor) method that got called when the app is created. (And that way it could be called again to update things.) For a season we could create "dynamic" data query connections. It worked great for those who used it. :)
As far as security goes, you should not have a SQL source that is without security. So that eliminates Access. LOL / Seriously, controlling more would be good. I like the direction we are going but expect that it's to late in the cycle for this version. We need to shoot for version 9 for additional features! :)
"Dynamic datasources", so to speak, defined in the application itself, still make sense to me. Yes, they cannot be controlled or shared by entities external to the application. But if I'm not using the DSN outside of the app, that doesn't hurt me, and if I DO need to use the DSN outside of the app, putting it in via the CF Admin is to an option.
This would also give me the flexibility to have different datasource security for different apps, or even for different deployments of the same app, since I would be able to programmatically define the datasource.
Yes, I can still do this with CAR files. And I'm going to start using this. But I still see some advantages to defining the datasource from within the application based on runtime logic. Thanks for the consideration.
I cannot seem to get this right. In my App CFC, I have:
<cfset THIS.Mappings[ "images" ] = "C:\Websites\images\" />
but then when I do:
<cfdirectory action="LIST" directory="images\" name="qFile" />
qFile has zero records. However, I can assure there are images in that folder. Am I missing something? Does this feature need to be turned on somewhere else? Thanks.
<cfdirectory action="list" directory="C:\Websites\images\" name="qFile" />
It works fine, so the path itself is correct (and returns a number of records).
Does the following work?
<cfset THIS.Mappings[ "/images" ] = "C:\Websites\images\" />
("/images" instead of "images")
what is the different between
extends="mymapping.applicationproxy" or
extends="mymapping.application"
they both achieve the same thing in the end, except with your proxy you have an extra un-needed step.
I extend application.cfc from sub folders all the time with no problems.
What I understand is this new mapping feature is only available in Application.cfc file.
This code works:
<cfcomponent>
<cfset this.name = "MappingsTestCFC">
<cfset this.mappings["/myincludes"] = "D:\Domains\mydomain\includes">
</cfcomponent>
But when I try to create some variable with following code in Application.cfm file it looks like it does not work.
<cfset application.mappings["/myincludes"] = "D:\Domains\mydomain\includes">
Are there way other way to use this new feature except Application.cfc?
"this.anyname" and "application.anyname" are not same.
But are there any way of creating parameters that we set in application.cfc this scope without having application.cfc?
CFCProxy, setThisScpe method? Or any alternative way?
LiveDoc info:
http://livedocs.adobe.com/coldfusion/8/htmldocs/he...
Some CFCProxy info w/ links:
http://www.bennadel.com/blog/331-How-Do-I-Call-Met...
<cfset THIS.mappings["/MyStuff"]="c:\inetpub\MyStuff">
NOT
<cfset THIS.mappings["MyStuff"]="c:\inetpub\MyStuff">
The Livedocs examples also don't include slashes. Am I right that the slashes are required?
http://coldfusion8.blogspot.com/2008/03/per-app-se...
<cfcomponent>
<cfset this.name = "MyApp">
<cfset this.mappings = structNew()>
<cfset structinsert(this.mappings,"/applicationpath","C:/MyAppFolder/")>
<cffunction name="onApplicationStart">
<cfset application.myobject = createobject("component","applicationpath.myobject").init()>
</cffunction>
</cfcomponent>
This simply will not work, Coldfusion will report that it cannot find the object specified. It doesn't work if you use OnRequestStart() either - the only way to do this is to do it OUTSIDE of the application.cfc, which isn't desirable or even possible depending on your application. Would be interested in other people's comments on this issue as I've not encountered any other mention of it online so far.
I set up some per application mappings in a Application.cfc to test it out. I've managed to succesfully use them within my CFCs (init objects etc.) So far so good.
I'm also used to set up "general" mappings using the CFADMIN and to reference these in the services-config.xml file, mapping my FLEX remoteobject calls to my CFSs.
However, the dynamically set per application mappings doesnt seem to work if used in the services-config.xml file.
Can anyone confirm that this is the case or if its possible please provide some hints of how its done.
Thanks!