AdobeStock_455007340

Scorpio Per Application Settings

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:

Or like this:

To set the Custom Tag path you can update THIS.customtagpaths which is a simple ColdFusion list. You can set the path like this:

Or use ListAppend() to add a path, like this:

You get the idea. It’s clean, simple, and highly intuitive.
Which means you now have yet another reason to use Application.cfc.

48 responses to “Scorpio Per Application Settings”

  1. Michael Long Avatar
    Michael Long

    In an application.cfm file it’s a relatively common practice to "extend" a base application.cfm’s settings by doing a cfinclude template="../application.cfm" at the top.
    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?

  2. Ben Forta Avatar
    Ben Forta

    Yep, just use EXTENDS and you can extend another Application.cfc. And so you can inherit settings from a parent and add/update as needed.
    — Ben

  3. TonyG Avatar
    TonyG

    It just so happens I just read about extending Application.cfc in a 2005 blog post by Sean Corfield.
    http://www.corfield.org/blog/index.cfm/do/blog.entry/entry/Extending_Applicationcfc

  4. Rick Smith Avatar
    Rick Smith

    Sweet Ben… now I know why my question went unanswered in the Scorpio beta forums… it CAN be done. 🙂

  5. Clint Avatar
    Clint

    Actually, because of the way Coldfusion searches for Application, extending an Application.cfc at the root is a little more complicated than that. Use a proxy instead.
    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?)

  6. dickbob Avatar
    dickbob

    @Clint,
    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

  7. dickbob Avatar
    dickbob

    Sorry, I think I must correct a wrong impression I’ve given.
    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

  8. Calvin Avatar
    Calvin

    Good stuff!
    How about datasources?

  9. Ben Nadel Avatar
    Ben Nadel

    Very cool stuff! I might start using mappings because of this.
    They don’t have anything like this for 404 errors by any chance? That would be sweeeet!

  10. John Farrar Avatar
    John Farrar

    I have had applications on shared hosting before where the CFBased custom tag paths were shared by more than one user. We had an incident where someone had a custom tag with the same version as ours but thiers was seen by ColdFusion before ours. This caused our site to crash.
    My ONE concern… will the ColdFusion server search the application mappings and customTagPaths as first priority?

  11. Tom Mollerus Avatar
    Tom Mollerus

    This is great news! Like Ben Nadel, I’m wondering exactly which settings are now configurable in Application.cfc. Ben (Forta), would you be able to give us a complete list?

  12. Adam Ness Avatar
    Adam Ness

    I’m so glad to see this, as this has actually been one of my major gripes about ColdFusion within the last year. I even <a href="http://www.greylurk.com/index.php?itemid=11">Blogged</a&gt; about it a few weeks ago.

  13. Ben Forta Avatar
    Ben Forta

    John, of course.
    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

  14. Clint Avatar
    Clint

    Mail settings, charting, data sources, verity, webservices, log directory and files, gateway types/instances

  15. Joshua Curtiss Avatar
    Joshua Curtiss

    Custom tags, Java class paths, datasources, mail settings, verity, and scheduled tasks would all be awesome if they could get encapsulated into Application.cfc. Shoot. This feature alone would make Scorpio worth it in my shop, and I know there are many other Scorpio features coming that are even better..!

  16. Ben Nadel Avatar
    Ben Nadel

    Java class paths, scheduled tasks, and 404 handler would be my top. And, if I had to pick one of the three, I would go with 404 handler as I think that has more potentially for *cool* stuff (and is something that I use more often).

  17. Ben Forta Avatar
    Ben Forta

    Some of those I buy, but not all. Log location, 404 handler, mail server settings, those all make sense to me. But datasources? Realize that this is Application.cfc, this gets processed on every request, do you really want datasources created on the fly over and over? I don’t believe that that works at all. Same for gateways and instances. It sounds to me like two features are being confused here, the need for per app settings, and how to handle no CF Admin access. This is the former, the latter is a very different discussion.
    — Ben

  18. Calvin Avatar
    Calvin

    Ben,
    Do you mean that these settings aren’t only being fired when you run OnApplicationStart?

  19. Calvin Avatar
    Calvin

    Just for clarification, I don’t think they are being confused in the same sense you are Ben.
    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.

  20. Ben Forta Avatar
    Ben Forta

    Calvin, and you can do that, it’s called a CAR file. And for hosting situations your admin can let you do that with a custom admin console using the Admin API (introduced in CFMX7) or specific admin logins (coming in Scorpio). Don’t get me wrong, I understands the problem that you are trying to solve, I just think that there are better solutions, then defining data sources on the fly.
    — Ben

  21. Reto Avatar
    Reto

    I would love to see a defaultDatasource setting. Not to define a datasource, but i would like to not specify the datasource each time in the cfquery tag.

  22. Joshua Curtiss Avatar
    Joshua Curtiss

    Calvin, yeah, you get where I’m coming from completely.
    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..

  23. Ben Forta Avatar
    Ben Forta

    Reto, I love that idea. Might be a bit late for Scorpio, but I will definitely make sure it is added to the wish list.
    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

  24. Ben Forta Avatar
    Ben Forta

    Calvin, these settings usually go in the "constructor" section of Application.cfc (see http://livedocs.adobe.com/coldfusion/7/htmldocs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=ColdFusion_Documentation&file=00000696.htm). Although, I guess they could also go in the onApplicationStart method. Either way, they need to be saved to THIS scope.
    — Ben

  25. John Farrar Avatar
    John Farrar

    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! 🙂

  26. Kyle Hayes Avatar
    Kyle Hayes

    Oh wow! That’s great! This is definitely a long awaited feature!!

  27. Joshua Curtiss Avatar
    Joshua Curtiss

    Ben, you’re right!! I have to admit I forgot about CAR deployments.
    "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.

  28. Ben Nadel Avatar
    Ben Nadel

    Ben,
    I cannot seem to get this right. In my App CFC, I have:
    <cfset THIS.Mappings[ "images" ] = "C:Websitesimages" />
    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.

  29. Ben Nadel Avatar
    Ben Nadel

    Also, just to add, if I do a CFDirectory with the path directly:
    <cfdirectory action="list" directory="C:Websitesimages" name="qFile" />
    It works fine, so the path itself is correct (and returns a number of records).

  30. Aaron Neff Avatar
    Aaron Neff

    Hi Ben Nadel,
    Does the following work?
    <cfset THIS.Mappings[ "/images" ] = "C:Websitesimages" />
    ("/images" instead of "images")

  31. Russ Michaels Avatar
    Russ Michaels

    dickbob, your reason for using applicationproxy seems flawed.
    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.

  32. O?uz Demirkap? Avatar
    O?uz Demirkap?

    Hi Ben,
    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:Domainsmydomainincludes">
    </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:Domainsmydomainincludes">
    Are there way other way to use this new feature except Application.cfc?

  33. O?uz Demirkap? Avatar
    O?uz Demirkap?

    Hmm.
    "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?

  34. Aaron Neff Avatar
    Aaron Neff
  35. Julian Halliwell Avatar
    Julian Halliwell

    Ben, I’ve just upgraded to CF8 and tried to set per app mappings following your examples but they just kept giving "not found" errors (used in both cfinclude and CFC invocation). The solution was to add a forward-slash before each mapping entry:
    <cfset THIS.mappings["/MyStuff"]="c:inetpubMyStuff">
    NOT
    <cfset THIS.mappings["MyStuff"]="c:inetpubMyStuff">
    The Livedocs examples also don’t include slashes. Am I right that the slashes are required?

  36. Holly Avatar
    Holly

    Is classpath something that is configurable in in CAR deployments or in the application.cfc? Or would we still be stuck with getting the multiple instances license of CF?

  37. Ahamad Avatar
    Ahamad

    I have added an example for per app settings here…
    http://coldfusion8.blogspot.com/2008/03/per-app-settings-example.html

  38. Andy Bellenie Avatar
    Andy Bellenie

    Putting objects into application scope when using per-app-mappings raises some issues. Take this example application.cfc
    <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.

  39. Morgan Gustafsson Avatar
    Morgan Gustafsson

    Per application mappings is not working with FLEX?
    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!

  40. Rafael Avatar
    Rafael

    Does anyone know of a way to display the custom tag paths that are configured for an application programmatically? Something along the lines of a system function like GetCustomTagPaths()?

  41. Ameen Avatar
    Ameen

    If I used
    <cfset THIS.customtagpaths=ListAppend(customtagpaths, "c:webmysitetags")>
    it gives error that Variable Customtagpaths is undefined.
    if I used
    <cfset THIS.customtagpaths="c:webmysitetags")>
    it overwrite all default paths and assume that all customtags are inside this folder "c:webmysitetags"
    even if I called the customtag from a file, where the customtag and file are existing in the same directory.
    any help plz.

  42. Andy Bellenie Avatar
    Andy Bellenie

    Try <cfset this.customtagpaths=ListAppend(this.customtagpaths, "c:webmysitetags")>
    … you missed the this scope in the first argument of listappend
    🙂

  43. Chris Luksha Avatar
    Chris Luksha

    I have the same troubles as Ameen except I already tried using the this.customtagpaths. I have the following code set:
    this.customtagpaths=ListAppend(this.customtagpaths, "#getDirectoryFromPath(getCurrentTemplatePath())#orgewsudf") ;
    and it returnes the following error:
    Element CUSTOMTAGPATHS is undefined in THIS
    Also – Is there a way to dump the system custom paths?
    thanks all,
    Chris

  44. Ameen Avatar
    Ameen

    @Chris Luksha
    For me its still not solved. What I did is, I used
    <cfset THIS.customtagpaths="c:webmysitetags">
    and then I was able to append other paths with
    <cfset THIS.customtagpaths=ListAppend(THIS.customtagpa

  45. Ameen Avatar
    Ameen

    Oops
    "….skip this check and looks in the paths and defined."
    I mean
    "….skip this check and looks in the paths I defined."

  46. Ted Steinmann Avatar
    Ted Steinmann

    I’m having an issue with my application randomly losing access to the location of my custom tags. Specifically I am getting the following error:
    “Cannot find CFML template for foo”
    I’m dynamically setting my application root, and deriving my custom tag path from that:
    <cfset this.root = getDirectoryFromPath(getCurrentTemplatePath()) />
    <cfset this.customtagpaths = this.root & "extensionscustom_tags" />
    Would there be any problems with using the above to derive the location of these tags?

  47. Ted Steinmann Avatar
    Ted Steinmann

    Update: This issue came up again for us, but more serioursly this time. Turns out cumulative hotfix 4|Coldfusion 8.0.1 fixed the issue:
    http://kb2.adobe.com/cps/529/cpsid_52915.html
    73761 Fix for the error "Cannot find CFML template for custom tag" thrown under load when using THIS.customtagpath in application.cfc and "enable per app settings" is enabled.

Leave a Reply