Getting Started with Cairngorm – Part 5
November 30th, 2007
In Part 4 you saw the full Service to Worker pattern demonstrated. However, the method discussed in the last tutorial doesn't fit every situation. In this tutorial you will learn a few "best-practices" for Cairngorm projects as well as an extension to the Service to Worker pattern for more complex cases.
Delegates, Commands, and Responders
These classes (Delegates, Commands, and Responders) have specific responsibilities. Many developers run into problems when they do not adhere to these responsibilities. The following tips are guidelines for your code.
- Responders - Responders should deal only in strongly-typed application objects. Responders may set values on the model.
- Commands - Commands never deal directly with server interaction. Commands may set values on the model.
- Delegates - Delegates should pass strongly typed strongly-typed application objects to the Responder. If the Delegate doesn't receive strongly-typed application objects, it must parse and convert the data into that format.

Figure 1 - Data Transmission in the Service to Worker Pattern
The goal of this separation of responsibility is that services should be able to be switched out with only a change in the delegate. This may sound a bit unimportant, but if you are working for a large company, the server-side implementation can change drastically from development to production. For this to work properly, the service call will need to have two responders: the Delegate, and the actual Responder. Figure 1 illustrates this separation. The data passed from the service to the delegate can be in virtually any format, but the transfer from the Delegate to the Responder needs to only be application data (VO's, model classes).
In this case, the Delegate now has an added responsibility, parsing the raw data. To accomplish this, you can create a factory class to parse the data. In the sample below the class DeliciousFactory (because it parses data from a Del.icio.us feed) has a method buildPostArrayFromJSON which handles this responsibility.
-
package net.davidtucker.deliciousbrowser.business {
-
-
import com.adobe.cairngorm.business.ServiceLocator;
-
-
import mx.rpc.AsyncToken;
-
import mx.rpc.IResponder;
-
import mx.rpc.events.FaultEvent;
-
import mx.rpc.events.ResultEvent;
-
import net.davidtucker.deliciousbrowser.factories.DeliciousFactory;
-
-
public class PostsDelegate {
-
-
private var responder:IResponder;
-
private var service:Object;
-
-
public function PostsDelegate( responder:IResponder ) {
-
this.responder = responder;
-
this.service = ServiceLocator.getInstance().getHTTPService( "sampleService" );
-
}
-
-
public function getRecentPosts():void {
-
-
// Call the Service and Attach that call to an AsyncToken
-
var token:AsyncToken = service.send(params);
-
-
// Create a Responder for the call
-
var responder:mx.rpc.Responder = new mx.rpc.Responder(onResult, onFault);
-
-
// Add the Responder to the AsyncToken
-
token.addResponder(responder);
-
-
}
-
-
private function onResult( e:ResultEvent ):void {
-
-
// Parse JSON into Array of VO's
-
var posts:Array = DeliciousFactory.buildPostArrayFromJSON( e.result as String );
-
-
// Pass VO Array to Responder
-
responder.result( new ResultEvent( ResultEvent.RESULT, false, true, posts ) );
-
-
}
-
-
private function onFault( e:FaultEvent ):void {
-
...
-
}
-
-
}
-
}
Code Example 1 - A Delegate Parsing Raw Server Data
Parsing the server data is only a part of this extended design pattern. For this to work properly with the traditional Cairngorm flow, the delegate must "intercept" the result of the service call. To accomplish this, you will attach an AsyncToken [Reference] to the service call, create a responder for the call, and then attach the responder to the AsyncToken. This is illustrated in lines 23-30 of Code Example 1.
Now that the delegate has "intercepted" the result of the service call, it need to have methods to parse the data. When you created the responder inside of the delegate (line 27 of Code Example 1), you passed in a result and fault method. In this case it was onResult and onFault. You now need to add these methods to the delegate.
To pass the parsed data to the original responder, you will need to create a new instance of the ResultEvent [Reference] with the parsed data in the result property (line 40 of Code Example 1). This event will be passed as an argument to the original responder's result method.
Setting ModelLocator Values
Within a Cairngorm application, it can be extremely tempting to set values of ModelLocator variables in your events, delegates, or views, but this should be avoided. These values should be set only in the Command Level (see Figure 1) of the application. This means that you can set these values in a Command or Responder. This keeps every class in tune with its true function.
Sequence Commands
Cairngorm also contains a class, SequenceCommand [Reference] that allows the developer to chain command/events together for sequential execution. Initially this may seems like it breaks the framework's rule oft having every command triggered by an event, but it doesn't. Inside of a SequenceCommand you define the nextEvent property (which is an instance of a CairngormEvent). This event is executed when the executeNextCommand method is called. This is the most effective way to attach multiple commands to a single user gesture.
-
public class SampleSequenceCommand extends SequenceCommand implements ICommand, IResponder {
-
-
public function SampleSequenceCommand() {
-
this.nextEvent = new GetPostsEvent();
-
}
-
-
override public function execute( e:CairngormEvent ):void {
-
...
-
}
-
-
public function result( event:Object ):void {
-
this.executeNextCommand();
-
}
-
-
public function fault( event:Object):void {
-
...
-
}
-
-
}
NOTE: The SequenceCommand class assumes that you are not separating your Command and Responder. You could easily extend the architecture and create a SequenceResponder class to achieve the same effect.
ViewHelper and ViewLocator Classes
Many people have inquired about the ViewHelper [Reference] and ViewLocator [Reference] classes. Both of these classes are now deprecated as of Cairngorm 2.1, and it is considered bad practice to use either of these classes in a new Cairngorm project. Should you be working with an existing project that still uses these classes, I would recommend refactoring your code to meet Cairngorm 2.2 standards.
Summary of Tips
- Don't use ViewHelpers and ViewLocators
- Only set ModelLocator variables in the Command Level (Command or Responder).
- SequenceCommand can be used to chain multiple commands to a single user gesture.
- Delegates deal in raw service data (which could be application data), but Responders only deal in strongly-typed application data.
- Commands do not directly communicate with services.
Application Code
Beginning Code Download (9 Kb)
Finished Code Download (12 Kb)
References
AS3CoreLib
Looking Ahead
In the next (and final) tutorial on Cairngorm, you will learn tips to make your Cairngorm development go faster as well as learning more "best practices" for Cairngorm development.





30 comments on “Getting Started with Cairngorm – Part 5”
01
Thanks for this tutorial David!
I’ve learned Cairngorm with this serie and I really thank you for that.
A question though : I have a component with many states. Let’s say a contact detail with 2 buttons (edit,remove). When I click on a button, the component’s state should change. Also, the currentState property depends on the detailContactState variable in the ModelLocator.
So, my question is: when I click on a button, may I change the currentState directly in my view or should I dispatch a new event to a command that will change the detailContactState?
02
same question ,change the model from views directly is ok?
03
@PeZ,@Nshen - In the last tutorial I will cover “multi-layered” views (which will partially address this issue). However, in these situations you must ask yourself - “Is the change of state in a component completely self-contained?”. If the user gesture is within the component and the change of state doesn’t affect the application model, the ModelLocator doesn’t even need to me involved in this - the component can store and change its own state.
However, if the view component relies on other components for user gestures or relies on application model data for it’s internal state, then you need to dispatch a Cairngorm event.
You obviously can break these rules, but you will end up with components that are not “loosely-coupled”.
04
Great Tutorials David!
This series has really helped me wrap my head around Cairngorm.
Looking forward to the next part!
05
[...] Part 5 [...]
06
Great job David, been following and its helping me a whole lot! Its been hard understanding these concepts but everything is soo clear now. Thanks. i hope you keep this up
K
07
[...] http://www.davidtucker.net/2007/11/30/getting-started-with-cairngorm-%e2%80%93-part-5/ [...]
08
Again, Great tutorial..
Just one question. What is the real purpose of the AsyncToken?
Thanks
09
I see the Language Reference said “The token that represents the indiviudal call to the method. Used in the asynchronous completion token pattern.”
a design pattern?
10
Well done David. I have been looking at Cairngorm for about 10 months now coming from mainly a php background. I read and googled heaps but could not find enough of the right info to have a go. Seeing your series of articles has given me the confidence to get my feet wet. Thanks mate …. look forward to the next movie.
11
Thx David
This tutorial was the most useful documentation in this topic. I’ve been searching for the right description since the company here decided to move this way from classic Java MVCs. You seem to be the only one who really wants to explain instead of just talking about.
12
Hey David
Thanks a lot for this great Cairngorm tutorials serie.
Just one question. I followed another tutorial where the author was using code-behind and separating the AS3 from the mxml. What do you think of this ?
13
It is certainly a personal preference. Some people hate MXML and ActionScript in the same file. I have no problem with it - and I also think that it leads to better project organization and less files.
14
Great tutorials. They have really helping me learn Cairngorm. I’m looking forward to reading the last tutorial in the series.
15
Great tutorial!
What do you suggest for a good structure with ServiceLocator and NetConnection?
16
Hey David, great series… I love it.. I finally have an idea aout cairngorm. Adobe article got me really confused. but in this part you said that you gonna covert “next week” cairngorm code generation.. what about that? thanks in advance.. keep on this way great work thanks for all
17
Hi David, excellent tutorials that I am working through and learning a lot.
I am facing a problem with the SequenceCommand - the executeNextCommand() is firing before the initial command has completed. I need it to fire after so it can use the data generated by the first command (loading external XML). I think I need to not use a responder and put the this.executeNextCommand(); in the result function rather than at the end of execute but I am not sure how to do it and get it called when the delegate returns. Not sure if that makes sense
18
Solved it by passing ‘this’ to the delegate from my command instead of a responder like this: var delegate:MyDelegate = new MyDelegate( this );
Thanks again for the tutorials.
19
This is such good stuff. Question .. sticking to a standard. If the data returning from the backend is e.g. an Oracle refcursor (single array) - do you advise still building a “single var” ColdFusion VO with matching ActionScript VO to move this data into e.g. a Flex datagrid. This app is for corporate reporting and there are dozens of Oracle procs that return data as a single “report list”. Should I be consistent and match each one of these proc calls with matching VOS to hold the “single var”?
Thanks, Mic.
20
David -
This is the only place I’ve seen such a good explanation of a more complex use of the Business Delegate’s purpose. Specifically using the delegate to hide the details of turning service results into application models which are actually usable by the commands.
This pattern is not understood by most people working with cairngorm yet… there is still much confusion so thanks for the clear explanation.
21
Hi David..
I have seen your videos..they are amazing and helped me a lot in understanding Cairngorm framework.
I have recently downloaded the samples from this page. I tried compiling them it is giving me error that “1045: Interface IModelLocator was not found.” I can understand that “IModelLocator” is renamed to “ModelLocator” in Cairngorm 2.2(latest). But I can not rename the interface as it will be same as the class name.
I have tried renaming it even. But it seems not working..I am trying out that, just but thought of informing you. It would be nice if you can tell me or update the examples.
thanks and regards
rconceiver
22
hey david..
it is solved..
actually IModelLocator is deprecated from the latest release.
thanks any ways…
but still if you want I can send you the modified build..
Thanks and regards,
rconceiver
23
Actually in Cairngorm 2.2 the ModelLocator Interface was deprecated and renamed to IModelLocator. You can check out the release notes here:
http://labs.adobe.com/wiki/index.php/Cairngorm:Cairngorm2.2:Release_Notes
Let me know if you have any more problems.
24
Hey Davaid,
This was AMAZING, I was wondering if I could call an XML file in Services.mxml and work with delegate file properly. Is that possible?
I would like to see the series 5 extend version
Thank You
25
@min - Do you mean a call through an HTTPService? Can you explain your situation a little more?
Thanks
26
great stuff… thank you for such good tutorials…
27
Great Work! In your next tutorial could you cover using SetCredentials(), it seems to be an aspect of Cairngorm no-one is mentioning. I’m trying to use WebORB.NET, but it could equally be Flourine or AMFPHP, I just can’t work out when and where to make the SetCredentials call.
Many thanks,
Matt
28
Very interesting series of videos - thank you.
I have a general Cairngorm question. Lets say you were building an application in Flex which was similar to the Flash CS 3 IDE or Eclipse, in that it contained multiple panels or views which could be opened and closed, and moved around to suit the person using it. Lets say one of these panels contained a Flickr image viewer, another panel contained a delicious post viewer, and a third loaded in stock prices. These three panels are all self-contained, fully functional components which do a particular job, and in an ideal world these could be reused in entirely different projects.
Within the scope of this project, the three panels can all be controlled by some fourth panel containing just a search box, and typing in Yahoo and pressing “Go” would make the Flickr image viewer load in images tagged with “Yahoo”, would make the delicious post viewer show posts tagged with “Yahoo”, and the stock price viewer would show the latest price of the appropriate shares. Or whatever.
I’m wondering how this would be structured in a Cairngorm project. I’m new to Flex, so my terminology is most likely completely wrong, but ideally to me I would have four different FrontControllers, one for Flickr, one for Delicious, one for Stocks, and one for the app. To accomplish this, would the Flickr viewer (for example) be a separate project entirely, and then somehow brought in to the main application as a component?
I can’t really explain what I mean, most likely because I’m lacking a little knowledge on how things all fit together in Flex as a whole, but I’d be very interested to read your (or anyone’s opinion) on how something like this would be tackled.
Thanks again for the videos!
29
Great tutorials David, I learned a lot from going through them but am stuck on one thing: howto use LocalConnection inside Cairngorm.
I don’t mean how to make LocalConnection work because that is easy enough from the docs. I need to use an AS2 swf within a Flex app so LocalConnection is required but where should it be placed within the Cairngorm structure ?
Drawing a blank here so any tips would be useful.
30
Great series. Thanks for putting these together as they have helped me immensely. Any idea when Part 6 will be available?
BTW, I also enjoy your tutorials on Lynda.com. Any thoughts as to making these types of tutorials (Design Patterns, etc) available on Lynda.com as well?
Thank you!
Leave a Reply