As Flex continues to grow as the choice RIA technology, many developers start investigating and apply Java design patterns to Flex implementations. Similar to Java Struts, Cairngorm is a MVC (Model-View-Controller) framework – endorsed by Adobe – that is widely popular within the community.
One of issues that frequently confuses, blocks, or complicates Cairngorm implementations is the issue of “view notifications”. Every Cairngorm developer ask the following question at some point: How should the Cairngorm business layer best communicate with the Presentation layer?
Review Figure 1 which illustrates the recommended relationships between the view and control layers[1]:

Commands are supposed to use the Model layer as the mediator between business and presentation layers. In Flex, data bindings and change watchers allow views to watch data models. When data is modified, hidden propertyChange events are dispatched from Models to Views and the View uses event listeners to self-update. This is the basic premise of the Flex Cairngorm MVC framework.
In real-world applications, data binding solutions espoused by Cairngorm MVC are not always sufficient; since such solutions require views to watch for data changes. Some times, however, watching for data changes is complicated… perhaps the data is not globally available. Sometimes the view [that dispatches the business event] is requesting data that should be available only to that specific instance of the calling view; and should not be stored in global repositories. Sometimes, we do not care so much about the data… but instead we want to execute custom code when the event succeeds and finishes.
PureMVC and traditional Cairngorm solutions require complex code and design patterns to solve these situations.
The above approaches create a proliferation of view controllers and is useful ONLY when multiple views want to listen to the same event and be notified simultaneously. Please note that in such rare situtations, a custom event-bridge or a traditional data binding approach would be more practical [but that is another article]. In fact, in most scenarios, the view simply wants the notification directly and exclusively (only to its instance). For these situations, there is a simpler – and better – solution to the ViewController complexity.
The remarkably easy solution is to use Responders as notification mechanisms to allow Commands to notify Views… just like the way Delegates notify Commands [See Cairngorm Secret Tip #2: Data Transformations within Delegates]. To understand the proposed solution, consider the Cairngorm approach where a Command instance employs a Delegate class as “API facade” to remote data services.
The command instance submits itself [or a proxy to itself] as a responder to the delegate. The delegate, in turn, simply uses the specified responder to direct dataservice responses directly to back to the command. This allows the Command to receive callbacks from the Delegate or the Server. In fact, advance this same approach is used at the Delegate level to allow Delegate instances to intercept server responses, transform data, and then notify/pass the modified data back to the Command.
Using Responders, a Command can submit itself as a callback to specific Delegate calls. Views can effectively do the same with Commands. Figure 2 below illustrates this process or queueing of responses. The queue builds with (1) View waits for a response from the Command, (2) the Commands waits on the Delegate, and (3) the Delegate waits on the Server. The queue unwinds after (4) the server responds, (5) Delegate notifies the command, (6) the Command notifies the view[2]. Using a Responder proxy, the view is notified after the actual dataservice request/response and after Command processing; see Step (6) in Figure 2.

Well, when we dispatch business events to commands, we create custom events. So we simply need to transport a Responder instance along with the normal event information that is dispatched to the Cairngorm control layer. If all custom events have constructors with optional responder arguments then we have a built-in mechanism to support callbacks from Commands.
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 mx.rpc { /** * This interface provides the contract for any service * that needs to respond to remote or asynchronous calls. */ public interface IResponder { /** * This method is called by a service when the return value * has been received. * While <code>data</code> is typed as Object, it is often * (but not always) an mx.rpc.events.ResultEvent. */ function result(data:Object):void; /** * This method is called by a service when an error has been received. * While <code>info</code> is typed as Object it is often * (but not always) an mx.rpc.events.FaultEvent. */ function fault(info:Object):void; } } |
package com.grdlinked.samples.control.events { import flash.events.Event; import mx.rpc.IResponder; import com.universalmind.cairngorm.events.UMEvent; public class LoadUserDetails extends UMEvent { public static var EVENT_ID : String = "loadUserDetailsBySSN"; public var ssn : String = ""; public var password : String = ""; public function ApplicationInitializeEvent( ssn:String, password:String, callbacks:IResponder=null) { super(EVENT_ID, callbacks, true, false); this.ssn = ssn; this.password = password; } } }
For the examples in the post, we use a custom event
When the event is processed by the command, the command can temporarily cache the view responder or callback. Sometime later – after the asynchronous data service call responds – the following can happen:
If your views want to implement the IResponder interface, each one of your views would need to include public result() and fault() functions:
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 | <?xml version="1.0" encoding="utf-8"?> <mx:Canvas width="400" height="300" implements="mx.rpc.IResponder" xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:Script> <![CDATA[ import mx.rpc.IResponder; import mx.controls.Alert; // Methods required by the IResponder interface public function result(data:Object):void { btnLoad.enabled = true; } public function fault(data:Object):void { Alert.show(event.message); btnLoad.enabled = true; } // Private methods invoked by child controls private function loadUserDetails(ssn:String):void { btnLoad.enabled = false; // disable button while waiting for a response. // Load the user details for the specified user //NOTE how this view will be the responder... var callbacks : IResponder = this as IResponder; var event : LoadUserDetailsEvent = new LoadUserDetailsEvent("435-34-1283", "anonymous", callbacks); event.dispatchEvent( ); // Cairngorm events self-dispatch directly to the business layer; } ]]> </mx:Script> <mx:Button id="btnLoad" label="Load User" textAlign="center" x="145" y="149" click="loadUserDetails()" width="147"/> </mx:Canvas> |
In our example the view needs to know when the results are available; since the load button is disabled until the business layer [and server] responds [3].
The above code sample shows, unfortunately, how each of your custom views would need to be modified to work as view responders. When the command finishes, it would call something like caller.result(). Unfortunately, the signature of the result() function is ambiguous and does not document which event triggered the result. In contrast a method like onResult_loadUserDetails() explicit documents its purpose.
After a thorough slapping, ask that developer this question:
“What if I had two buttons that each dispatched separate business events and each needed separate response handlers? How could the result() function be the common event handler for both events? Would I have to somehow detect – inside the result() method – which event is responding?”
As you can see, this solution rapidly creates nasty code and rapidly produces nasty, convoluted, unmanageable code.
So instead of requiring an abomination of view interfaces or view inheritance (which is even worse), the view will instead create an instance of a Responder class that will serve as a proxy responder class. The Responder class will redirect result() and fault() calls to methods that we specify. [4] Let us look at some code for clarity. Below we see an example of custom view component created to load and display user details.
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <?xml version="1.0" encoding="utf-8"?> <mx:Canvas width="400" height="300" xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:Script> <![CDATA[ import mx.rpc.IResponder; import mx.controls.Alert; import mx.rpc.events.FaultEvent; import mx.rpc.Responder; private function loadUserDetails(ssn:String):void { // Load the user details for the specified user var callbacks : IResponder = new Responder(onResults_loadUserDetails, onFault_loadUserDetails); var event : LoadUserDetailsEvent = new LoadUserDetailsEvent(user.ssn, user.password, callbacks); btnLoad.enabled = false; // disable button while waiting for a response. event.dispatchEvent( ); // Cairngorm events can self-dispatch to the business layer. } // *************************************************** // Private EventHandlers for the loadUserDetails() // *************************************************** private function onResuls_loadUserDetails(user:UserVO):void { // The SSN and password were authenticated; here are user details _user = !user ? new UserVO() : user; btnLoad.enabled = true; } private function onFault_loadUserDetails(event:FaultEvent):void { Alert.show(event.message); btnLoad.enabled = true; } private var _user : UserVO = new UserVO(); ]]> </mx:Script> <mx:Text text="Please enter your credentials to edit your account:" x="16" y="30"/> <mx:FormItem label="FullName:" x="23" y="208"> <mx:Label text="{_user.fullName}"/> </mx:FormItem> <mx:FormItem label="SSN:" x="54" y="104"> <mx:TextInput id="txtSSN" text="{_user.ssn}" width="129"/> </mx:FormItem> <mx:FormItem label="Password:" x="23" y="70"> <mx:TextInput id="txtPassword" /> </mx:FormItem> <mx:Button id="btnLoad" label="Load User" textAlign="center" x="145" y="149" click="loadUserDetails()" width="147"/> </mx:Canvas> |
Commands – after the processing is finished – will trigger any cached IResponders::result() methods to notify the sender [View] of the event.
In the code example above, look at line 15 where we use a Responder instance to act as a proxy for the functions that we want to call. The Responder class does NOT know any details about the view itself. It simply has functions that may be called upon an event response. For a successful response, the view wants onResults_loadUserDetails() to be called. Likewise for failures, the view wants onFault_loadUserDetails() to be called. With responders, the view essentially provides event handlers for Command post-processing.
To summarize the above code snippet as psuedo-code, you (a) use a responder proxy wrapper class, (b) package the responder instance inside the event, and (c) extend the command base class to support the caching of the callback/view responder. And voila’ you are done!
This is VERY clean:
Better yet, this functionality is built into the Cairngorm Extensions (CGX) using both the Callback and the mx.rpc.Responder classes. CGX is an open-source extension to cairngorm. If you are interested in this and other Cairngorm extensions provide comments to this blog or or visit Google Cairngorm Extensions.
Hi Thomas,
Thanks for your post! that’s exactly what I was looking for.
Anyway, I missed somewhere to download the swc file with the cairngorm extensions you’re using there and, as many other guys commented, a code sample of the command class.
I’ve been digging a little more on that questions and I found a very simple example of an application using (I think) exactly all that theory you explain so well. Here’s the link:
http://nagpals.com/blog/post.cfm/hello-world-using-cairngorm-extensions
You can click in “View application” to see it working and then click “View source”. Also, if you download the example, you get the SWC file with the Cairngorm Extensions.
I’m going to try to use in a little example and see if it works.
Thanks once again and be sure I’ll stay tuned for upcoming posts
Victor,
While the View source tree does NOT show the libs, the downloadable zip archive has the LocalizationMap source and the .SWCs in the /libs/*.swc.
The Cairngorm swc is included in the archive. Click this link: The Cairngorm Extensions to browse the online source code for the CGX swc.
Thanks for the posting. The title of the article is Cairngorm Secret Tip #3 …
Do you have other postings, such as #1, #2?
The best tutorial i have read so far.
Social comments and analytics for this post…
This post was mentioned on Twitter by ryancanulla: #cairngorm, heres a great article on using IResponder to pass view notifications http://bit.ly/2Keuls...
Great article.
This saves the new “notify-view” event generation/dispatch from the command to the view.
Now we have a use case that several views are listening to the “notify-view” event generated by the command. But in your example, it seems only one callback responder can be specified in the original event. Can you suggest a way to resolve our issue?
Thanks!
Eyu, you have made an excellent an astute point. True, callbacks is a 1-to-1 connection between the request originator and the response. If you have a need for multiple callbacks (e.g. more than 1 listener wants to be notified), then use either the ModelLocator databinding approach OR you can create a special dispatcher that supports originators to register for events… think of this an “event bus/pipeline” for your special needs. Unfortunately event bus architectures are ALWAYS specialized and are beyond the scope of a blog.
Thanks for writing up this clear explanation. And of course, thanks for clearing up some of the details of using the UM extensions a while back at the Online Flex meetup. It has helped my Flex workflow greatly.
Mani
Love the article, but it would be nice to see what the command class looks like, or at least a link to an example.
If I am understanding this correctly, since the responder is optional on the event, the command class would have to check to see if it is defined before calling it to avoid a null pointer exception correct?
So would a command result function notifying a view responder look something like this?
public function result(data:Object):void{
//update model
/*I assume responder is stored a property on the command? */
if (this.responder){
this.responder.result(data);
}
}
Jeremy Wischusen’s last blog post..Adobe Flex Frameworks Article
This is why the CGX (Cairngorm extensions) Command class has a notifyCaller() method. That method checks for a valid callback closure. Don’t forget to call super.execute() in the Command::execute() method…
I love you well-written article and the idea, but I also have a few comments:
1. It seems to me, this approach puts even more logic into the presentation layer, which is very hard to unit test.
2. I’d say, that your approach should be used only for cases where the databinding mechanism is not applicable. Databinding is cleaner. Don’t you think?
Databinding is certainly cleaner than callbacks. However, if you have a single view/component instance that wants specific data (without databinding triggers to other instances), then callbacks is probably the cleanest solution. Remember that logic in presentation models works great. Heavy-loading logic in presentation components is not recommended. Instead create facade or delegate classes to manage complexities of multiple view interactions, etc.
Any chance for a complete code sample for one of your examples, esp. the last one? Including the additional Cairngorm classes and those that need to be extended and answering to your three last items:
(a) use a responder proxy wrapper class,
(b) package the responder instance inside the event, and
(c) extend the command base class to support the caching of the callback/view responder.
Graet and interesting article. Where can I find you r other secret tips #2 and #1? I cannot find them.
Thanks and keep blogging!
Thanks pyso,
As with all good intentions, reality often delays my blogging or responses.
Secrets #1 and #2 are postponed… but I am two upcoming blog entries that you will LOVE.
Great article,
I’m not able to transfer the command result back to the view by responder. could you explain it?
Can you share a sample project?
It could help me to understand view notifictions.
Remember that your command MUST call super.execute(event) in order to cache any callbacks to views.
e.g.
override public function execute(event:CairngormEvent):void {
super.execute(event);
switch(event.type) {
…
}
}
AND your response handlers must in turn always invoke a notifyCaller() to notify view or other originating callers that the synch or asynch event has responded/finished.
e.g.
notifyCaller();
“dependency injectors”
Really Cool!
Any idea when youre going to realese this feature?
Note that dependency injectors are already available in the Mate MVC. And… best of all, you can use the Mate EventMaps with Cairngorm. So the Mate EventMap will only have dependency injectors [MateDI] (no event handlers) AND Cairngorm has the event handlers. This is an excellent blend because MateDI supports injection into any specified class instance regardless of position in the view hierarchy. And whenever the data/model changes, all instances of the views get “re-injected”. So your Cairngorm (CGX) code modifies data models and presentation models, MateDI updates the views. By the way, such techniques also removes most needs for CGX callback or view notifiers.
Stay tuned for a blog about LocalizationMaps and Cairngorm… for super-easy techniques and solutions to provide i18n/localization support to your apps WITHOUT ANY CHANGES to your view/UI components!
Mike,
I like this article!
It was quite timely for me, as I have been working around the issue with a timer that polls the modelLocator for the desired info. (I’ve been activating the timer when calling the event and deactivating it in its listener when the changed info is received.) This is definitely a more elegant way to accomplish this goal. I’d like to use this solution instead.
One question though, when you say “extend the command base class to support the caching of the callback/view responder,” which class are you proposing we use as the super class for the command base class? This wasn’t evident to me.
Steven,
If you want to watch [from your views] for changes in the ModelLocator you can use (a) databindings, (b) ChangeWatchers, or (c) view notifications. Technique (b) allows you the ability to easily run your own custom code when the target data changes. Technique (c) can be used simultaneously with (a) and (b) to provide for very powerful systems of interactions.
Never use timer’s to poll the ModelLocator
Hi Thomas,
by talking about Cairngorm…
I just have seen your presentation for the CairgormExtensions…(The adobe.acrobat.com One)
Are you planning to do another one….
?
really interessting stuff by the way… but I got still some problems I cannot get my head around…
Moritz,
ViewNotifications are definitely challenging to wrap one’s head around. Just think about event bubbling or plate stacking; but here the bubbling is “up view to command, command to delegate, delegate to service and then back down to the view.” I think I will post 2 quick examples of view notifications: one without Cairngorm Extensions [CGX] and one with CGX.
Meanwhile, I am planning on 3 more Cairngorm postings… so stay tuned.
oh that sounds great…
By the way I spend a bit time in the past couple of days with studying the concept of notifying the view directly from the command via responder
… Watching your docu / presentation carefully about 5 times
… together with your pdf and some example scripts helped me a lot… guess I would say I understand the process now… I just had to loose the idea of giving the model to much importance.
There are just some bits… one mature thing which makes myself some headaches is the (creation) / use of modules withing in cgx’s. I love the new subController idea, this is so much better… But how would I create the module itself .. or lets say … more important where? – Would I create a command that deals with the whole process or would the view itself create the new module… but what happens if this new “miniApp/cgEnvironment” must be able to be created from anywhere in the project? In this case also a responder cannot help… isnt it?
I think you mentioned something about Mate’s techniques in such a scenario.
Is there anything you could advice on? Especially in context with modules in popups?
Mercy in advance
it is useful to see how Command looks now.
as for me it’s convenient to group events into common class. so when dispathing it we do:
var event : AppEvent = new AppEvent (
AppEvent.GET_USER_DETAILS_BY_SSN);
event.responder = responder;
event.ssn = “123″;
event.password = “******”;
event.dispatch();
may be ssn and password better to srore in model (unless this is a very special password, just for this query only).
so command will fetch its data from model vars:
model.selectedSSN
model.password
If your event also has properties or attributes with specific data types, then grouping events into a common class is not recommend. Consider the event AppEvent.GET_USER_DETAILS_BY_SSN which requires the SSN and password. But if the event AppEvent.UPDATE_USER wants a UserVO? Now your grouped event class has some attributes only used sometimes. This is as bad coding practice.
And consider the issue of maintenance. Users will see an AppEvent used in your code, but they must determine the event type value in order to know why that event is being used. And what if the developer specifies the wrong event type?
This is why unique, custom event classes are almost always recommended. Thus, I would create two event classes: GetUserDetailsEvent and UpdateUserEvent… and better yet, the class names even help with documentation and usage context.
Bojinx implements a system like this but it’s easier to use and provides more response types for each command.
There is one restriction though that a few people have asked me to resolve and that’s the fact that they cant listen to the same response from multiple locations so I’m working on that now, in the next revision of Bojinx you should be able to use a responder like you do now for efficiency or listen to response events for a particular command from multiple locations.
The solution works well though
good to see other people implementing it.
Wael Jammal’s last blog post..Bojinx Core V3.2.1 – Minor bug fix
Great article Thomas! We need to get drinks and continue our “compare and contrast Cairngorm and Rails patterns” discussion. I recently had to solve a similar issue in my “as3-on-rails” stack, and I think you’d enjoy reviewing the code, comparing the techniques. I’ll blog about it once I fly the coop.
Michael,
I am working on improvements to CGX that will deprecate some of the use cases for View Notifications. Using a similar solution found in the Mate framework, I will configure dependency injectors to inject data (whenever the data models are changed) directly into view properties. This will be very powerful.
And I still need to post a blog about 3 Methods for Component Couplings in Flex. You will love that one also.
Regarding drinks, as long as it is wine…. then anytime my friend.
Hey this has helped me a lot. Thank you very much. I’ll be waiting for your “3 Methods for Component Couplings in Flex” article. [:)]