Composition over inheritance with ColdBox 3
As ColdBox 3 is still in development, I've turned into a bit of a version junkie and often update my ColdBox revision from the SVN server. This all works fine for me on my development box, but causes problems for other members of the development team who don't run the latest revision. Another downside to running on the bleeding edge is that any other applications I have already built tend to break.
So, how do I make sure that all members of the development team have the latest version of ColdBox? Well, typically, MVC frameworks work by having the Application.cfc extend the framework. This means you can't use per-application mappings, so can we use "Composition over Inheritance"?
Luckily ColdBox 3 has a cunning trick up it's sleeve that allows you to "bootstrap" ColdBox to your application and therefore allow per-application mapping to the ColdBox directory, that is a sub-folder inside my application folder. There is more information on the ColdBox wiki, but there isn't an example of what the Application.cfc looks like. So here is one I created using the excellent ColdFusion Builder ColdBox extension:
<!--- note, this doesn't extend coldbox.system.ColdBox --->
<cfcomponent output="false">
<cfsetting enablecfoutputonly="yes">
<cfscript>
// COLDBOX STATIC PROPERTY, DO NOT CHANGE UNLESS THIS IS NOT THE ROOT OF YOUR COLDBOX APP
COLDBOX_APP_ROOT_PATH = getDirectoryFromPath(getCurrentTemplatePath());
// The web server mapping to this application. Used for remote purposes or static purposes
COLDBOX_APP_MAPPING = "";
// COLDBOX PROPERTIES
COLDBOX_CONFIG_FILE = "";
// COLDBOX APPLICATION KEY OVERRIDE
COLDBOX_APP_KEY = "";
// APPLICATION CFC PROPERTIES
this.name = Right(ReReplaceNoCase(COLDBOX_APP_ROOT_PATH,"[^A-Z]", "", "all"),64);
this.sessionManagement = true;
this.setClientCookies = true;
if ( IsDefined( "cookie.cfid" ) )
{
this.sessionTimeout = createTimeSpan(0,0,30,0);
}
else
{
this.sessionTimeout = createTimeSpan(0,0,0,1);
}
// create a mapping to the myapp/frameworks/coldbox directory
this.mappings["/coldbox"] = COLDBOX_APP_ROOT_PATH & "frameworks/coldbox";
// orm
this.datasource = "mydsn";
this.ormEnabled = true;
this.ormSettings = {};
this.ormSettings.cfclocation = "model";
this.ormSettings.flushatrequestend = false;
this.ormSettings.automanageSession = false;
if ( CGI.SERVER_NAME eq "localhost" )
{
this.ormSettings.logSQL = true;
}
</cfscript>
<!--- on Application Start --->
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfscript>
//Load ColdBox
application.cbBootstrap = CreateObject("component","coldbox.system.Coldbox").init(COLDBOX_CONFIG_FILE,COLDBOX_APP_ROOT_PATH,COLDBOX_APP_KEY,COLDBOX_APP_MAPPING);
application.cbBootstrap.loadColdbox();
return true;
</cfscript>
</cffunction>
<!--- on Request Start --->
<cffunction name="onRequestStart" returnType="boolean" output="true">
<!--- ************************************************************* --->
<cfargument name="targetPage" type="string" required="true" />
<!--- ************************************************************* --->
<!--- BootStrap Reinit Check --->
<cfif not structKeyExists(application,"cbBootstrap") or application.cbBootStrap.isfwReinit()>
<cflock name="coldbox.bootstrap_#hash(getCurrentTemplatePath())#" type="exclusive" timeout="5" throwontimeout="true">
<cfset structDelete(application,"cbBootStrap")>
<cfset application.cbBootstrap = CreateObject("component","coldbox.system.Coldbox").init(COLDBOX_CONFIG_FILE,COLDBOX_APP_ROOT_PATH,COLDBOX_APP_KEY,COLDBOX_APP_MAPPING)>
</cflock>
</cfif>
<!--- Reload Checks --->
<cfset application.cbBootstrap.reloadChecks()>
<!--- Process A ColdBox Request Only --->
<cfif findNoCase('index.cfm', listLast(arguments.targetPage, '/'))>
<cfset application.cbBootstrap.processColdBoxRequest()>
</cfif>
<!--- WHATEVER YOU WANT BELOW --->
<cfreturn true>
</cffunction>
<!--- on Application End --->
<cffunction name="onApplicationEnd" returnType="void" output="false">
<!--- ************************************************************* --->
<cfargument name="appScope" type="struct" required="true">
<!--- ************************************************************* --->
<cfset arguments.appScope.cbBootstrap.onApplicationEnd(argumentCollection=arguments)>
</cffunction>
<!--- on Session Start --->
<cffunction name="onSessionStart" returnType="void" output="false">
<cfset application.cbBootstrap.onSessionStart()>
</cffunction>
<!--- on Session End --->
<cffunction name="onSessionEnd" returnType="void" output="false">
<!--- ************************************************************* --->
<cfargument name="sessionScope" type="struct" required="true">
<cfargument name="appScope" type="struct" required="false">
<!--- ************************************************************* --->
<cfset appScope.cbBootstrap.onSessionEnd(argumentCollection=arguments)>
</cffunction>
<!--- OnMissing Template --->
<cffunction name="onMissingTemplate" access="public" returntype="boolean" output="true" hint="I execute when a non-existing CFM page was requested.">
<cfargument name="template" type="string" required="true" hint="I am the template that the user requested."/>
<cfreturn application.cbBootstrap.onMissingTemplate(argumentCollection=arguments)>
</cffunction>
</cfcomponent>
Neat huh?
- Posted in:
- ColdFusion
- Coldbox
- OOP
- CFBuilder


Comment by Aaron Greenlee – July 19, 2010
Comment by Aaron Greenlee – July 19, 2010
Comment by Markus Schneebeli – September 13, 2011
Comment by John Whish – September 14, 2011