Mach-ii for newbies - part1
Getting started
Written by Trond Ulseth

1. Introduction

Back in the good old days of my programming career, about 5 years ago, life was easy. Coming from a html/designer background (I actually started my learning with a web site on GeoCities and a copy of Paint Shop Pro) the path to learning ColdFusion was pretty easy going. The amount of online tutorials and paperback books being eager to teach me this fantastic way of programming my homepages almost moved me to my tears. It was just days before I had my own ColdFusion driven guestbook up and running.

I’ve been working as a web developer for about 4 years now, with more spaghetti code on my consciousness than any sane mind can bear to think about. But with ColdFusion MX came cfc’s, and even though it took a while before I discovered them, thanks to them I now find my code extremely tidier and easier to maintain, and I must say that to some degree my style of coding has evolved into some kind of framework which is pretty neat.

But, and there’s a big but, I have come to realize that there are far better ways of organizing code than I can ever hope of mixing together by my self. And after a lot of sniffing around (Google and Fullasagoog) and chatting for advice on IRC, I decided that I would dip my toes into the waters of the mach-ii framework (http://www.mach-ii.com).

However, being spoiled with mountains of books and terabytes of tutorials, I found the available documentation for mach-ii disappointingly lacking. This is not to say that there’s no documentation at all, but what I found I did not find very pedagogical for a total newbie to it. So after months of not quite getting started I decided. I will just dive into it and make a simple application, my good old guestbook, and write a tutorial as I go along. And hopefully other newbie’s, like me, will find this useful as well.

I must underline, I am learning as I’m writing, or writing as I’m learning. I can therefore not give any guaranty that what I am doing is totally best practices, or that I have so much understanding of what I’m doing that I explain it as clear as could be possible. I’ll try though to write in an easy to understand and slightly entertaining way.

I’m going to presume that you have a pretty good grasp of ColdFusion from before. I’m not going to explain ColdFusion tags and functions, variables and properties, what cfc’s are etc. This stuff is well covered from before in the before mentioned amount of books and existing tutorials.

2. Getting prepared

First go to the mach-ii code page (http://www.mach-ii.com/code.cfm) and download the latest version of the Framework Code (version 1.0.10 as I’m writing), and the Application Code Skeleton. Extract them into the home directory of your web server. On my machine they are placed like this:

C:\Inetpub\wwwroot\MachII
C:\Inetpub\wwwroot\MachAppSkeleton

This placement is what I’ll assume during the tutorial. It should not be hard to configure it to work in another set up, but I’m not going to cover that here (maybe in a later tutorial when I have to do it my self).

Now rename the MachAppSkeleton directory to MyGuestbook.

Open the Application.cfm file in the newly renamed MyGuestbook folder, and edit the name attribute of the cfapplication tag to “My Guestbook”.

<cfapplication name="My Guestbook" sessionmanagement="yes" />

Open the mach-ii.xml file in the config directory under MyGuestbook. Under properties change the application root value to /MyGuestbook

<properties>
   <property name="applicationRoot" value="/MyGuestbook" />
   <property name="defaultEvent" value="DEFAULT_EVENT" />
   <property name="eventParameter" value="event" />
   <property name="parameterPrecedence" value="form" />
   <property name="maxEvents" value="10" />
   <property name="exceptionEvent" value="exceptionEvent" />
</properties>

(There’s a closer explanation of these properties at the end of chapter 3)

Now if you open http://localhost/MyGuestbook you should get a blank page, with no errors.

However, blank pages can be rather boring after a while, and can under no circumstance be called a guestbook, so even if you hear the call of the sofa, you need to stay with me a while longer.

Everything in mach-ii is controlled by events. Or at least so I think. It might be that later on in the process we might find this to be wrong. But for now I will pretend it is so. So in order to show some content we need to specify the defaultEvent in the mach-ii.xml file (the mach-ii.xml file is pretty much the heart of the mach-ii framework – so don’t bother closing it. We will do pretty some stuff in here). Let us set the default event value to “showMain”.

<properties>
   <property name="applicationRoot" value="/MyGuestbook" />
   <property name="defaultEvent" value="showMain" />
   <property name="eventParameter" value="event" />
   <property name="parameterPrecedence" value="form" />
   <property name="maxEvents" value="10" />
   <property name="exceptionEvent" value="exceptionEvent" />
</properties>

Now we need to specify what the showMain event will do. Further down the mach-ii.xml file you’ll find the event handlers:

<!-- EVENT-HANDLERS -->
<event-handlers>
   <event-handler event=
"DEFAULT_EVENT" access="public">
   
<!-- any legal elements -->
</event-handler>

Let’s make some changes. We change the event to showMain (because that is the event we declared as default event just now) and put in an element called view-page:

<!-- EVENT-HANDLERS -->
<event-handlers>
   <event-handler event=
"showMain" access="public">
   <view-page name=
"mainTemplate" />
</event-handler>

As you probably can guess (at least I did, and I’m not among the sharpest knifes in the drawer), view-page tell the application what should be shown in the browser window.

There’s one little thing more we have to do in the mach-ii.xml file (I told you we were going to do pretty some stuff in here). Let’s go even further down to find the page views:

<!-- PAGE-VIEWS -->
<page-views>
   <page-view name=
"NEW_VIEW_NAME" page="/views/NEW_VIEW_FILE.cfm" />
   <page-view name=
"exception" page="/views/exception.cfm" />
</page-views>

Now let’s edit the name of the first page view to reflect the view we called from our showMain event, and make it call something more intuitive than NEW_VIEW_FILE.cfm:

<!-- PAGE-VIEWS -->
<page-views>
   <page-view name=
"mainTemplate" page="/views/mainTemplate.cfm" />
   <page-view name=
"exception" page="/views/exception.cfm" />
</page-views>

(We see that there’s another page view called exception there – let’s not bother about that. It’s probably there for a reason, and maybe we’ll stumble across it later)

Now the last thing we need to do in order to get something on the screen is to create the mainTemplate.cfm file and put it in the views folder. For now let’s make it simple:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>
My Guestbook</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body>
<h2>
Welcome to my Guestbook!</h2>
</body>
</html>

Now let’s open http://localhost/MyGuestbook and see if there’s some change. Voila! Not exactly rocket science though. Actually we would have accomplished the same just with the mainTemplate.cfm file. Oh well – we’ll just have to trust that there will be some payoff for the extra work further down the road.

Now let’s try to put some meat on the skeleton.

3. Getting started with mach-ii development

Now it’s time to start shuffling some data into our application. The first thing we’ll do is to give visitors the opportunity to add their messages to the guestbook.

Bellow the header in mainTemplate.cfm adds the following basic form:

<form method="post" name="msgForm">
   <fieldset>
      <legend>
Add your message</legend>
      Name:<br>
      <input name="name" type="text"><br>
      Email:<br>
      <input name="email" type="text"><br>
      Message:<br>
      <textarea name="message" cols="40" rows="5" wrap="virtual"></textarea><br>
      <input type="submit" name="Submit" value="Post message">
   </fieldset>
</form>

Before moving on to how we can make mach-ii aware of the data that is entered (notice we did not add any action attribute to the form yet), we need to have somewhere to store the data. In our case we’ll chose a database (an xml file would be another good option).

In my case I’ll make a MyGuestbook database in MySQL, for now with the following single table.

guestbook
id int(11) auto_increment, primary key
date datetime
name varchar(50)
email varchar(50)
message longtext

Here’s a table creation script:

CREATE TABLE 'guestbook' (
      'id' int(11) NOT NULL auto_increment,
      'date' datetime NOT NULL default '0000-00-00 00:00:00',
      'name' varchar(50) NOT NULL default '',
      'email' varchar(50) NOT NULL default '',
      'message' longtext NOT NULL,
      PRIMARY KEY ('id')
) TYPE=MyISAM AUTO_INCREMENT=1 ;

 

Have you created the database? Ok – then you must define the data source in the ColdFusion administrator. Let’s call it…. MyGuestbook (ok, I’m predictable here. I’ll let the mach-ii framework itself provide the excitement).

If you’re anything like me you are probably used to defining your dsn in the application.cfm file (something like <cfset db = “MyGuestbook”>). Not so in mach-ii. Here we’ll go back to the trusted old mach-ii.xml file (I think we have come pretty some way when we can refer to it as the trusted old...). Up in the properties section well add a property:

<properties>
    <property name=
"applicationRoot" value="/MyGuestbook" />
    <property name=
"defaultEvent" value="showMain" />
    <property name=
"eventParameter" value="event" />
    <property name=
"parameterPrecedence" value="form" />
    <property name=
"maxEvents" value="10" />
    <property name=
"exceptionEvent" value="exceptionEvent" />
    <!-- Application variables -->
    <property name=
"dns" value="MyGuestbook" />
</properties>

Now we’re ready to maneuver submitted messages into that database. We’ll start with the beginning. We need an action parameter for that form. Remember earlier I said that I think everything in mach-ii is controlled by events? We’ll remember that as we set the action parameter like this:

<form action="index.cfm?event=message.create" method="post" name="msgForm">

Also remember that events had associated event handlers. We now need to add an event handler for the message.create event.

<event-handler event="message.create" access="public">
    <event-bean name="message" type="MyGuestbook.model.message.message" />
    <notify listener="messageListener" method="createMessage" />
</event-handler>

Whoa – what’s happening here? In the event handler we worked with earlier we had a view-page method. That one we could understand without invoking too many of the little grey ones. Now we introduce two new ones which by first look are not that self explanatory. We are heading for slightly deeper waters.

The bean

The first new method in the event handler is “event-bean”. A bean is a cfc which models a single instance of an object. In our case the bean creates a message object from the info passed from the form. A bean consist of an init() method as well as so called getters and setters for each of the object attributes.

Let’s take a look at the code for our bean before I try to explain anything else (key word being try).

<cfcomponent displayname="message" hint="I model a single message">

    <cffunction name="init" access="public" returntype="message" output="false" displayname="Message Constructor" hint="I initialize a message.">
            <cfargument name="id" type="numeric" required="false" default="0" displayname="" hint="" />
            <cfargument name="date" type="date" required="false" default="#Now()#" displayname="" hint="" />
            <cfargument name="name" type="string" required="false" default="" displayname="" hint="" />
            <cfargument name="email" type="string" required="false" default="" displayname="" hint="" />
            <cfargument name="message" type="string" required="false" default="" displayname="" hint="" />

            <cfscript>
                variables.instance = structNew();
                setID(arguments.id);
                setDate(arguments.date);
                setName(arguments.name);
                setEmail(arguments.email);
                setMessage(arguments.message);

            </cfscript>

            <cfreturn this />
    </cffunction>

    <!--- GETTERS/SETTERS --->

    <cffunction name="getID" access="package" returntype="numeric" output="false" displayname="" hint="I return ID">
        <cfreturn variables.instance.id />
    </cffunction>

    <cffunction name="setID" access="package" returntype="void" output="false" displayname="" hint="I set ID">
        <cfargument name="id" type="numeric" required="true" />
        <cfset variables.instance.id = arguments.id />
    </cffunction>

    <cffunction name="getDate" access="package" returntype="date" output="false" displayname="" hint="I return date">
        <cfreturn variables.instance.date />
    </cffunction>

    <cffunction name="setDate" access="package" returntype="void" output="false" displayname="" hint="I set date">
        <cfargument name="date" type="date" required="true" />
        <cfset variables.instance.date = arguments.date />
    </cffunction>

    <cffunction name="getName" access="package" returntype="string" output="false" displayname="" hint="I return name">
        <cfreturn variables.instance.name />
    </cffunction>

    <cffunction name="setName" access="package" returntype="void" output="false" displayname="" hint="I set name">
        <cfargument name="name" type="string" required="true" />
        <cfset variables.instance.name = arguments.name />
    </cffunction>

    <cffunction name="getEmail" access="package" returntype="string" output="false" displayname="" hint="I return email">
        <cfreturn variables.instance.email />
    </cffunction>

    <cffunction name="setEmail" access="package" returntype="void" output="false" displayname="" hint="I set email">
        <cfargument name="email" type="string" required="true" />
        <cfset variables.instance.email = arguments.email />
    </cffunction>

    <cffunction name="getMessage" access="package" returntype="string" output="false" displayname=""

About This Tutorial
Author: Trond Ulseth
Skill Level: Intermediate 
 
 
 
Platforms Tested: CFMX
Total Views: 193,429
Submission Date: January 15, 2005
Last Update Date: June 05, 2009
All Tutorials By This Autor: 1
Discuss This Tutorial
  • Damon, Didn't Trond do a good job? Yay Trond! You rock, my Nordic friend... I've recently begun a deep exploration of OO as it applies to my CF development. I've discovered several things that really appeal to me, and I'll try to relate them as concisely as can be. OO is less about function and more about design. Consistent design across an entire industry saves time, eases communication, and solidifies design patterns and methods. Even if something works well in procedural, unless someone knows your design patterns there's going to be a steeper learning curve for them (and potentially higher costs in that case) that if standard design protocols are used and those coming into a project understand those protocols. It's a given that accomplishing any given task is possible in both OOP and PP, so the point isn't that work unit x was provided for. The point is the countless millions of man hours that have gone into developing OO standard practices and therefore provide a set of standard patterns. We can avail ourselves of these tools to enhance our workdays and decrease the amount of work we have to do when designing an application. One of the functional benefits of OO is that the goals of loose coupling, cohesion, and encapsulation provide easier mechanisms for inserting/editing behavior. Modular software has been proven over and over again to be much more easily maintained. Since 70-80% of an application's lifecycle is maintenance, I like the idea that I've lightened my load for 70-80% of the work I have to do. With tools like UML at my disposal, I am able to "draw plans" for an application, so I know what all the parts are before I start writing code. Granted, if someone already has a way to handle that in procedural, then this is probably not so much an issue... until I add another developer to the project and have to spend any amount of time showing them how the application works. I am able to extricate my presentation from my event model from my business model, so if I wish to switch from MachII to Fusebox I can do it quickly. If I choose to alter the way a system works I can simply insure that the View continues to receive it's data as per the design and completely reinvent everything outside it. If my business model changes, it doesn't affect the view or the controller. Since OO is based on the ideals of cohesion and loose coupling, error detection is simplified because error messages are specific to the context in which they occurred and I can log events and/or errors at the individual CFC level. Since OO provides some very specific guidelines that are applicable to any design project in any language, I am better able to avail myself of new tools like instantiating Java objects and incorporating them into my applications, or porting my application to other languages. It an investment of time and energy to learn OO design patterns, I'll grant you that. But for me specifically, the benefits are better architectural tools, standardized design patterns, and easier transition/communication about my projects. Plus, one gains a better understanding of other languages in the process... specifically Java. That can't be a bad thing. :D The main thing to remember is that OO *isn't* about functionality at all. It's about design and structure. I can do the same work in PP, and probably produce the final result more easily and more quickly than I could in OO. However, I've been thru enough development projects to know that a very flexible design based on proven patterns is going to make updates, changes, and fixes a lot simpler once the main development process is complete. The other advantage is incorporating things like MachII and Fusebox and Tartan into an application. They're in use by thousands of applications, being debugged and improved all the time, and I am able to leverage the work of others into my projects with that confidence. That thought applies to OO in general, since I'm able to benefit from the work of thousands of software experts as I develop applications. I could go on forever, so I'll shut up now... but I hope I've helped with the questions. Best regards, Jared

  • First off. Great post Trond. I for one am very glad you donated your time and knowledge to the CF community. Keep up the good work. I came here because of a blog by Sean Corfield. I've been using the Fusebox framework and CFCs for years, but I've never quite had the time to delve into Mach-ii. Ben's whitepaper on Implicit Invocation makes sense to me, but I'd never used an architecture like that. While I have used CFCs, I mainly use them as a convenience for consolidating (reusing) code and to handle all my database work. And while I'm familiar with CRUD, I'm still a little confused about the whole 'instance creation' aspect of OO. I'm used to dealing with either a single record, or multiple records (recordsets). To me, an 'instance' of an object is the same thing as a query object with one record in it. Let me rephrase that. Why should I bother with an OO Object, when a single record query works just fine for me? For example, why have the abstract 'message.cfc' component that will eventually call upon the 'messageCRUD.cfc' to do an insert. Why can't I just call the insert() function in the 'messageCRUD.cfc' and bypass the 'message.cfc' component alltogether? And I'm still very confused about how OO handles the differences between an object-oriented view of the world and a relationship-oriented persistence mechanism (the database). Don't get me wrong, I'm open minded about it, but I'm waiting to see how the Mach-ii framework (well, OO in general) will save me time as a developer.

  • Alex, Vicky, Ken - thank you a lot for your generous positive feedback. Can Atak - Plans are that a part two will cover data retreival/display, editing and deleting. And a part three to cover filters, plug-ins etc. However I have several deadlines in work forcing me to work double shifts for a while, so I think part two is at least a month ahead. Sorry about that. Vamsidar - Thank you for the kind words. If you have concrete suggestions for improvements don't be afraid to shoot me an email.

  • This is a Good One....But can be improved( this statement may be a bit general but)..... This Tutorial will definitely give a good start to any Beginner who want to learn Mach-II... I Agree with the conclusion that the lack of documentation is due to Hal and Ben being afraid of losing training income(which is very bad .....) plz do post your opinions about this mail.. (Grad student,UM at Saint Louis, Working on a project using Mach-II)

  • I also need to show & delete my guestbook entries :) Please! Send part 2, 3 ... in a short time! Thanks in advance!

  • I am also going to have to strongly disagree with KP. I have been using Mach-ii for a while now, and the biggest complaint I had when learning the framework, was there are no good tutorials. I don't really blame Ben and Hal for not putting out more tutorials. I am pretty sure they don't just sit on their hands all day trying to think of things to do (or ways to prevent people from taking money away from them by putting out tutorials :). I think this is a great starter tutorial, in fact I am sending it to one of our new employees. I would like to see a bit more on Beans and even some future moving into plugins and filters. Overall, great tutorial, keep up the great work.

  • I beg to differ with KP's comments too. This is the first tutorial on this subject that hasn't made me want to run away screaming. KP, if you can write up a better one, let's see it.

  • I have to disagree with it being a poorly written tutorial. Any complex methodologies cannot be so easily explained and sometimes its difficult to explain each part unless you don't want to give us any code samples. For what is a FREE tutorial written in the authors own time, I think its an excellent piece of documentation which is far more informative than any problems people may feel it has.

  • Kp, I appreciate feedback. I really do. But I prefer it to be on the constructive side. When feedback is not constructive I'll bite back (not literally - I'm a nice guy :). I think jumping to the conclusion that the lack of documentation is due to Hal and Ben being afraid of losing training income is pretty bold. Do you have any proof that this might be the case, or is this your own conspiracy theory? I'm not a native English speaker/writer. Should that prevent me from contributing to the CF community? I am however happy to receive concrete corrections to spelling and grammatical errors - just throw me an email. Ok - that I don't explain the concept of beans well enough I find valid constructive feedback. The tutorial focuses on the mach-ii framework. I find the configuration xml file to be VERY important in this matter. While a bean is not a mach-ii specific concept, and therefore not focused on explaining either. In future updates to the tutorial I'll include some helpful links to articles and blog posts that explain this and other concepts way better than I can anyway.

  • Yup, I agree that there is too little good documentation on Mach-II - for a reason. The two guys who originated the framework make their money on training. Still, I think it's time for a comprehensive book such as the one written about Fusebox. Unfortunately, the tutorial above continues the tradition of poorly written documentation. Don't get me wrong - I appreciate the effort. But the English is terrible, and the author jumps concepts. For example, why do you spend so much time talking about configuration xml file and then don't explain the concept of Beans?

Advertisement

Sponsored By...
Mobile App Development (IOS, Android, Cordova, Phonegap, Objective-C, Java) - Austin, Texas Mobile Apps - Touch512, LLC.