Netflix API with Cairngorm
I know that many developers have their own preference when it comes to frameworks, so I thought I would show some examples in each of the main frameworks. I am going to start with Cairngorm as it is probably one of the most widely used frameworks.
Cairngorm is actually fairly simple though you wouldn’t know that by looking at the Cairngorm docs. I’ve seen those docs confuse more people, so I am going to try to simplify it right here. Cairngorm breaks down to the process of an event, calling a command. That’s it, forget everything else. Events calling commands. Now everything else is just making this process work within your application.
Do you always have to use a delegate? Nope, unless you have a service you are calling then it is recommended you use delegates, but even then it isn’t required.
Does your command need to implement the IResponder and have result and fault methods? Nope, unless you have a service you are calling, then you need to have the result and fault event to handle the service response.
Do you have to use models? Nope, though it is recommended, but you can work with the Cairngorm framework without creating models.
Does EVERY gesture have to lead to a CairngormEvent and a Command? Nope, mainly just events that need to go to a service or go outside of your component’s scope. Everything else can be handled within your component, no need to use Cairngorm within a component.
Now what about the ModelLocator? That is a place to hold models that would be accessed from all over the application. So DON’T do what many programmers do, don’t store ALL of your data in the ModelLocator. Just store those models and bits of data that are needed all over the application.
In the following example we will start up a Flex application with Cairngorm, go through the authorization process, and run the autocomplete service. Nothing huge, but a good starting point.
The View
When I am setting up my Cairngorm based application the first thing I take care of is the view. It’s not really a necessity and will change over time, but it is nice to get something going visually so that you can hit a button and run your services. For this little test app I’m just going to throw together a pretty simple view to resemble something as such:
The whole idea of this app is to authenticate as much is necessary to run the autocomplete service call and get back a response. Easy Easy.
Events and Commands
Once I have the view at a point that makes me happy, I am ready to work on events and commands. These come in sets – DON’T FORGET THAT. Equally as important is the naming of these event/command pairs, I recommend BEING LAZY about your naming. Did you name the event: AutocompleteServiceEvent? Then name the command: AutocompleteServiceCommand. This makes it easier later to see which event is paired with which command, no reason to get fancy here.
Setting up the event
ALL EVENTS THAT WILL GO INTO THE CAIRNGORM PROCESS MUST EXTEND THE CAIRNGORM EVENT! This is the class setup that you will need on your event:
When planning your event, simply determine what information is necessary for the command to have to complete it’s job. In the case of the Autocomplete Service all we need is a term, so that is the variable that we will add to the event. When setting up a variable in an event I prefer to pass the variable in the constructor and protect the variable so it can only be accessed via a getter later on, no setters. Why? Because I don’t want my variable to change later on as it is fired through my application.
The final thing that I set up is a static constant to hold the name of the event. This isn’t necessary, but this reduces the chance for a spelling mistake to take down your entire application.
With your variables determined, and your event named, our final event looks as such:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | package com.unitedmindset.events { import com.adobe.cairngorm.control.CairngormEvent; public class AutocompleteEvent extends CairngormEvent { public static const AUTOCOMPLETE:String = "autocomplete"; private var _term:String; public function get term():String { return _term; } public function AutocompleteEvent(term:String) { super(AUTOCOMPLETE); _term = term; } } } |
Your Command
Once you have the event taken care of you need to make your command. First ask, “is this event going to handle a service call?” If yes, then you need to include the IResponder interface, if not, don’t include it. Easy. In our case the command will handle a service call so we will include the IReponder interface. We will also need to include the Cairngorm Command interface – which just provides access to the “execute” method. Finally, we don’t need the constructor though you can leave it if you like. Our class setup looks as such:
Which will produce the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package com.unitedmindset.commands { import com.adobe.cairngorm.commands.Command; import com.adobe.cairngorm.control.CairngormEvent; import mx.rpc.IResponder; public class AutocompleteCommand implements Command, IResponder { public function execute(event:CairngormEvent):void { } public function result(data:Object):void { } public function fault(info:Object):void { } } } |
There are a couple of steps that you will have to follow for each command. First we need to get the Cairngorm Event that is coming into our execute method and type the event to our custom event. This type change allows us to use a typed object for compiler validation and allows us to use our code hinting on the event. Since we determined this command will run a service call we would normally need to include the delegate to call the service and attach our responder. But for this case we will just keep things cut down and add the result/fault event listeners. Also, the API doesn’t allow for addResponder() support, so we are skipping the delegate.
A delegate is simply a place to put your service calls so that they are easily accessible. I like to group my service calls by the endpoint. I will go more into the delegate settings shortly.
Now with our event typed properly, we can send the variables from the event to the service call. Once the service call has been made, what is the command going to do when it gets back? That is what we need to handle now in the result and fault event handlers. In this example I will place the autocomplete results in the ModelLocator and use binding in the ModelLocator to place them back in the view, your app may require something differently but for this example this works perfectly. If there is a fault, I will show an Alert to the user. Very simple.
Our final command looks as such:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | package com.unitedmindset.commands { import com.adobe.cairngorm.commands.Command; import com.adobe.cairngorm.control.CairngormEvent; import com.netflix.webapis.catalog.TitlesService; import com.netflix.webapis.catalog.params.CatalogParams; import com.netflix.webapis.events.NetflixFaultEvent; import com.netflix.webapis.events.NetflixResultEvent; import com.unitedmindset.events.AutocompleteEvent; import com.unitedmindset.model.ModelLocator; import mx.collections.ArrayCollection; import mx.controls.Alert; import mx.rpc.IResponder; public class AutocompleteCommand implements Command, IResponder { public function execute(event:CairngormEvent):void { var delegate:TitlesService = new TitlesService(); var e:AutocompleteEvent = event as AutocompleteEvent; var params:CatalogParams = new CatalogParams(); params.term = e.term; delegate.addEventListener(NetflixResultEvent.RESULT,result); delegate.addEventListener(NetflixFaultEvent.FAULT,fault); delegate.autoCompleteService(params); } public function result(data:Object):void { var result:NetflixResultEvent = data as NetflixResultEvent; ModelLocator.getInstance().autoCompleteCollection = new ArrayCollection(result.result as Array); } public function fault(info:Object):void { var fault:NetflixFaultEvent = info as NetflixFaultEvent; Alert.show("Error occured while calling for autocomplete service.","System Alert"); } } } |
Side Note: The Delegate
Typically the delegate is a perfect place to reflect the services that your application can access. In this case we didn’t use the Delegate but typically you send the delegate a reference of the command for the service to respond to. The delegate will handle calling the service and return the response (either result/fault) back to the referenced command.
The glue that binds: The Front Controller
Once you have the Event and Command set up you can actually bind the two together via the Front Controller. Your Front Controller will typically be a very simple map of events to commands. This way when you send a CairngormEvent out via the CairngormEventDispatcher, the Front Controller maps that event to the proper command and the command’s execute function is called. Again, EASY! This process of calling the execute function is also called the command design pattern.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.unitedmindset.control { import com.adobe.cairngorm.control.FrontController; import com.unitedmindset.commands.AutocompleteCommand; import com.unitedmindset.events.AutocompleteEvent; public class NetflixController extends FrontController { public function NetflixController() { super(); _initializeCommands(); } private function _initializeCommands():void { addCommand(AutocompleteEvent.AUTOCOMPLETE,AutocompleteCommand); } } } |
Wrapping it up
That’s it. The View now sends of the User Gesture, which creates a Cairngorm Event, that is mapped through the Front Controller to the Command. The Command makes a service call and receives back the response from the service. With that result the Command updates the model, in this case, the ModelLocator and through binding the View is updated.
Everything from this point on is just repetition of this same structure.
This is the final Cairngorm Example and the source.
I couldn’t leave the application the way it was for long, because I feel that using models is better than not using models. I refactored just a touch and put the data within models.
This is the final Cairngorm Example using models (better practice) and the source.








Thank you. This is really helpful.
I would enjoy seeing your take on the PureMVC version of the same application. I appreciate your lucid explanation of the Cairngorm framework. I just recently figured out cairngen and that has been great for giving me a starting point code wise, however, I really appreciate the warnings about including all data in the model as that’s precisely what it seems like you should do based on the docs and many examples that are given. And again, about being selective for what gestures get promoted to the status of event when coding. The docs are great at telling someone what they can do, but not so much on what they probably shouldn’t do.
I find myself wondering if the reason fireclay and mate have come about is because of the over use of events. I know there is a tendency to treat these application frameworks like Flex and Java as a blackbox, but as a traditional C coder who has to deal with memory allocation and pointers…there are of course have to be limits. As a suggestion for a future D-Flex meeting some (me) might find it helpful to know what are the tipping points for these frameworks.
Again, I really appreciate the time you put into these blog entries.
I am already in the works on the PureMVC post and will be getting it up as soon as I am back from vacation. I like the idea of testing the tipping points of these frameworks. Would this be something you would like to work on together?
I’m game for that. As an outsider looking in, my gut feel is that EventMaps, Business delegates, Event Buses (via publish/subscribe w/ queuing), etc. solves the same problem but with respective biases and prejudices. With Cairngorm and the business delegates, I think there is more of a chance to incorporate event buses, proxies, queuing, and subscribing without polluting the view. On the view side, it comes down to property injectors, data binding, and mediating, right? Now that I think about it, is there something tangible and measurable to go after or just instinctual frameworks to pick and consequences to suffer for making one part easier than the other. I hate to say it, because I value options, but Adobe is far more likely to optimize data binding in the player and/or adding queued/deferred/more intelligent binding perhaps so any framework that relies on binding has an advantage at least as good as the binding implementation is at that point, and that would make Cairngorm a long term candidate. Neat on the PureMVC example, again, much appreciated. Have a good vacation. Also, where would you think to begin?
Never mind my last. I’m an idiot. Of course. I just read that data binding is doing implicit events and listeners and it should be very obvious considering you can explicitly name an event. So, it’s all back to events and it looks like it’s a difference of events add/hold the bubbling. So Mate v. Everyone Else…then everyone else amongst themselves. PureMVC v Cairngorm v. etc