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!