Alex Uhlmann: September 2006 Archives

« July 2006 | Main | November 2006 »

September 28, 2006

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> );

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 }"/>

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 }"/>
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!

Posted by auhlmann at 11:58 AM | Comments (16)

Cairngorm Sample – How Business Logic Can Manage Views Part IV

In the last post about this topic, I’ve added some functionality and another use case to our stock quote application and showcased how a Cairngorm application could scale with focusing on creating model objects. In this post I’ll perform some further refactorings to our model objects.

Furthermore, our customer wants us to show a pop-up as soon as a successful stock purchase is being made. I’ll cover how a state change in your model can transparently cause view related code (like creating a pop-up) to be executed.

Iteration 6 - Refactorings

In iteration 5 we had a statusMessage field in both model objects, StockQuote and StockPurchase. Two separate text input fields have listened to these properties. Now, let’s only have one status message for both model objects. This i.e. could bring us to the idea of creating another object that encapsulates StockQuote and StockPurchase. Let’s call it StockTransaction:

package com.adobe.cairngorm.samples.dashboard.model
{
	public class StockTransaction
	{
		[Bindable]
		public var stockQuote : StockQuote;		
		[Bindable]
		public var stockPurchase : StockPurchase;		
		[Bindable]
		public var status : int;
		
		public function StockTransaction()
		{
			stockQuote = new StockQuote();
			stockPurchase = new StockPurchase( stockQuote );
		}
	}
}

Note that in the above, I’ve changed the previous statusMessage property; which was typed as a String, to a status property; which is typed as an int. I’ve done that so our model objects can only be concerned with a status of our use case and not with the presentation of this status. I think the presentation of the status is something that our views should be responsible for.

Our model objects can contain the different status options they can be in. i.e. our new StockQuote object can have an ERROR and a SUCCESS status, showing that the StockQuote retrieval was either successful or not. So, we can define the states with two values.

public static const ERROR : int = 1;
public static const SUCCESS : int = 0;

In our new GetStockQuoteCommand we can decide in what state the StockQuote object is currently in. Here’s a snippet of it:

public function onResult( event : * = null ) : void
{
	//for demo purpose: event would normally be an event object of remote service result.
	stockTransaction.stockQuote.lastStockQuote = event as Number;			
	stockTransaction.stockQuote.isPending = false;
	stockTransaction.status = StockQuote.SUCCESS;
}
		
public function onFault( event : * = null ) : void
{
	stockTransaction.stockQuote.lastStockQuote = NaN;
	stockTransaction.status = StockQuote.ERROR;
	stockTransaction.stockQuote.isPending = false;	   	
}

There are various ways to achieve a similar separation of concerns. In this application however, I'll let the StockMarketPod.mxml view listen to the value of status and depending on the status value, StockMarketPod will display a String, which is defined on this view. StockMarketPod uses a helper class called StatusMessageFormatter that translates the status property into the correct String needed by the view. This helper class is initialized like this:

<view:StatusMessageFormatter 
	id="statusFormatter" 
	statusMessages="{ [ '', 'Quote retrieval error.', 'Purchase error.', 'Purchase succesfull.' ] }"/>	

I listen to the status via a function binding on the status property. For more information on this you can take a look into the full source code for this application at the end of this post.

Flex 2 make it easy to perform refactorings like this. This is very important since refactorings of your model objects can occur all the time and most often you rarely get it right the first time around. ;)

Iteration 6 - Invoking View Related Methods

As said in the beginning of this post, our customer wants us to alert the user via popup when a stock purchase request has successfully been made. Let’s think of creating a simple Alert window (mx.controls.Alert). When the onResult handler of the PurchaseStockCommand is invoked we know a stock purchase has been completed.

I think of creating an Alert control as something only views should be concerned about. It’s like creating other view components, managing states of view components or effects. I think only views should be responsible. Usually we bind UI controls to properties of our model objects. But for creating an Alert control, there’s no UI component where we can bind to. How do we best let a view invoke a view related method after a certain state change in our model occurred?

I basically see two ways to do this from a model. We could manipulate a model object so it dispatches an EventDispatcher event that the view can listen to. We could also just mark properties of our model as Bindable and let our views subscribe to either a custom event name that you have defined in our Bindable metadata (with [Bindable(event="customEventName")]), or to the default "propertyChange" event. Using the propertyChange event your view's event handler method would have to differentiate what property changed. You can do that with the passed in mx.events.PropertyChangeEvent object. Listening to a custom event name defined in the Bindable metadata, we have to dispatch the event manually using dispatchEvent.

I see two drawbacks using this approach. First of all, it’s more code to write and most importantly, to read. This is because your views need to subscribe manually to events and define event handlers. It might also affect your models since some of them might need extra EventDispatcher functionality. Secondly, we need to make sure that our model objects exist when the view is subscribing to the event.

The latter is something binding gives us for free. We can bind to a state change of a model even if the model isn’t initialized at the time of subscription. Furthermore, using the binding approach is just quicker to do in many cases.

Following the binding approach, we can bind to a property of our model objects and invoke a method in our views with using the mx:Binding tag.

This could look like the below:

private function set createChargedMessage( value : Boolean ) : void
{
	if( value ) Alert.show( "Thanks! Your bank account has been charged" );
}
<mx:Binding 
	source="stockTransaction.stockPurchase.isComplete" 
	destination="createChargedMessage"/>	

Now, instead of using mx:Binding I recommend that you use an extended version of the Observe tag that Paul Williams originally blogged.

This can make your code more secure, and furthermore it does also give you a slightly easier API to solve the problem here. We only need to listen to the "true" value of the isComplete Boolean. Therefore, we tell our new utility exactly this.

<ac:ObserveValue 
	id="observe" 
	source="{ stockTransaction.stockPurchase.isComplete }" 
	handler="{ createChargedMessage }" 
	value="{ true }"/>

The createChargedMessage will be reduced to this:

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

For more information on why I’ve introduced this utility class, please read the follow up post on this topic, "Using Binding Securely".

Summary

What have we done here?

We needed our view to invoke a view related method based on some state change in our model. First, we’ve changed the state in the model with invoking a Command. The Command located our model object via ModelLocator and changed the state of this model object via its API. Because our view subscribed to this specific state change (via binding in our case), it could react to it with invoking a method. Since it was using mx:Binding, we didn’t need any extra ActionScript to setup the binding, neither did we need a MXML component that would accept a return value (which we didn’t have since we were calling a popup).

As I’ve noted above, there’s also one little drawback on how we use the binding approach here.

For more information on the drawback and a solution to it with an additional feature please read the next post, "Using Binding Securely"

As after every post in this series, you can view the application and download the source code of it via right mouse click > View Source.

Posted by auhlmann at 11:15 AM | Comments (8)

September 08, 2006

MAX 2006: Leveraging Flex 2 and Flash Player 9 for Truly Cinematic Experiences

As MAX 2006 in Las Vegas is coming closer and it’s shaping up to be a fascinating conference. I’m talking about

Leveraging Flex 2 and Flash Player 9 for Truly Cinematic Experiences

and I’d like to give you more information where this will be about, in hope you consider joining my session!

I’ll talk about how cinematic effects can dramatically improve the user experience of a Rich Internet Application and can contribute significantly to the success of how your RIA will translate the experience that your costumer wants to deliver.

You will see new types of effects and learn best practices toward their use and creation.

New Flex Effects Leveraging Flex 2 Features

I’ll showcase a variety of different effects but most importantly I'll showcase a new type of cinematic effects, leveraging the performance improvements, the new bitmap manipulation features and the new Effects Framework in Flex 2. You'll be given ideas and complete source code for these new type of effects and will be able to create your own customized effects based on the principles demonstrated.

One of these effects is a flip effect. I’ve a little teaser for you here:

See the Flip effect

How this is done, how you can use it in your own work and how all the other effects look like…stay tuned for MAX 2006!

Future of AnimationPackage

Some of you might know that I’ve developed AnimationPackage, an ActionScript 2 library for Flash and Flex 1.x developers. I’ll outline how I see the future of this framework and how I see it fitting alongside the Flex 2 effects framework.

See you soon, on the
25. October, Wednesday, 1:45 p.m
and the
26. October, Thursday, 3:00 p.m.
in Las Vegas!

I'm excited!

Posted by auhlmann at 10:35 AM | Comments (5)