Getting Started with Cairngorm – Part 3
October 29th, 2007
Now that you have isolated two specific elements of the Cairngorm Micro-Architecture, you will now create a more complete Cairngorm application. Up to now the tutorials have covered only one design pattern, the ModelLocator, but now you will be introduced to the most crucial element of Cairngorm, the Service to Worker design pattern. The explanation of this pattern will span two tutorials. This tutorial will cover the basic flow inside of a Cairngorm application, and the next tutorial will expand this flow to include server interaction. However, before you can properly implement this design pattern you need to learn about the organization of a Cairngorm project.
Organizing a Cairngorm Project
One of the tasks involved with any project is organization. When working with other developers, this becomes extremely important. Normally a Cairngorm project is organized in the following manner:
- There is a Main.mxml file that is the main application file for the Cairngorm application.
- The project files are contained in a folder that uses "reverse-dns" format. For example, if the project was named CairngormSample, I would use the following folders net/davidtucker/CairngormSample .
- Within the CairngormSample directory, there will be the following folders (there will be additional folders added in the next tutorial).
- events/ - This directory holds all of the custom events for the application
- control/ - This directory houses the FrontController for the application
- commands/ - This directory contains the Commands that are called by the FrontController
- model/ - The ModelLocator is contained in this folder (and other classes related to the model)
- view/ - The components of the view are contained in this directory
By following this standard, you can know where to find any class that you may need in your Cairngorm application. Figure 1 illustrates this project structure. It also is a good development process to have a standard organizational structure for your projects - even if you are not using Cairngorm.

Figure 1 - Cairngorm Project Structure
The Service to Worker Pattern
The Service to Worker pattern is the hardest for most people to grasp. It encompasses most of the logic for a Cairngorm application. To understand this pattern, you will need to understand some of the classes that are included with Cairngorm and their respective purposes.
- CairngormEvent [Reference] - CairngormEvent is central in this pattern. It extends from Event. For your event to be handled properly in Cairngorm, it will need to be of type CairngormEvent.
- CairngormEventDispatcher [Reference] - CairngormEventDispatcher actually dispatches the CairngormEvents. It is a singleton (just like the ModelLocator). In previous Cairngorm versions, you would call this class regularly, but now CairngormEvents can dispatch themselves (via the method dispatch). This method is simply a wrapper for the CairngormEventDispatcher, so even if you don't actually import and call the class, it is still central to the Service to Worker pattern in Cairngorm.
- FrontController [Reference] - The FrontController maps a CairngormEvent to a Command.
- ICommand [Reference] - For a Command to function properly in Cairngorm, it needs to implement the ICommand interface. This interface requires that a command have a method named execute and that it accept the CairngormEvent that is mapped to it as an argument.
The Cairngorm Event Flow
The way that these classes interact is the Cairngorm Event Flow. Figure 2 illustrates this entire process. While this process seems lengthy, it follows a logical order.

Figure 2 - Cairngorm Basic Event Flow
For example, assume that Figure 2 shows what happens when a user clicks a login button. It would follow the following steps:
- The user is viewing a component that has a login button.
- When the button is clicked, that component would dispatch an event named LoginEvent that extends CairngormEvent.
- The FrontController would receive the LoginEvent and execute the command that is mapped to that event. For this example, it will be named LoginCommand and will implement ICommand.
- The Command is executed and received the LoginEvent as an argument. The LoginCommand will change the workflowState value in the ModelLocator.
- The ModelLocator will have a predefined constant for the "Logged in View". The command will change workflowState to this value.
- Since the view is bound to workflowState, it will automatically update itself to the new view.
Once these items are understood, the next most important thing to understand about Cairngorm is: Everything Should Be Mapped to an Event. This is a drastic over-simplification, but it holds true in most situations. When a user clicks a login button - it should dispatch a CairngormEvent. When the user selects an option to change the view - it should dispatch a CairngormEvent. When a user submits a form to be stored on in a database - the form should dispatch a CairngormEvent. The dispatching of a CairngormEvent sets everything in motion.
Custom CairngormEvents
The class CairngormEvent can be used inside of your project, but in most situations you will create your own custom events that extend CairngormEvent (as stated previously, for an event to be included in the Cairngorm Event Flow it should extend CairngormEvent). Another reason to create custom events it to create custom properties of the event which contain data that you need to pass to the command. CairngormEvent has a property named data (of type Object) that can contain data, but it is ideal to have a strongly-typed property where you can place the data to pass.
For this example you will create an event that corresponds to the earlier example of a login page. This event will need to meet the following criteria:
- Extend CairngormEvent
- Have a property for the username
- Have a property for the password
Code Example 1 illustrates this completed event. You can see that you will need to import both CairngormEvent and the basic Event class. Also, as with all events, you have to define the Event constant. In this instance, you can use LOGIN. The properties are defined below the constant - and they also are passed into the constructor. The only thing out of the ordinary is that you need to override the public method clone(). This is the the method that the event uses to make a copy of itself. This is key in the Cairngorm Event Flow. Also, for the function to implement ICommand this method will need to have a return type of Event (and not CairngormEvent).
-
package net.davidtucker.CairngormSample.events {
-
-
import com.adobe.cairngorm.control.CairngormEvent;
-
import flash.events.Event;
-
-
public class LoginEvent extends CairngormEvent {
-
-
public static const LOGIN:String = "Login";
-
-
public var username:String;
-
public var password:String;
-
-
public function LoginEvent(submittedUsername:String,submittedPassword:String) {
-
username = submittedUsername;
-
password = submittedPassword;
-
super(LOGIN);
-
}
-
-
override public function clone():Event {
-
return new LoginEvent(username,password);
-
}
-
-
}
-
}
Code Example 1 - Custom Event
Commands
The Commands within a Cairngorm application actually "command" the application. Even in the next tutorial where you will be interacting with a server, the command still will do a majority of the work. In this example you will create a component that will receive the username and password from the LoginEvent, check the values against hard-coded values, and then change the workflowState on the ModelLocator if the values are correct. The following example performs these steps (but it doesn't have the hard-coded values included - that will be covered in the video).
The first thing to notice about the code below in Code Example 2 is that the LoginCommand implements ICommand. To accomplish this the ICommand class is also imported. In addition, you will notice the boilerplate code that you have used in the past to bring in the ModelLocator. To properly implement ICommand, the method execute() is also created. It received an event of type CairngormEvent (it has to be CairngormEvent and not LoginEvent to properly implement ICommand). To properly use the event, you will need to cast this event to the type LoginEvent (the process of casting will be further explained in the video). The actual logic has been left out of this command, but you can see that the ModelLocator updates the view. Once the logic is implemented this line of code would probably be inside of an if statement.
-
package net.davidtucker.CairngormSample.commands {
-
-
import com.adobe.cairngorm.commands.ICommand;
-
import com.adobe.cairngorm.control.CairngormEvent;
-
import net.davidtucker.CairngormSample.events.LoginEvent;
-
import net.davidtucker.CairngormSample.model.ViewModelLocator;
-
-
public class LoginCommand implements ICommand {
-
-
public var modelLocator:ViewModelLocator = ViewModelLocator.getInstance();
-
-
public function LoginCommand() {
-
}
-
-
public function execute(event:CairngormEvent):void {
-
-
var loginEvent:LoginEvent = event as LoginEvent;
-
-
// COMMAND LOGIC
-
-
modelLocator.workflowState = ViewModelLocator.WELCOME_SCREEN;
-
-
}
-
}
-
}
Code Example 2 - Cairngorm Command
Front Controller
As stated earlier, the FrontController maps your CairngormEvents to specific commands. Without this, your events would never integrate into the Cairngorm flow. The class extends FrontController and has two methods: the constructor and the initialize method. The initialize method is where you will use the addCommand method to map your events to commands (as you can see with the LoginEvent and LoginCommand).
-
package net.davidtucker.CairngormSample.control {
-
-
import com.adobe.cairngorm.control.FrontController;
-
-
import net.davidtucker.CairngormSample.commands.*;
-
import net.davidtucker.CairngormSample.events.*;
-
-
public class SampleController extends FrontController {
-
-
public function SampleController() {
-
this.initialize();
-
}
-
-
public function initialize():void {
-
-
//ADD COMMANDS
-
this.addCommand(LoginEvent.LOGIN,LoginCommand);
-
-
}
-
-
}
-
}
Code Example 3 - The Cairngorm FrontController
Simply creating a FrontController is not enough. Like any class it needs to be instantiated inside of your application. Code Example 4 illustrates how to instantiate your FrontController in the Main.mxml file of your application. You simply need to add the control directory as an XML Namespace and then include the FrontController tag in the file.
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
-
xmlns:control="net.davidtucker.CairngormSample.control.*"
-
layout="absolute">
-
-
<control:FrontController id="controller" />
-
-
</mx:Application>
Code Example 4 - Integrating a FrontController
Now that you have seen the basic elements of a Cairngorm project, you can actually build the working sample with the video. As always, the application code is included below.
Application Code
Download (7 Kb)
Looking Ahead
This is the basic Cairngorm flow. You may notice that this flow really does not include any "Services" yet. Server interaction will introduce a few additional steps to the flow (which will be covered in depth in the next tutorial).





27 comments on “Getting Started with Cairngorm – Part 3”
01
Hi David,
In code sample #1, I’d recommend putting the additional properties inside the “data” object which is defined in ICommand:execute() [http://www.davidtucker.net/docs/cairngorm/com/adobe/cairngorm/control/CairngormEvent.html#data]
Also, it might be better practice to pass in a loginVO to the LoginEvent() constructor rather than individual properties. The idea being that the loginVO would get sent to the back-end service.
Excellent articles. Looking forward to the next one!
02
It should go in a VO, but I didn’t want to dive into VO’s until the next tutorial (this tutorial ended up being a bit longer than originally intended). In the next tutorial, I will cover VO’s and the ServiceLocator.
03
Thanks again for great tutorial!
04
Just perfect! Thanks
05
Excellent. Thanks a million for these tuts, very helpful! When is part 4 coming?
06
I estimate that Part 4 will be published this weekend. I wish I could have it done sooner, but I try to be sure they are as thorough and error free as possible.
07
These tutorials are fantastic David, they are helping me dig into Flex more than anything else I’ve been able to find out there so far, keep ‘em coming!
08
It is very helpful for me .Hope to see next one soon.Thanks.
09
[...] basic Cairngorm Event Flow that is handled in Part 3 is essential to any Cairngorm application, but most applications interact with a server. The [...]
10
David,
While I was waiting for part 3 I looked into PureMVC as well. Seems to be a lot of similar concepts between the two frameworks. PureMVC has a lot of talk around it right now - any experience or insight into how it compares to Cairngorm? Cairngorm is backed by Adobe, but PureMVC seems to be a little bit more straight forward and a little easier to grasp. Again, finding your tuturials the best material on Cairngorm yet.
11
@Flex New Guy - PureMVC is certainly getting a lot of buzz. I have briefly looked into it, and I am still evaluating it for enterprise-level solutions.
I do have one note though - if you are a professional Flex developer, you need to know Cairngorm. It was the framework that Adobe supported, so many companies still rely on Cairngorm (and will continue to - even if “easier” frameworks come along).
12
[...] Part 3 [...]
13
[...] http://www.davidtucker.net/2007/10/29/cairngorm-part-3/ [...]
14
thank very much
15
Thanks
16
[...] Tradução do original inglês: http://www.davidtucker.net [...]
17
This is completley irrelevant, but I really wish this was named something other than “Cairngorm”. What a lousy name. Not slick, doesn’t roll off the toungue, and just conjurs up a picture of something completely hopeless, much like a hurricane hitting the Gulf coast.
18
Thanks for taking the time to do these tutorials. Some things are finally starting to “click” regarding Cairngorm.
19
Great tutorial… however as soon as I instantiate the controller in the program, either the way you do or with AS3, the application fails to build silently. very puzzling! I’m using latest SDK with FlashDevelop, same problem with Flex builder 3. The code is downloaded from this page. Please help me!
20
Excellent tutorials !
I read several articles to understant “Service to Worker” pattern,
this article helped me a lot understand it!
Thank’s again !!!
21
[...] David Tucker - Web Development Goodness » Blog Archive » Getting Started with Cairngorm – Part 3 Looking for some examples of how people break up flex directory structure (tags: cairngorm flex) [...]
22
great tut thanks
23
Great tutorial, thank you so much.
I was wondering how to structure my cairngorm directories for things I resuse in multiple applications, such as the login/logout screens.
Thanks,
Shannon
24
very thanks
25
public class SampleController extends FrontController {
public function SampleController() {
this.initialize();
}
public function initialize():void {
//ADD COMMANDS
this.addCommand(LoginEvent.LOGIN,LoginCommand);
}
}
}
according to your codes of LoginEvent class,LoginEvent.LOGIN==”Login” which is a String value.
so we can see that code “this.addCommand(LoginEvent.LOGIN,LoginCommand)” just map the LoginCommand to a String value,rather than an event.
it confused me.
26
[...] Tucker :: Getting Started With Cairngorm :: Part 1 :: Part 2 :: Part 3 :: Part 4 :: Part [...]
27
Excellent.:):)
Leave a Reply