Using Relative File Paths To Configure Application Mappings In Lucee CFML 5.3.8.201
Historically, Adobe ColdFusion was never very friendly to relative file paths on the server - a relative file path always seemed to point to a different folder than the one in which my script was executing. Lucee CFML, on the other hand, has made it a point to be much more intuitive when it comes to relative file paths. Since switching to Lucee CFML, I've come to love this relative file path behavior when performing file I/O; however, it only just occurred to me that this same behavior may also work when configuring Application Mappings within the Application.cfc
file. As such, I wanted to compare the current Adobe ColdFusion behavior to the current Lucee CFML 5.3.8.201 behavior.
Before we look at the relative path behavior, let's quickly talk about what I used to have to do in my Application.cfc
file. Historically, I would have to use ColdFusion's native path-functions to find the directory in which my Application.cfc
file lived. Then, I'd have to build my mappings relative that that directory. The code looked something like this:
component
output = false
hint = "I define the application settings and event handlers."
{
// Define the application settings.
this.name = "AppMappingsDemo";
this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 );
this.sessionManagement = false;
// Setup the application mappings that can be used in server-side file access paths:
// things like the expandPath() function, the include tag, and the module tag can all
// consume mappings in order to create some abstraction around the file-system.
this.root = getDirectoryFromPath( getCurrentTemplatePath() );
this.mappings2 = {
"/root": this.root,
"/up-one": ( this.root & "../" ),
"/down-one": ( this.root & "vendor/" )
};
}
Notice that I am using the getDirectoryFromPath()
and getCurrentTemplatePath()
functions in order to find the file-system location of the Application.cfc
template; and then using that value to build-out the mappings
structure. This isn't super complicated; but, it's a point-of-friction; and, it represents some additional processing that has to be done on every single page request that runs through your ColdFusion application.
Now, let's compare that Adobe ColdFusion Application.cfc
to a Lucee CFML Application.cfc
that leverages Lucee's friendly take on relative file paths:
component
output = false
hint = "I define the application settings and event handlers."
{
// Define the application settings.
this.name = "AppMappingsDemo";
this.applicationTimeout = createTimeSpan( 0, 1, 0, 0 );
this.sessionManagement = false;
// Setup the application mappings that can be used in server-side file access paths:
// things like the expandPath() function, the include tag, and the module tag can all
// consume mappings in order to create some abstraction around the file-system. In
// this case, notice that I am using RELATIVE FILE PATHS to define the mappings.
this.mappings = {
"/root": "./",
"/up-one": "../",
"/down-one": "vendor/"
};
// NOTE: Historically, with Adobe ColdFusion, I've had to configure mappings using
// much more complicated path-parsing since Adobe ColdFusion doesn't like using
// relative file-paths for anything server-side related (except the include tag).
}
Notice how much cleaner my mappings
structure is when I can use file paths that are relative the Application.cfc
. But, does it work?! To test this, I am going to output the expandPath()
version of each one of these mappings at various folder-depths within the application. Here's my root index.cfm
file:
<cfoutput>
<h1>
In Root - #server.coldfusion.productName#
</h1>
<dl>
<dt><code>/root</code></dt>
<dd>#expandPath( "/root" )#</dd>
<dt><code>/up-one</code><dt>
<dd>#expandPath( "/up-one" )#</dd>
<dt><code>/down-one</code><dt>
<dd>#expandPath( "/down-one" )#</dd>
</dl>
<!---
In order to make sure that the location of the SCRIPT isn't somehow influencing
the way the expandPath() is interacting with the Application.cfc mappings, let's
try to output the same mapping values in a few folders at various depths within
the folder hierarchy. Both of the following files have the same DL as above.
--->
<iframe
src="./sub/index.cfm"
style="display: block ; width: 100% ; height: 182px ;">
</iframe>
<iframe
src="./sub/sub/index.cfm"
style="display: block ; width: 100% ; height: 182px ;">
</iframe>
</cfoutput>
Notice that I have a definition list (<dl>
) of path values. And, that I have two iframe
s. Each of the iframe
s outputs the same definition list; only, it performs the output in sub-folders of the application.
Now, it should be noted that I am running my test servers at the following location:
/Users/bennadel/Sites/testing-lucee/
And, that this experiment is, itself, in a sub-folder of the server:
/Users/bennadel/Sites/testing-lucee/app-mappings/wwwroot/
With that said, let's render this page in Lucee CFML 5.3.8.201:
As you can see, even though our Application.cfc
is located in a sub-folder of the running server; and, even though we are consuming the application mappings in even deeper folders within the file-system; all of the mappings just work when using intuitive relative file paths.
Sweet, sweet chickens!
Now, let's run the same exact page in Adobe ColdFusion 2021:
As you can see, in Adobe ColdFusion 2021 (and historical versions of ColdFusion), the relative paths within the Application.cfc
are not relative to the "application root", they are relative to the "server root". This is why - historically - I've always had to mess with the getCurrentTemplatePath()
function when configuring my application mappings.
Lucee CFML has a lot of really nice developer ergonomics; one of which is its attitude towards relative file paths. In general, relative file paths "just work". They work when performing file I/O; and, as we now know, they work when configuring ColdFusion application mappings. So nice!
Want to use code from this post? Check out the license.
Reader Comments
Hi Ben, I love the idea of simplifying mapping definitions in this way, but I'm not sure it's 100% reliable.
I have a use case in which it seems not to work. See my follow-up post here: https://blog.simplicityweb.co.uk/127/defining-application-mappings-using-relative-paths-in-lucee
@Julian,
Good stuff. Inheritance is always a bit tricky when it comes to
Application.cfc
- left a comment over on your article.