Singletons Business Objects in CFWheels

Like many application development frameworks, there is lots of plumbing within that you don't have to use, but hey, it makes a ton of sense. Singleton object management is a good use case. Now let's be clear, I could add something like ColdSpring to offload my object factory pattern to a separate  framework - that often makes sense, but depending on the client and how encapsulated you want to keep things, sometimes just a good clean way to do it on your own makes the most sense.

So we want to make instances of a component and keep these instances around beyond a request. In CFWheels, what's the best way?

As it turns out, the answer is mind-bogglingly simple - but we have to consider (2) things:

  1. Where do we create the object instances?
  2. How will we be able to reference them?

In straight-up ColdFusion (no framework), we have Application events like onRequestStart, onSessionStart, OnApplicationStart & onServerStart that answer question#1. As for how to reference them, well, that's easy too - we can just use the "scope" of choice for the persistence - "request, session,application or server" and your done. Of course you may need a trigger to "refresh" the cached instances (now you're adding some plumbing). Here's the "old school" way of handling this (or at least the non-framework way)

<cffunction name="onApplicationStart" returntype="boolean" output="false">
	<cfset buildCache() />
	<cfreturn true />
</cffunction>

<cffunction name="onRequestStart" returntype="boolean" output="false">
	<cfif structkeyExists(url,"reload")>
		<cfset onApplicationStart() />
	</cfif>
	<cfreturn true />
</cffunction>

<cffunction name="buildcache" hint="I'll build the app cache of singletons">
	<cflock scope="application" type="exclusive" timeout="10">
		<cfset util = createObject("component","lib.util.widget").init() />
	</cflock>
</cffunction>

But with CFWheels, we really should leverage the framework and not worry about micro-managing these events (although we certainly can if we want to get that granular) - so check it out. Answer #1: config/settings.cfm Answer#2: use the CFWheels set() function:

<cfscript>
	set(util= createobject("component","lib.util.widget").init());
</cfscript>

The Beauty of this solution is that settings.cfm only fires when the application loads (or reloads) - essentially (but not identical to) the onApplicationStart event. Secondly, to provide visibility of our variable anywhere in the application, using the set() function allows us to access the variable by using the get() function

<cfscript>
	util = get("util");
</cfscript>

please note: This solution is specifically for application singletons - behind the scenes, CFWheels is using the application scope for these settings - in fact, the documentation on config/settings.cfm explicitly states this file is for configuration - which is in fact a good use case for application level persistence, but not the only use case. Singleton (Business) Objects are also perfectly viable candidates for this same sort of persistence.