5

I have trouble with setting mappings in Application.cfc We have diverent Server (dev,QS,prod) Each with a little different Pathes. I want to set serverspecific pathes and variables via configuration file. On ApplicationStart you read the ini file and setup your system. http://www.raymondcamden.com/index.cfm/2005/8/26/ColdFusion-101-Config-Files-AGoGo This works fine.

Normaly you set mappings in Applcation.cfc like this:

<!--- in Application.cfc --->
<cfset this.mappings['/components'] = "D:\Inetpub\wwwroot\myApp\components">

Somewhere in a normal cfm File I instatiate a cfc named test via:

<cfset t = createObject("component", "components.test")>

I want to set the mappings only once at onApplicationsStart

<cffunction
    name="OnApplicationStart"
    access="public"
    returntype="boolean"
    output="false"
    hint="Fires when the application is first created.">

    <!---create structure to hold configuration settings--->
    <cfset ini = structNew()>
    <cfset ini.iniFile = expandPath("./ApplicationProperties.ini")>
    <cfset application.ini = ini>

    <!--- read ini file --->
    <cfset sections = getProfileSections(application.ini.iniFile)>

    <cfloop index="key" list="#sections.mappings#">
       <cfset this.mappings[key] = getProfileString(application.ini.iniFile, "mappings", key)>
    </cfloop>

But this don't work because this.mappings is empty and next request. :(

Putting this to OnRequestStart

<!--- read ini file --->
    <cfset sections = getProfileSections(application.ini.iniFile)>

    <cfloop index="key" list="#sections.mappings#">
       <cfset this.mappings[key] = getProfileString(application.ini.iniFile, "mappings", key)>
    </cfloop>

I get an error that the component can't be found. This is strange.

Putting the struct into Application scope

    <cfloop index="key" list="#sections.mappings#">
       <cfset APPLICATION.mappings[key] = getProfileString(application.ini.iniFile, "mappings", key)>
    </cfloop>

How to call my Component?

<cfset t = createObject("component", "application.components.test")>

Doesn't work.

So I have 3 targets.

  1. reading all pathes and mappings from ini file
  2. reading them once at ApplicationStart
  3. easy usage in sourcecode.
tshepang
  • 12,111
  • 21
  • 91
  • 136
inog
  • 53
  • 1
  • 7

1 Answers1

7

Mappings can't be set in onApplicationStart(), they must be set in the pseudo constructor of Application.cfc, and they must be set on every request.

It's also important to note that the application scope is not available at this point, therefore if you need to cache anything you'll need to use the server scope. You can cache your mapping struct to the server scope and just set it into this.mappings each request.

<cfcomponent>
  <cfset this.name = "myapp" />

  <!--- not cached so create mappings --->
  <cfif NOT structKeyExists(server, "#this.name#_mappings")>
    <cfset iniFile = getDirectoryFromPath(getCurrentTemplatePath()) & "/ApplicationProperties.ini" />
    <cfset sections = getProfileSections(iniFile) />
    <cfset mappings = structnew() />
    <cfloop index="key" list="#sections.mappings#">
      <cfset mappings[key] = getProfileString(iniFile, "mappings", key)>
    </cfloop>
    <cfset server["#this.name#_mappings"] = mappings />
  </cfif>

  <!--- assign mappings from cached struct in server scope --->
  <cfset this.mappings = server["#this.name#_mappings"] />

  <cffunction name="onApplicationStart">
  <!--- other stuff here --->
  </cffunction>

</cfcomponent>

If you intend to keep you ini file in the webroot, you should make it a .cfm template and start it with a <cfabort>. It will work just the same but will not be readable

ApplicationProperties.ini.cfm

<cfabort>
[mappings]
/foo=c:/bar/foo
Chris Blackwell
  • 2,138
  • 17
  • 22
  • Thanks very much this brings me an big step into the right direction. But because of this line I get an "not Found Error" when calling a page which is not in webroot. – inog May 11 '12 at 14:20
  • I don't want to hardcode it. Any idea for this chicken or egg dilemma? – inog May 11 '12 at 14:30
  • Thats because its calling expandpath() relative to the current file location. You'll have to use an absolute path, i've updated my answer to show this – Chris Blackwell May 11 '12 at 15:14
  • If you intend to keep the ini file in the webroot you should ***not*** mislabel it a CFM file, but rather tell your webserver not to serve *.ini files! (Same goes for XML and everything else that isn't a CFML template.) – Peter Boughton Aug 22 '12 at 12:58
  • adding .cfm to configuration files is a simple cross platform solution that works without requiring changes to the hosting environment that may or may not be possible, its used widely by applications, frameworks and even Railo's config files. – Chris Blackwell Aug 22 '12 at 13:26