Writing Your Own Simple MVC Framework in ColdFusion
There are a few ColdFusion frameworks around but unfortunately it may not always be possible to use them – such as in a shared hosting environment. See my previous post about ColdFusion mappings which discusses why.
The following notes describe how a simple event driven framework might be written. This is intended to be a bare bones framework to hopefully keep everything as simple as possible.
Credit
I did have a brief look at the Model-Glue before writing this up, so any good ideas that you see here can be credited to Joe Reinhart and Model-Glue. All of the bad ideas are completely mine.
What is a Model View Controller?
Perhaps the first place to start is to understand what is a Model View Controller?
The Model represents the group of your ColdFusion components that manage the current state of your application, the business logic, and the data storage (i.e. 'data persistence').
The View represents the group of components and .cfm files that handle the display of all information in the browser. The View displays the page layouts and sets up the colours and fonts etc. as well as displaying the hyperlinks, buttons and forms to capture input from the users of your application.
The Controller ties together the Model and the View. Specifically, a click of a link or button in the browser window (i.e. the View) causes a message to be sent to the Controller (via an HTTP request). The Controller then interacts with the Model to do some processing then sends a message back to the view indicating what to display next.

Components of our simple framework
There are not many components that make up this simple framework. The key components that we will be discussing are:
Event - the event coming from the browser, which is an instruction of what to do next.
Controller – the component that knows how to handle the event.
EventResult – a component that contains the outcome of the event.
ViewState – a component that contains data that may be displayed within the browser (i.e. within a View).
Events
We will use the term 'event' to represent an HTTP request. Specifically an event occurs when a hyperlink or a form button is clicked.
So what does an event look like? Well, an event is something that has a name and associated data. I will call this data the 'event attributes'.
For example, suppose you have a form that simply collects a person's first name and last name. When submitted it displays the words "Hello" followed by the persons name. The form may look something like this:
<input type="hidden" name="event" value="SayHello" />
First Name <input name="firstName" /><br />
Last Name <input name="lastNameName" /><br />
<input type="submit" value="Go" />
</form>
Notice the hidden field in the form named "event". If this form was submitted with the first name "Davy" and last name "Jones", it will create an event with the name "SayHello" and the attributes firstName="Davy" and lastName="Jones".
Our event component may look something like the following.

So how does our SayHello form data get converted into an event? Well the 'event' parameter is set as the event name, and all of the form fields are set as the event attributes. This can be done quite easily in the init() method on the Event component. Here is a code snippet (I have left out validation and some other bits to keep it simple for now):
<cfargument name="formData" type="struct" required="true" />
<cfset var name = "" />
<cfset var eventName = "" />
<!--- Set all of the form parameters as event attributes --->
<cfloop item="name" collection="#arguments.formData#">
<cfset setAttribute(name,arguments.formData[name]) />
</cfloop>
<!--- Set the event name --->
<cfset setName(getAttribute("event")) />
<cfreturn this />
</cffunction>
This could be extended to support URL data as well by simply adding a second argument holding the URL variables, and add them in the same way to the set of event attributes.
Lastly, how do we use our event component? This event needs to be created at the top of your index.cfm file ready for use by the rest of the application. You would likely create a default event in case the event parameter was not passed in from the form.
<cfset event = createObject("component","Event").init(form) />
The Controller
Once we have our event ready, we need to pass it to the controller; it is the controller's responsibility to handle all events that occur within the system. In a large system the controller may be broken into multiple smaller controllers each handling a different part of the system.
So our Controller is going to process our event and then return to us an EventResult object to let us know what happened.
So what sort of results can we expect after processing an event? In this example, we will assume the only result is to display some output.
So back to our controller:

The controller will have a handleEvent() function that takes the event we created above as a parameter. This handle event function will then pass the event onto another function that has the same name as the event itself.
So in our example above that has an event called SayHello, we will need a function in the controller also called sayHello() to handle that particular event.
Determining if a function exists in a component
I think a quick note might be useful here to discuss about a very nice feature in ColdFusion that allows you to discover if a particular function exists in a component.
Suppose you have defined a function as follows:
<!--- Your code here --->
</cffunction>
You can check for the existence of this function as follows:
<!--- Yes the function exists --->
<cfelse>
<!--- No, the function does not exists --->
</cfif>
Or, using a variable
<cfif isDefined("variables.#functionName#")>
<!--- Yes the function exists --->
<cfelse>
<!--- No, the function does not exists --->
</cfif>
Calling ColdFusion functions
Usually when calling a function, you would use syntax such as
However, ColdFusion supports an alternate syntax using the
<cfinvoke method="#functionName#" returnvariable="eventResult">
<cfinvokeargument name="event" value="#event#" />
</cfinvoke>
Back to the Controller
So now we can look at how the handleEvent() function will work. First it checks if a function exists that has the same name as the event, and if so it executes that function then returns the resulting EventResult.
<cfargument name="event" required="true" />
<!--- Define a variable to hold the result of the event call --->
<cfset var eventResult = "" />
<!--- Get the name of the event --->
<cfset var eventName = event.getName() />
<!--- Check if a function with the same name as the event exists --->
<cfif isDefined("variables.#eventName#")>
<!--- Execute the event handler function --->
<cfinvoke method="#eventName#" returnvariable="eventResult">
<cfinvokeargument name="event" value="#arguments.event#">
</cfinvoke>
<cfreturn eventResult />
</cfif>
<!--- If the function was not found then throw an error --->
<cfthrow type="MissingEventHandlerException" />
</cffunction>
The EventResult
What does an event result look like? As mentioned above, to keep things simple our event will simply provide some output that needs to be displayed in the browser.

How does the Event Result get created?
The event result is created back in our Controller in the function called by handleEvent(). In our example this is the sayHello() function:
<cfargument name="event" required="true">
<!--- Get the first and last names out of the event --->
<cfset var firstName = arguments.event.getAttribute("FirstName") />
<cfset var lastName = arguments.event.getAttribute("LastName") />
<!--- Create the string to return --->
<cfset var output = "Hello, #firstName# #lastName#" />
<!--- Create and return the event result --->
<cfset var eventResult = createObject("component","EventResult").init() />
<cfset eventResult.setOutput(output) />
<cfreturn eventResult />
</cffunction>
So within the controller, the handleEvent() function calls the SayHello() function, which returns an eventResult all the way back to the original .cfm page.
How is the output displayed in the browser?
Back in out index.cfm file we can now complete the code to display the generated output:
<cfparam name="form.event" default="">
<cfset event = createObject("component","Event").init(form) />
<!--- Pass the event to the controller to handle --->
<cfset controller = createObject("component"," Controller").init() />
<cfset eventResult = controller.handleEvent(event) />
<!--- Display the result --->
<cfoutput>#eventResult.getOutput()#</cfoutput>
View Templates and View State
You will need to display more than just simple text in the browser. Following is a technique that you can use to display views based on a template page.
A View is made up of two things (1) a normal ColdFusion .cfm template that contains the page layout and display related code, and (2) a View State which is simply data that can be displayed.
The template simply gets data out of the view state and displays it however it chooses. The view state does not contain any HTML, it only contains the raw data to be displayed, such as text to display or a structure of data appropriate for the page (such as a set of Products that needs to be listed).
The view state is a set of name and value pairs. The value can be anything such as a string value or some kind of structured data such as a query result. The component may look something like:

In our SayHello example, the view state will contains the two bits of data submitted in the form; FirstName with the value "Davy" and LastName with the value "Jones"
What does a template look like? Well, heres a template 'sayhello.cfm' that could be used for our SayHello event:
<cfset lastName = viewState.getValue("LastName") />
<html>
<head>
<title>Say Hello</title>
</head>
<body>
Hello, #firstName# #lastName#
</body>
</html>
Displaying the View Templates
So how do we get our template and view state data to appear within the browser?
First we need to define a location for to store our view templates. For this example we will place them in a /views directory in the root of our website.
We now change our sayHello() function to take into account the view template:
<cfargument name="event" required="true">
<!--- Get the first and last names out of the event --->
<cfset var firstName = arguments.event.getAttribute("FirstName") />
<cfset var lastName = arguments.event.getAttribute("LastName") />
<!--- Create a view state --->
<cfset var viewState = createObject("component","ViewState").init() />
<cfset viewState.setValue("FirstName",firstName) />
<cfset viewState.setValue("LastName",lastName) />
<!--- Create the string to return. Notice that the viewState variable
is directly available to the template --->
<cfsavecontent variable="output">
<cfinclude template="/views/sayhello.cfm">
</cfsavecontent>
<!--- Create and return the event result --->
<cfset var eventResult = createObject("component","EventResult").init() />
<cfset eventResult.setOutput(output) />
<cfreturn eventResult />
</cffunction>
Notice that we make use of the
At the moment this template processing is taking place in the Controller. Not sure if that is the best place for it but it seems to work.
Where's the Model?
The Model is the place where all of your business logic and database access is placed. A framework really shouldn't know anything about your Model, that way the framework can be reused across any application you put together.
Wrapping Up
This entry is my current thoughts on creating a simple custom framework. I have left out quite a bit of code and have kept it as simple as possible to hopefully keep the focus on the main idea.
A couple of extra thoughts:
* I didn’t use any .cfcs to display output – they simply build up a string of text which is ultimately passed to a .cfm for display. To display output the .cfc functions need to have the output="true" set all the way down to the point of the display. This just doesn’t seem a very tidy approach.
* Here we create a new controller on each page request, when really only one instance is really needed, so perhaps the controller should be kept in an application variable.
* I have omitted virtually all code related to error handling and inheritance to try keep the code simple.

Possum Jones
...although I'm like 2 years late finding it ;)
Here are a couple of thoughts two years on from writing this entry:
THE EVENT OBJECT
I don't think I could ever write another application without some kind of Event object. Something as simple as packaging url and form variables into a component is so useful. These days I allow a default value to be provided when getting an attribute.
For example, return 0 if the "id" attribute has not been provided:
<cfset id = event.getAttribute("id",0)>
And I have since discovered structAppend() which is a much nicer way of merging the url and form scopes together, rather that all of that looping!
THE CONTROLLER
Having a single application controller component could end up with an enormously fat controller. This can be better managed by splitting an application down into different directories and having a separate index.cfm file in each that simply passes the event object off to a corresponding controller. The controller component does not need to sit in the same directory as index.cfm file but is sitting in an appropriate component area directory.
Short story: have a different controller component for each section of the code.
But, having said all of that, if we want to keep everything simple we could just leave the "controller" code in the index.cfm file (using a simple switch statement to handle each of the possible events). It may not seem object oriented because it is not in a component, but this can assist us when rendering the views ...
THE VIEWS
The views in this example are generated by:
a) Setting some variables needed by the view (the "View State")
b) Include the "view template" and save the output to a variable
c) Store the output variable in an "event result" variable and return it
d) Get the output out of the event result and display it
Well, these days in a home grown framework application I am tending to use cfm files as the controller, which then use custom tags for template rendering.
The main reason is that it keeps the code a little simpler.
My controller code these days looks something along the lines of:
<cfset eventName = event.getArg("event","user.list")>
<cfswitch expression="#eventName#">
...
<cfcase value="user.list">
<cfset users = getUserService().getAllUsers()>
<cfset event.setArg("users",users)>
<cfinclude template="/views/user/user.list.cfm">
</cfcase>
...
</cfswitch>
The getUserService() represents a call to a user service object stored in the application scope.
All values required by the view are placed in the event object, so the set of users returned from this service is placed here (these days I am using getArg() rather than getAttribute() which is the mach-ii naming convention).
ARGUMENTS.FORM.firstName
ARGUMENTS.URL.firstName
...not that this scenario will ever occur, but just wondering how you currently handle possible conflicts.
From what I have seen, community frameworks that use Event objects follow the same approach, but they allow the precendence to be configured.
When the same variable is passed through the URL and Form scopes in one request I would consider it to be a programming error that needs to be fixed. It's definitely an unlikely scenario, but I have seen it in production code.
Possum Jones made a comment about views being packages and I found this very interesting. Why? Well I've created my own pet framework that is based on the concept of Event and View Packages. Both events and views can broadcast messages to the controller depending on what you are trying to achieve. In some cases I want the view and result data from the model to be self contained, and in other cases I want the event to filter data from the model to the view. Overall I’ve gained incredible flexibility while not evading the fundamentals of MVC.
Like Kevan's good example, I used a similar object for storing form and url values called StateCollection which extends a GenericCollection component. The GenericCollection component is also used by my ViewCollection and LogCollection components. This helps maintain a high level of consistency when referencing object types.
stateCollection().getValue('SomeValue')
stateCollection().isValueDefined('SomeValue')
viewCollection().getValue('SomeView')
viewCollection().isValueDefined('SomeView')
These are not singleton objects and are created on every request. All events share the same state collection object which assists greatly when chaining events.
I went as far as to create a lightweight generic object manager which handles all my Non-Singleton and Singleton (Beans, Services, DAOs/Gateway) objects fairly elegantly.
Most of the Coldfusion frameworks out there helped influenced this pet project, giving me the best of all worlds. I am very satisfied with the outcome, especially now that I’ve been able to finally chop that XML syntax down to a bare minimum. I am always seeking better and efficient methods to build large apps quickly and more robustly, even if it means I have to step outside the box a little. Just a little. :)
Hussein
Sounds like some great ideas there. Nice to keep the viewCollection separate from the state. Any thoughts on LightWire or ColdSpring for your object management?
Regarding getting your XML down to a bare minimum; recently I have been noticing some attention to the idea of "convention" over "configuration". For example MXUnit is using a directory structure for organising it's test suites (rather than explicitly creating test suite components) and I understand that the ColdBox framework uses a directory structure for it's event handler (controller) organisation so no handler XML is required. Nice :)
To be honest with you, I've never used LightWire before but will check it out now that you've mentioned it. Coldspring is very good (can't deny that) but for some projects I grew a little weary of all the different xml files to manage. One of the things I've done that I don't think ColdSpring does out of the box is the ability to globalize or localize object instances (correct me if I am wrong). Within the context of my framework’s rules, Globalized objects share data with all core and sub applications within a related web app (All bundled web apps with the same coldfusion ApplicationName but the AppKey required by the framework is unique) while localized objects are only accessible by the app that created them. I find this very useful when you don't want to expose all your objects to every application especially when in a team environment.
Actual Syntax Example:
<_objects>
<!-- Visible to the application that initialized this component only -->
<_object name="VehicleGateway" class="myWebApp.com.model.vehicle.VehicleDAO" global="false" singleton="true" />
<!-- Visible to the application that initialized this component and any other that share the Coldfusion ApplicationName -->
<_object name="VehicleService" class="myWebApp.com.model.vehicle.VehicleService" global="true" singleton="true" >
<constructor>
<arguments>
<argument name="vehicleGateway">
<reference object="VehicleGateway" />
</argument>
</arguments>
</constructor>
</_object>
</_objects>
[Edit: using _objects, _object so they don't get stripped out of the comment]
The xml may not display the best here but you should get the idea. This is nothing elaborate but it works nicely for me.
Coldspring still has its place for me but I quite like my light version which works seamlessly within my framework. From here all I do is reference an object like getObject(“VehicleService”).someMethod().
Re: conventions and configuration
I use both techniques. I have components organized in EventPackages, Filters, ViewHelpers and ViewPackages directories just to name a few. I can setup xml configurations to reference by unique name or enable an auto load call to one or more directories with optional recursion. E.G. Each ViewPackage should have a unique name (ProductViewPackage, OrderViewPackage) followed by a "ViewPackage" suffix so that the prefix becomes the Identifier.
Simple Example
runView(“product”,”list”)
runView(“order”,”list”)
The same applies to events.
Why I still kept xml configuration around?
I don’t always need the entire directory. What if I only wanted one View/Event Package from a list of 20 components? I think everything has its place and I do like the flexibility of choosing what I want when I want it, however, it calls for good organization else your app becomes too confusing for others to dissect. With that all said; I love conventions more than configuration and big thumbs up to the ColdBox team for implementing it so fluidly in their architecture. I’ll check out MXUnit too; heard about it but never had the chance to dig in. There are quite many great CF solutions today and never enough hours in the day to experiment with them all. I guess most people use them as the needs surface. Kinda like me and NSTree now. :)
Hussein
ColdSpring does support the concept of parent and child object factories (where the child can see the parent objects). This may be similar to your global/local concepts, however each factory has its own xml file.
Thanks for sharing your framework concepts.