Using Binding Securely

In my last post about the Cairngorm Dashboard example I’ve added a little functionality that allowed a view to react to a state change in the model in order to do something view related like invoking a popup or an effect.
I’ve been using the binding approach and that made it very easy and flexible to do. But as I said in my last post, this can have one slight drawback you have to consider. In this post I’ll showcase the drawback and provide a solution to it via an extended version of Paul’s Observe tag. Furthermore, this extended version of Observe makes it even easier to perform this kind of listening to the model.


Behind the scenes, binding uses flash.events.EventDispatcher. But binding gives you much more than just that. You can bind to properties even when their objects aren’t initialized yet. You can also bind to XML data using E4X to specifically listen to certain areas of the XML. For more information on the features of binding make sure you read the Chapter 37 in Part 5 of the Flex 2 Developer’s Guide.
There are multiple ways to use binding. All of them require a source that defines what property you want to listen to and a destination that defines what shall be triggered once your source changes.
You can either use the MXML curly braces syntax, function binding, the mx:Binding tag or define bindings in ActionScript.
Either way, you have to be careful in triggering application code in a destination of a binding, which we’ve done in previous examples of my Dashboard sample using either function binding to trigger a formatter or mx:Binding to invoke a view related method.
Since the Binding feature hides us from many exceptions that would have been thrown using EventDispatcher, it cannot differentiate in certain situations when certain; to us important, exceptions are thrown in our application code that is triggered in the destination. Let’s showcase this and throw one of these “certain” exceptions on purpose in our latest Cairngorm Dashboard sample. Let’s throw one that I’m sure you’ve have seen before: The one and famous:
ErrorID 1009: “Cannot access a property or method of a null object reference.”
Change the createChargedMessage setter to:

private function set createChargedMessage( value : Boolean ) : void
{
var o1 : Object = {};
o1.o2 = {};
trace( "show o2 " + o1.o2 );
o1.o2 = null;
o1.o2.foo = "bar"; //oops, o2 doesn't exist, an exception should be thrown.
trace( "show foo " + o1.o2.foo );
if( value ) Alert.show( "Thanks! Your bank account has been charged" );
}

Since this code is triggered as a destination of the mx:Binding tag, the runtime exception that should appear on

o1.o2 = null;
o1.o2.foo = "bar";

is swallowed by the binding code in the Flex framework. You will not see the usually expected runtime exception displayed via the Flash Debug Player. Instead, the following code like the trace( "show foo " + o1.o2.foo ); will just not execute.
Note, that this will only happen with certain exceptions. It will only happen on the following exceptions:

  • Error #1006: Call attempted on an object that is not a function.
  • Error #1009: null has no properties.
  • Error #1010: undefined has no properties.
  • Error #1055: – has no properties.
  • Error #1069: Property – not found on – and there is no default value

For more information on these errors take a look at Run-Time Errors of Adobe Livedocs.
Note also, that this will only happen when your application code in the destination executes in the same ActionScript block. This means if your exception throwing code executes in a different frame (as would usually be the case on a custom effect) you will see a runtime exception as expected.
However, if your application code does throw one of the swallowed exceptions in the same ActionScript block, there are ways so you can see this immediately.
You could use a special debug class in the Flex framework to help you see the error message. Use
mx.binding.BindingManager.debugBinding( <your destination as a String&gt );
But in a production environment I’d recommend you use another more bullet-prove way of solving this problem. You can use the extended version of Paul’s Observe tag.

<ac:Observe
source="{ stockTransaction.stockPurchase.isComplete }"
handler="{ createChargedMessage }"/&gt

Using Observe you can invoke a method instead of the setter.

private function createChargedMessage( value : Boolean ) : void
{
if( value ) Alert.show( "Thanks! Your bank account has been charged" );
}

Try putting the code from above that will throw a runtime exception into the createChargedMessage method. Observe will make sure that a runtime exception is being thrown as expected.
Internally, Observe wraps another global Error handler around your destination, saves the exception thrown and throws it in the next frame.
Furthermore this approach offers an additional feature for your convenience. If you want to listen to only a specific value of the source, you can use ObserveValue for this. In our use case of the iteration 6 Cairngorm Dashboard we just want to know when the isComplete property of our StockPurchase object is true.

<ac:ObserveValue
id="observe"
source="{ stockTransaction.stockPurchase.isComplete }"
handler="{ createChargedMessage }"
value="{ true }"/&gt
private function createChargedMessage() : void
{
Alert.show( "Thanks! Your bank account has been charged" );
}

I’ve mentioned above that this also applies to function bindings. In StockMarketPod.mxml of the iteration 6 Cairngorm Dashboard sample application, I’ve used the provided Observe.execute method in order to ensure a secure use of our function binding, which tirggers a custom formatter.

<mx:Label text="{ observe.execute( statusFormatter.format, stockTransaction.status ) }"/>

You can download the Observe and ObserveValue utility classes from here.
Hope this helps!

17 Responses to Using Binding Securely

  1. Xavi Beumala says:

    You could also use mx.binding.utils.ChangeWatcher or mx.binding.utils.BindingUtils to invoke a method instead of a setter.

  2. Omar Ramos says:

    I was using this aproach and came up with a bug. I am using the ObserveValue tag inside a popup and when the value isComplete changes the Observe invokes the handler which closes the popup using PopUpManager.removePopUp( this );. Now when I close the poup I set the isComplete to false in case I make that call again. But now next time I open the window the ObserveValue tag invokes the handler but with a difrent scope of “this”. So now when I do
    PopUpManager.removePopUp( this ) it does not work because of the wrong scope. Any Ideas?

  3. luchyx says:

    Hi Alex.
    I have a question/problem with cairngorm.
    When i try to compile my project appear this error.
    /*
    1144: Interface method onFault in namespace com.adobe.cairngorm.business:Responder is implemented with an incompatible signature in class com.ria.commands.login:LoginCommand.
    */
    I found in the doc’s that the error code 1144 is
    /*
    1144 Interface method _ in namespace _ is implemented with an incompatible signature in class _.
    Method signatures must match exactly.
    */
    But any idea how can i solve it.
    Should I move me code near to the Cairngorm.swc file. It’s a namespace problem?
    Thanks in advance.!

  4. vigen says:

    Hi,
    I’m going to write a large application using Cairngorm and i am not sure how to update a single item in a collection of items. a specific item may change after server poll and i would like to implement some kind of a smart update that doesn’t update’s the whole collection and still change the view. can it be done with modelLocator and databinding?
    thanks, i find all your articles very useful.
    Eran

  5. Joel says:

    If you can bind data elements to XML using E4X and you are retieving XML from the server why wouldn’t you use XML Value Objects instead of Action Script Value Objects?
    Thanks

  6. Marcus says:

    Great tips. Thanks for sharing.
    As Xavi mentioned in the first comment, mx.binding.utils.BindingUtils is available for binding to methods. I’ve been using BindingUtils for this purpose, but have found one slight drawback to the approach. The binding is triggered once when it is set, which is often prior to the source of the binding being set with anything useful. I have simple workarounds for most situations, but I’ll be stoked if these tags avoid that initial call.
    Well, off to give it a go. Thanks again for taking the time to share with all of us.
    Marcus.

  7. yeah great, if you want to learn some more basic binding? Binding 101 can be found here:
    http://labs.flexcoders.nl/?p=24

  8. Mike Britton says:

    I wasn’t able to get Observe to work, but ObserveValue works like a charm. Did anyone else have problems implementing Observe?

  9. JR says:

    Why do not use ChangeWatcher ?
    ChangeWatcher.watch ( model, “propertyname”, handler )

  10. Andy says:

    Mike: I am also having problems with observe.. I was previously using Pauls version, but when I swap it out with Alex’s the handler no longer fires… I am listening to a string object on a model in cairngorm. I have gone back to using Pauls version for the moment. Any thoughts Alex?

  11. Ernest says:

    hi,
    If you want to see some more Binding magic then have a look at http://philemonworks.wordpress.com/2007/07/17/flex-bindable-hash/
    I use this to implement a cross-component ModelLocator.
    Ernest

  12. jvfacio says:

    Hi,
    is possible use the Observe in action scrip?? i try to implements in one component but don’t work. the project complie but not work.
    you have any example in action scrip??

  13. Peter says:

    The binding is triggered once when it is set, which is often prior to the source of the binding being set with anything useful. I have simple workarounds for most situations, but I’ll be stoked if these tags avoid that initial call.

  14. David Frankson says:

    Flex 3 does not support using bindings from actionscript onto XML or E4X. You have to use the {} or tag from mxml. I filed a feature request to add a new method onto the BindingUtil class to help with bindings from AS3. Vote for or comment on this issue below:
    https://bugs.adobe.com/jira/browse/ASC-3054

  15. sharp aquos says:

    is possible use the Observe in action scrip?? i try to implements in one component but don’t work. the project complie but not work.

  16. Werbeagentur says:

    I had the same Problem:
    ErrorID 1009: “Cannot access a property or method of a null object reference.”
    But thanks for the examples. it´works excellent…

  17. Henry Rabinowitz says:

    Are there advantages of using the Observe tag over ChangeWatcher.watch() method? Is the main advantage of Observe tag simply that it can be used in mxml code?