# My first brush with Cairngorm

So after reading “Professional Cairngorm” I decided that I would try using Cairngorm on my next project. Well that project is is the final stages of completion and I’d like to share my thoughts.

The project was a dynamically driven Flex app embedded in a web-browser that could also run on AIR. The application was read-only and did not collect data from the user but simply presented data one way. This app consisted of a your typical main screen, featuring configurable “portlets” that gave teasers into the deeper content contained within. It also had primary top navigation each of which drove to sub-screens which could render their data-sets in various customizable layout views, each of which having its own set of second level navigation to navigate within that sub screen. The data was stored in an XML implementation of an “Content Store” interface which could also be swapped out with a SQLite or web-service backed version if necessary. The lower level service layer that stored and managed all of the content as well as the navigation meta-data was wired together using Spring Actionscript and also leveraged other libraries like AS3 Commons.

For the application logic itself (i.e. how the views render, how the user navigates around, what screen renders what data etc) was all handled by using Caringorm 2.2.

By default, Cairngorm seems to drive the developer to be extremely granular with their Command, CairngormEvent and Delegate declarations. What this means is that if you are not careful, you will end up with an absolute overload of classes for a simple application. Instead I took the approach consolidating domain related functionality into larger Delegate classes which could handle more than one type of small specific operation. My Delegate classes abstracted away my lower level service layer (where the content and navigation meta-data was stored) away from the application and fulfilled its contracts through the delivery of VOs to the commands, subsequently to the model and finally to the views via Flex data binding.

I also tried to limit the number of events down to a total of four, one for bootstrapping Spring, one for handling a screen change, one for rendering the correct body and finally one for launching external resources. The number of VOs (value objects) I ended up with was fairly large (about 10) as I was very careful to create granular VOs so that I had zero coupling with the underlying service layer which was hidden away by the Delegate classes. The underlying service layer certainly had its own VO like objects which I could have permitted to bubble up to the model/view, but taking the decoupled VO approach is the way to go in an MVC framework such as Cairngorm. You can end up replicating a lot of properties etc, but it is worth it in the long run as your VOs help you gel your domain model without tying it to the underlying implementation.

In the past I’ve played around with PureMVC, as well as my own custom MVC like framework for throwing together quick Flex apps. Overall I would say that my experience with Cairngorm in this small app was a positive one. There was a slight learning curve to get going, but it was not difficult at all if you have used other MVC frameworks in any other language. Cairngorm is heavily dependent upon Flex/AS3’s internal data binding and that can be a positive or negative depending on your personal views, however I found it to be quite powerful and convenient.

On the downside, the most awkward thing in Cairngorm for me was the Model (ModelLocator), for a small app like this one it was fine, but it just seems like a giant “global variable” store (not seems, it is in fact one) and if you are doing a complex app, I feel it would be necessary to break this up into different model’s for different parts of the application. Ideally each view should not be directly bound to your custom ModelLocator as Cairngorm forces this which basically couples your view directly to a specific model implementation. Instead a DI approach might be better.

Thankfully this application did not have to use the ServiceLocator as I was using in-process services (not web-services or remoting). Why was I thankful? Well when I looked at the ServiceLocator the whole thing made me cringe! The documentation on how to use it as well as the source, plus the fact you declare an wire it up in MXML…. It just seemed like a combination of bad naming and bad implementation. Secondly, unless you are using the hardwired web-service, http object or remoting versions in that class, the ServiceLocator in Cairngorm appears to be useless out of the box without customization. You just can’t easily plop in your own services bound by an arbitrary key. Why don’t they support custom abstractions of a “service” beyond the default “remote” three provided in Flex? Why does a “service” have to be remote in Cairngorm? Why should it care?

Overall… like I said my experience was fairly positive and would use it again for a similar project. That said, I do have some issues with the framework. I also fundamentally don’t understand why this framework is the “de-facto” standard promoted by Adobe and seemingly viewed as required knowlege for any “real Flex/AS3 developer”. Shouldn’t knowing the principles of MVC be more of a requirement than simply the nuts and bolts of a specific framework implementation?

Next stop… I am going to try out some other AS3/Flex MVC frameworks. I’ll report back on those.

# Security Sandbox Violation during run and debug after moving or copying a Flex project in Flex Builder

Ugh, this is one of those classic examples of getting sidetracked in your daily work because of some annoyances with Flex Builder. Today I copied an existing Flex Builder project in Eclipse to another directory (new renamed project). I then edited the project settings (renamed the project) before importing the new copied project into Eclipse. This worked great and Eclipse immediately imported the new project and recognized it as a Flex project.

The problem came up when I tried to debug my app. When I hit debug I got the dreaded *** Security Sandbox Violation *** (Adobe’s equivalent of the blue screen of death) once my app attempted to make an UrlLoader request for a sibling resource to the SWF. Now, at this point I was frustrated as this was an exact cloned copy of the project that still worked under the original project name in Eclipse.

Turns out, that during a true “Create new Flex Builder Project” setup in Eclipse, Flex Builder adds your project’s bin-release and bin-debug directories to the local Flash Players global security settings as a trusted resource. This is necessary so you can debug/run your Flex projects in eclipse without getting the Security Sandbox Violations when accessing local resources.

Now how to fix this?

and proceed to add your copied/new project’s bin-debug and bin-release dirs. Then next time you run, the security sandbox exceptions will go away, just as if you originally created the project in Flex Builder’s “wizards” of smart.

# Book Review: Professional Cairngorm

This is a review of the book Professional Cairngorm by Jeremy Wischusen. When describing his motivations for writing this book the author tells a story about experience with Flex/AS3 development, but none of it using Cairngorm, then he had a job interview…. And in typical fashion, when he answered no to the “cairngorm experience” question, the interviewer basically said that if you have not used “Cairngorm” you don’t know anything about Flex/AS3. What a joke! This is a side rant, but I can relate to this guy as I have done about a year and a half of pretty serious AS3 development without Cairngorm, and after having read this book, I really don’t see why Cairngorm is such a major “must know” AS3/Flex MVC framework. The author does a good job covering the history of this framework, and all said and done, it sounds likes some flash developers originally threw the framework together then Adobe Consulting threw its official “stamp of approval” on it, and there you go. Everyone must learn Cairngorm…..

So that said, just take a look at Chapter 3, which describes the Cairngorm’s “ServiceLocator”. Wow, if that does not seem like an overly convoluted set of classes and interfaces just to lookup HTTP/WS/RMI services, then I am not sure what it is.

Moving on….. to the book. This is a decent book, and the author is correct that for a newcomer to Cairngorm, there is not a ton of very good documentation out there for those starting with this framework. The author does a fairly good job of presenting the framework and how it works in a simple straightforward approach. Roughly the first 1/2 of the book is dedicated to discussing the inner working of the major Cairngorm players, the last 1/2 of the book covers a detailed step by step case study (blog app) followed by good coverage of the communities Cairngorm complaints, expert tips and 3rd party extensions.

Complaints about this book: First off I felt like the author may have been rehashing a lot of the material that is already out there, given the many references to official docs and other resources that were cited. The second complaint is the horrible formatting of the code samples. The wrapping of code lines is awful and so is the spacing between methods etc. Very hard to read and they could have done a better job with that.

Overall: Do you need to learn Cairngorm in about a day? Get this book.

Skill levels/Audience: Targeted towards people with zero Cairngorm experience, but intermediate to advanced AS3/Flex experience. Backgrounds with other MVC frameworks is helpful in understanding the material. This book is NOT for people brand new to Flex/AS3.

FYI, last year I played around with PureMVC, and this year (2010) after reading this book, I am going to make an effort to do at least one or two projects using Cairngorm. Lets see how it goes and I will report back!

# Upgrade to Spring AS 0.8 and others

The Spring Actionscript project is maturing and as they do, they keep teasing apart the entire project. So I am now upgrading from 0.7 to 0.8 and if you are to, here is what you can expect. (change log here)

a) If you were using the older AS3Reflect library, well now they moved that again over to as3commons.reflect. Also note that the ClassNotFoundError which used to be in AS3Reflect has now moved to as3commons.lang. The have been factoring out a lot of stuff, however Spring AS still is dependent on these new libraries so you must download those SWCs and link them in.

b) Looks like as3commons now has a logging package, ugh, yet another! I already have support for Spicelib logging as well as the default Flex logging framework built into my framework, so I guess I might need to take a look at the new as3commons logging to see if I will create an adapter for that.

c) If you are still referencing the older Prana Framework xml schemas in your xmlns declaration (in applicationContext.xml) you will need to update those to use the new schema location over at springactionscript.org. It should look like the below:

<pre><?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springactionscript.org/schema/objects"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springactionscript.org/schema/objects
http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd">


d) as3commons.reflect now dumps traces of errors during the pre-instantiation phase for all singletons. This seems to occur for objects who’s constructor expects a non-null parameter, but the reflect code is passing NULL for all parameters. In my case, my app comes up A-OK and functions fine, however if you are running in debug mode you will see all this trace output from as3 reflect.

e) lastly, if you have any sort of a build script, in my case a Groovy GANT script, make sure to update those for the new library dependencies.

Those are the only items I really ran into when upgrading. All my FlexUnit tests passed A-OK so it looks like I am good to go. Good luck.

Also check out the Spring AS docs located here

It looks like since I last looked, they added quite a few new interested features:

a) They fixed the import issue finally, now you can import other XML files as well as import them if they are embedded in your app

b) You can define your app context “xml” within MXML directly inline your Flex app which may be of use

# Spring AS & Prana woes with blank prop or constructor args

UPDATE: The bug described here appears to be fixed as of 0.8

So I’ve been doing a fair amount of work with Spring Actionscript v0.7.1 (formally the Prana Framework). In AS3 you can define methods and/or constructors that take optional arguments. Optional arguments must always be defined after the required arguments and they are noted by the presence of a default value in the method/constructor signature as such:

package my {
public class MyClass {

//constructor
public function MyClass(reqArg1:String, opArg1:Boolean=false, opArg2:String=null):void {
// your constructor code for MyClass here;
}

}
}


When you are defining a bean in Spring AS you can define it’s constructor arguments as so:

<object id="myClassInst"       class="my.MyClass"       scope="prototype">                          <!-- required arg 1-->   <constructor-arg value="val4ReqArg1"/>   <!-- pass false for optional boolean arg 2 -->    <constructor-arg value="false"/>    <!-- intentionally pass BLANK to 3rd optional arg -->    <constructor-arg value=""/></object>


Well when running this  you will get an error like this for the 3rd argument:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at org.springextensions.actionscript.ioc.factory.xml. parser.support.nodeparsers::KeyValueNodeParser/parse()
at org.springextensions.actionscript.ioc.factory.xml. parser.support::XMLObjectDefinitionsParser/parsePropertyValue()
at org.springextensions.actionscript.ioc.factory.xml. parser.support::XMLObjectDefinitionsParser/parseProperty()
at org.springextensions.actionscript.ioc.factory.xml. parser.support::XMLObjectDefinitionsParser/parseProperties()


This is a bug in Prana (see here http://jira.springframework.org/browse/SESPRINGACTIONSCRIPTAS-49), to get around this until it is fixed, you will need to pass some dummy value, that your constructor code will interpret as a BLANK, such as literally the string “BLANK”. Stupid? Yes, but until this is fixed in Spring AS this is the solution unfortunately!

# Easy Multipart file uploads / POSTs using URLStream or AS3HttpClientLib

When working on a cross runtime Zinc/AIR method method of posting files to a remote server, I came across Mike Stead’s URLFileVariable and URLRequestBuilder classes which makes the process of uploading multiple files (or ByteArray’s of data) via an HTTP POST much easier. Click here get his code

The basic concept is this: assuming you have one or more ByteArray’s of file data and the filenames to go with them, you prepare one or more URLFileVariable’s. The URLFIleVariable’s are added to the URLVariables as follows:

// create the standard "URLVariables"
var vars:URLVariables = new URLVariables();
// lets set a ByteArray of JPG data with the filename "myFile.jpg" against the POST variable "file1"
vars.file1 = new URLFileVariable(myByteArray, "myFIle.jpg");


Now at this point, as in my case, I am passing these URLVariables to either an AIR implementation of an HTTP client (using URLStream) or a Zinc implementation (using AS3HttpClientLib). This was all described here in another post.

In my AIR implementation of an HTTP client abstraction I use an URLStream and the code that deals with the URLVariables works something like the following.


/* Standard URLStream code that interacts with URLVariables
which contain Mike Stead's URLFIleVariables and uses his URLRequestBuilder */

var stream:URLStream = new URLStream();

// [ REGISTER for your stream listeners here...

/* use Mike Stead's URLRequestBuilder to properly build the
URLRequest and encode it to contain all the multi-part data and filenames in the "vars" created above */
var req:URLRequest = new URLRequestBuilder(vars).build();

// ensure a POST because URLRequestBuilder only specifies POST if the variables contains files.
req.method = URLRequestMethod.POST;

// define some URL to post to
req.url = "http://my.something.com.xyz/url_to_post_to.xyz";

// fire off the POST

// as the load completes, your event handlers for the stream should take over


Now on the other hand, if you happen to be using AS3HttpClientLib (as described in one of my other posts) you will be coding the equivalent of the URLStream code above, however using AS3HttpClientLib as follows. Here we do not use the URLRequestBuilder but simply manually retrieve the appropriate information from Mike’s URLFileVariable instance.

....

// our AS3HttpClientLib HttpClient
var client:HttpClient = new HttpClient();

...
// [Remember to setup your "client" event hooks as described in the AS3HttpClientLib docs here]

// create a new POST request
var postReq:HttpRequest = new Post();

// lets create an Array to hold all the different "parts" of this multipart post
var parts:Array = new Array();

/* lets push the URLFileVariable we created earlier into the parts Array
according to how AS3HttpClientLib expects it, as a Part object. Here
we are simply creating a new Part and populating it with the data
that we defined up above when we created the URLFileVariable */

parts.push(new Part("file1",vars.file1.data, "application/octet-stream", [{name:"filename",value:vars.file1.name}]));

// create a multipart that points to the "parts" Array
var mp:Multipart = new Multipart(parts);
postReq.setMultipart(mp);

// create a URI
var uri:URI = new URI("http://my.something.com.xyz/url_to_post_to.xyz");

// fire off the request
client.request(uri,postReq);



Thanks again to Mike Stead’s UrlFileVariable and URLRequestBuilder classes for helping me make an generic HTTP multipart post process easier and I hope my post will give those reading some help along the way on implementing their own.

# Strange IMPORT failure in Spring AS

So I’ve started to think about splitting up the main applicationContext.xml file in one of my projects. The current one is getting quite large. Spring AS has the ability to import bean/object definitions from another XML file of your choice such as the following example where my context defines one object “yObject” and then declares an import to bring in another XML file which contains further object definitions:

<objects....>
<object id="yObject" class="my.package.YObject"/>
<import file="subConf.xml"/>
</objects>


The contents of “subConf.xml” file look as follows:

<objects....>
<object id="zObject" class="my.package.ZObject"/>
</objects>


After booting up Spring AS, I can successfully retrieve “yObject” however “zObject” is null. I have also tried specifying the subConf.xml file explicitly via a full path to no avail. I’ve been following the docs to the tee and this simply has made no sense! So after hours of fiddling with this and going through debugging the source code for Prana directly I found that when the following header that is in the objects tag the e4x “xml.descendants(“import”)” call within XMLObjectFactory._addImportLocationsIfAny() yields zero results.

<objects xmlns="http://www.pranaframework.org/objects"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.pranaframework.org/objects
http://www.pranaframework.org/schema/objects/spring-actionscript-objects.xsd">


When I remove all the xmlns/schema info OUT of the tag. The xml.descendants(“import”) works fine. Huh? Seems like an e4x bug?

[UPDATE 1/24 this is now fixed in the Prana source in SVN]

# Prana Framework is now under the Spring umbrella

Great news and I’ve been hoping for this for quite a while. Spring has taken the Prana Framework under its wing and added it as an official Spring extension called Spring Actionscript. Here is another post about this.

When I first got into developing in AS3/Flex this past summer I immediately began looking for some sort of “Spring like” bootstrap/DI container for AS3 apps. Well the playing field was pretty slim. The two main ones out there were SpiceFactory’s Parsley project and the Prana Framework. I tended to like Prana’s because at the time it was much closer to Spring and quite lightweight. I also compared the functionality and activity on the forums and it appeared that Prana was getting more traction. As I posted previously, due to the uncertainty of who would come out the winner in the AS3 IOC world I ended up putting in a light IOC container abstraction layer in my AS3 API as to not be bound too tightly to any one implementation… as my app was only calling variations of <code>getObject()</code> to fetch services etc.

So here we are several months later and with this news that Spring is officially making Prana it’s AS3 extension of Spring, I think we made the right decision. This is great news

# Local IO write performance in Zinc improved

Looks like the folks over at MDM have improved their local IO write support (windows only) with the release of v3.0.10 of MDM Zinc. This is probably due to Adobe AIR and people’s complaints about the lack of better support for writing ByteArray data to disk in Zinc. Note that this new feature is only available when you are running on a PC
(mac/linux still have to use the old HEX conversion method)

In a previous post I wrote about the slow performance of writing binary data in Zinc. However now it is definitely faster, however still not as fast as writing under Adobe AIR. Regardless, it looks like MDM has listened to their users and made a step to improve things and that is great.

Here is an example of how to write a ByteArray to disk now under 3.0.10. Note this is faster than the old HEX conversion method and is much faster and less code:

var data:ByteArray = // some byte array of your data
mdm.FileSystem.BinaryFile.setDataBA(data);
mdm.FileSystem.BinaryFile.writeDataBA("c:\some\path\to\file");


Kudos to the folks at MDM for adding this new feature.

[Updated 10/27/2009: The PseudoThread framework described below has been incorporated into the AS3-commons project: Concurrency Module. You can check out the latest source by clicking here or read an updated HOWTO located here.]

Ok, those of you who know AS3 and the Flash Player are saying “Wait a second, there is no threading in AS3”, and you are correct, however for those of you from a heavy Java background like myself, I’m here to provide you with a sample of code that will give you some pseudo threading capability that you are accustomed to.

Why would you need something like this? Well since the player processes applications with one thread, if you need to do some sort of background operation that is intensive, doing so may freeze up the GUI which would prevent the user from being able to do anything until the task completes. By using a thread like PseudoThread you can prevent the application from freezing while your background operation runs over time.

I’ve provided two classes, PseudoThread and IRunnable as well as a simple example (main.mxml) which uses this little framework. One could create a more robust and larger AS3 threading framework based on the concepts of PseudoThread and IRunnable. One might want to introduce a thread manager, the abilities to stop() and pause() as well as throttle the rate of processing. Either way, if you need threading capability, these classes below should be of help to you and at a minimum help to get you going on your own custom implementation.

To get started checkout the source over at the bitsofinfo project at Google Code or you can get it from the AS3 Commons – Concurrency Module

The overall concept here is that a PseudoThread processes an IRunnable until the IRunnable is completed with it’s work or until an optional timeout is reached. You implement the details of an IRunnable however you see fit. An IRunnable is responsible for doing some task within it’s process() method, and this method will be called again and again until your IRunnable’s isComplete() method return’s true and then the PseudoThread will stop.

IRunnable

Lets first take a look at IRunnable (below) which is the interface that your code implements in order to be processed by a PseudoThread. This is similar to a Runnable in Java. The getTotal() and getProgress() are methods which would permit some abstract external resource to display or report/track progress of an existing unit of work being processed by an PseudoThread. PseudoThread itself utilizes these methods as it dispatches ProgressEvents.

package org.bitsofinfo.thread {

/**
* An IRunnable is to be used with PseudoThread which
* will call an IRunnable's process() method repeatedly
* until a timeout is reached or the isComplete() method returns
* true.
*
*
* */
public interface IRunnable {

/**
* Called repeatedly by PseudoThread until
* a timeout is reached or isComplete() returns true.
* Implementors should implement their functioning
* code that does actual work within this method
*
* */
function process():void;

/**
* Called by PseudoThread after each successful call
* to process(). Once this returns true, the thread will
* stop.
*
* @return	boolean	true/false if the work is done and no further
* 			calls to process() should be made
* */
function isComplete():Boolean;

/**
* Returns an int which represents the total
* amount of "work" to be done.
*
* @return	int	total amount of work to be done
* */
function getTotal():int;

/**
* Returns an int which represents the total amount
* of work processed so far out of the overall total
* returned by getTotal()
*
* @return	int	total amount of work processed so far
* */
function getProgress():int;

}

}


Next is PseudoThread which is the actual workhorse. To process an IRunnable you simply create a PseudoThread and pass it an IRunnable who’s process() method will be continually called by the PseudoThread every msDelay milliseconds as specified via PseudoThread’s constructor. PseudoThread is really nothing more than a generic wrapper of the flash Timer class. The PseudoThread dispatches events for complete, error and progress.

package org.bitsofinfo.thread {

import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;

/**
* Dispatched when the thread's work is done
*
* @eventType	flash.events.Event.COMPLETE
*/
[Event(name="complete", type="flash.events.Event")]

/**
* Dispatched when the thread encounters an error
* or if the Thread times out
*
* @eventType	flash.events.ErrorEvent.ERROR
*/
[Event(name="error", type="flash.events.ErrorEvent")]

/**
* Dispatched when the thread's work makes progress
*
* @eventType	flash.events.ErrorEvent.ERROR
*/
[Event(name="progress", type="flash.events.ProgressEvent")]

/**
* <p>This class simulates a thread in ActionScript </p>
*
* <p>You create a PsuedoThread by passing an IRunnable
* who's process() function will be called every "msDelay" milliseconds.
* The IRunnable's isComplete() method is consulted
* after each process() invocation to determine if the processing
* should cease. When IRunnable.isComplete() returns true
* the Thread will terminate and fire off the Event.COMPLETE
* event. </p>
*
* <p>PseudoThreads are useful for time consuming processing operations
* where a delay in the UI is un-acceptable. The smaller you set the <code>msDelay</code>
* setting, the faster this thread will execute and subsequently other parts of your application
* will be less responsive (noteably a GUI).</p>
*
* <p>Note! To prevent memory leaks in your application callers must always remember
* to de-register for the complete event from this thread after it has been received
*  (as well as the progress and error events!)</p>
*
* <P>Caller can also specify the max amount of time this Thread should run before it will
* 	stop processing and throw an Error. This is done via the <code>msTimeout</code> constructor
* argument. If no timeout is specified the process will run forever.</P>
*
*
* */
public class PseudoThread extends EventDispatcher {

// the timer which is the core of our PseudoThread
private var intTimer:Timer = null;

// total times we have ran
private var totalTimesRan:int = 0;

// default max runtimes is forever
private var maxRunTimes:int = 0;

// the IRunnable we are processing
private var runnable:IRunnable = null;

// a unique name for me
private var myName:String;

/**
* Constructor.
*
* @param	runnable			The IRunnable that this thread will process. The IRunnable's process()
* 								method will be called repeatably by this thread.
*
* @param	threadName			a name identifier
*
* @param	msDelay				delay between each thread "execution" call of IRunnable.process(), in milliseconds
*
* @param	msTimeout			the max amount of time this PseudoThread should run before it will
* 								stop processing and dispatch an ErrorEvent. If no timeout is specified
* 								the process will run until the IRunnable reports that it is complete.
*
* */
this.runnable = runnable;

if (msTimeout != -1) {
if (msTimeout < msDelay) {
throw new Error("PseudoThread cannot be constructed with a timeoutMS that is less than the delayMS");
}
maxRunTimes = Math.ceil(msTimeout / msDelay);
}

this.intTimer = new Timer(msDelay,maxRunTimes);
}

/**
* Destroys this and deregisters from the Timer event
* */
public function destroy():void {
this.intTimer.stop();
this.intTimer.removeEventListener(TimerEvent.TIMER,processor);
this.runnable = null;
this.intTimer = null;
}

/**
* Called each time our internal Timer executes. Here we call the runnable's process() function
* and then check the IRunnable's state to see if we are done. If we are done we dispatch a complete
* event. If progress is made we dispatch progress, lastly on error, this will destroy itself
* and dispatch an ErrorEvent.<BR><BR>
*
* Note that an ErrorEvent will be thrown if a timeout was specified and we have reached it without
* the IRunnable reporting isComplete() within the timeout period.
*
* @throws ErrorEvent when the process() method encounters an error or if the timeout is reached.
* @param	e TimerEvent
* */
private function processor(e:TimerEvent):void {
try {
this.runnable.process();
this.totalTimesRan++;

} catch(e:Error) {
destroy();
this.dispatchEvent(new ErrorEvent(ErrorEvent.ERROR,false,false,"PsuedoThread ["+this.myName+"] encountered an error while" +
" calling the IRunnable.process() method: " +e.message));
return;
}

if (runnable.isComplete()) {
this.dispatchEvent(new Event(Event.COMPLETE,false,false));
destroy();
} else {

if (this.maxRunTimes != 0 && this.maxRunTimes == this.totalTimesRan) {
destroy();
"timeout exceeded before IRunnable reported complete"));
return;

} else {
this.dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS,false,false,runnable.getProgress(),runnable.getTotal()));
}
}
}

/**
* This method should be called when the thread is to start running and calling
* it's IRunnable's process() method until work is finished.
*
* */
public function start():void {
this.intTimer.start();
}

}
}


TestRunnable

TestRunnable is an example of a very basic IRunnable implementation. TestRunnable’s process method simply increments a counter each time it is called by the PseudoThread. Once it gets to 100, the unit of work is complete. Again this is a very simple example but you could implement an IRunnable who’s process() method does considerably more complex work.

package org.bitsofinfo.thread
{

public class TestRunnable implements IRunnable
{

private var counter:int = 0;
private var totalToReach:int = 100;

public function TestRunnable() {

}

public function process():void {
counter++;
}

public function isComplete():Boolean {
return counter == totalToReach;
}

public function getTotal():int
{
return this.totalToReach;
}

public function getProgress():int
{
return this.counter;
}

}
}


main.mxml

main.mxml brings it all together and runs a TestRunnable via a PseudoThread and displays the progress on the screen as well as allowing you to restart/start the simple test.

<?xml version="1.0" encoding="utf-8"?>
creationComplete="reset()" viewSourceURL="srcview/index.html">

<mx:Script>
<![CDATA[

var runnable:IRunnable;

try {
} catch(e:Error) {
// thread might already be destroyed due to actually being finished vs pressing reset in the middle
}
}

}

private function createRunnable():IRunnable {
runnable = new TestRunnable();
return runnable;
}

private function start():void {
}

private function handleComplete(e:Event):void {
this.progBar.setProgress(100,100);
this.progress.text = runnable.getTotal().toString();
progBar.label= "CurrentProgress" + " 100%";
}

private function handleProgress(e:ProgressEvent):void {
progBar.label= "CurrentProgress" + " " + Math.ceil(e.bytesLoaded/e.bytesTotal *100) + "%";

}

private function reset():void {
}

this.progBar.setProgress(0,100);
this.progBar.label =  "CurrentProgress" + " 0%";

this.progress.text= this.runnable.getProgress().toString();
this.totalWork.text = this.runnable.getTotal().toString();
}

]]>
</mx:Script>

<mx:Label x="10" y="14" text="Total work:"/>
<mx:Label x="125" y="14" text="Progress:"/>
<mx:Label x="83" y="14" width="30" id="totalWork" visible="true"/>
<mx:Label x="184" y="13" width="39" id="progress" />
<mx:Button x="249" y="11" label="Start" width="67" click="start()"/>
<mx:Button x="324" y="11" label="Reset" width="67" click="reset()"/>
<mx:ProgressBar id="progBar" x="10" y="40" width="425"
minimum="0" visible="true" maximum="100" label="CurrentProgress 0%"
direction="right" mode="manual" />

</mx:Application>


Hopefully this post was of some help to those of you who have a need for threading like behavior in ActionScript, Flex or basic AS3. Again, this post was recently updated and now you can checkout the source for the PseudoThread at Google Code.

I also apologize for not being able to just show the working example directly here in this post. WordPress.com does not permit embeds!