Anatomy of a Framework - Mach-II - Part 2 - The Request Process
Posted on Sep 27, 2007
In our first entry in this series where we are looking under the covers of various ColdFusion frameworks, we examined what happened when Mach-II first starts up. The application startup process handled a lot of the heavy lifting for the framework, and therefore our examination of the request process becomes fairly straightforward.
Effectively, the application startup process parsed all relevant XML configuration files and created collections of events and commands that can be called and processed. These are, obviously, just component method calls on your Mach-II specific CFCs (i.e. the listeners, plugins and filters). Thus, the request process, in simplistic terms, is just a matter of parsing the event information and stringing these calls together. The entire request process in Mach-II 1.5 (currently in beta) is kicked off within the onRequest() method of Application.cfc which calls handleRequest() machII.mach-ii.cfc. Let's take a closer look.Configuration Mode
As is standard on frameworks, Mach-II has the concept of configuration modes that allow the framework to be reloaded to simplify working in development, where changes to the configuration XML or framework specific components is common. Thus the first thing that happens in the request process is logic to decide if the framework should be reloaded or not. In the case of Mach-II, a MACHII_CONFIG_MODE of 1 will always reload, 0 will reload only if the XML has been modified and -1 will never reload. This setting is set in the properties area at the beginning of Application.cfc.
Building the Event Object
If you are familiar with Mach-II, you know that the Mach-II event object contains all the values from both the form and URL scope. Thus, the next process run gets all the arguments for the event from the form and url scopes and appends them to the event arguments. In addition, Mach-II 1.5 introduced some new URL management features that support SES URLs, so the process of building the event arguments also parses out variables from an SES URL.
With the addition of module support in Mach-II 1.5, Mach-II now has a new method of calling module events which by default is event=moduleName:EventName. Therefore, when parsing the event parameter, which is the next process that occurs, the framework first determines if you are calling an event within a module. If you haven't defined an event at all, the default event is called. Next it determines if the called event is defined in your configuration XML and that it is not set to private, which means it cannot be called publicly but rather only by other events. If everything is defined properly, the event is appended as the next event in the event queue with the "event context" (/MachII/framework/EventContext.cfc).
Now that the event object for our request has been fully populated and validated, its time to actually process the event as it is defined within the configuation XML. As you may remember from Part I, the filters, plugins and listener calls were all appended to application specific arrays and collections of commands during the startup process. Processing the event becomes simply a matter of looping through and executing the various commands within the relevant array or structure. Of course, with plugins, there are the various plugin points and those are called at the appropriate time within the execution process of the event.
First, the application calls any plugins with a pre-process plugin-point defined. Next, it loops through the event queue, loads the appropriate appManager for the call because modules have their own appManager that is a child of the main/parent appManager. Subsequently, the framework calls any plugins with a pre-event plugin point defined. Once this is complete, the eventHandler execute the event, which is a matter of looping through the various "commands" within that event and calling their appropriate execute method. Within the /framework/commands/ folder you can see the various command CFCs that relate to their correlating XML syntax expression (i.e. listeners, filters, subroutines, views, redirects, etc.). After, the commands have complete processing, any post-event plugin methods are called and finally any post-process plugin methods are called.
What We've Learned
I think the key here is that the core of the frameworks heavy lifting is accomplished at startup, whereby most of the code needed to execute is parsed and cached within the framework itself. While this makes the application startup process sometimes slow, the request process is, as you can see, straightforward and light. In fact, few objects are actually instantiated during the course of the request.
I also believe that this further illustrates that while a framework may seem like a black box at times, there is no magic going on behind the scenes. All of the code discussed is something someone reasonably versed in ColdFusion code could understand. At its core, the entire request process is simply a matter of looping through a predefined set of component method calls and executing them in the proper order. What the framework provides is both a toolset for accomplishing this (and other common tasks) with less effort, as well as a consistent, proven, documented and easily-understandable approach.
Posted By Paul Marcotte / Posted on 09/27/2007 at 9:23 AM