Getting a Reference to the DisplayList in FlexUnit 4.1 Unit Tests

Although it’s generally frowned upon, sometimes the code under test needs to gain a reference to the Stage and or DisplayList.  In my case I was unit testing a component which listened for children being added and removed from the DisplayList.

The following methods takes advantage of FlexUnit 4.1′s UIImpersonator Class which will provide access (and helper methods) for interacting with the DisplayList.  In order to use this, you must invoke the ‘flex’ flavour of FlexUnit (ie: include flexunit-4.1.0-8-flex_4.1.0.16076.swc in your library path.)

// You must include the (ui) annotation to inform FlexUnit that 
// you require access to the DisplayList.
[Before (ui)]
public function setup() : void
{
	// UIImpersonator requires an instance of UIComponent; it's a shame it 
	// doesn't just use `DisplayObject`
	_container = new UIComponent();
 
	// Gain a reference to the Stage.
	UIImpersonator.addChild(_container);
 
	// We can now create our client under test and supply a Stage reference.
	_instance = ExampleClientUnderTest();
	_instance.setStage(_container.stage);
}
 
// Again, don't forget the (ui) annotation.
[After (ui)]
public function teardown() : void
{
	// Don't forget to clean up the DisplayList once you're done :)
	UIImpersonator.removeChild(_container);
}

At this point I’m still not sure how you can gain reference to the DisplayList in a ‘pure’ AS3 FlexUnit 4.1 TestRunner; if you do then please leave a comment below! :)

Posted in ActionScript 3 | Leave a comment

Getting Python and Fabric Installed on Windows

Amazon’s Simple Storage Solution (S3) has changed the way the Internet works, but getting files onto it isn’t as straightforward as a simple SCP. This tutorial will show you how to setup Fabric and get some files up onto S3.

Getting Fabric Setup

Fabirc is lightweight deployment toolkit – the closet analogy that I can draw is that it’s the Apache ANT of deployment. Fabric makes it easy to create an interactive script that will guide you (or others!) through the steps involved in getting your application (and all of its supporting files) onto remote servers.

So, let’s get started; If you are starting from scratch on Windows then you will want to go ahead and install python, come back when you’re done :)

Now that you have python installed, you’ll want to get hold of Setup Tools which makes it easy to download and update python modules. Once installed, you will want to add your Python Directory/scripts folder added to your system path. Once done, you can just issue:

easy_install Fabric

However, if like me, you are rocking all this on windows, then you will be informed that Fabric has failed to install with the following error message:

error: Unable to find vcvarsall.bat

Luckily, this is not a show stopper, you just need to grab MinGW, add it to your PATH and then modify your distutils.cfg file to point to it – once you’ve done that Fabric will install just fine :)

Once Fabric is installed you can summon it by issuing `fab` at the command line. Again if you’re on Windows you may be greeted with a nasty stack trace ending with:

ImportError: No module named win32api

Don’t worry, this one’s simple as well – just go and grab PyWin32 extensions and you’ll be on your way :) (BTW: Who said development on Win32 was difficult ;)

fab-installed-win32

Writing Your First Fabric Script

So now you have fabric installed it’s time to roll up our sleeves and start writing out first fabric script. By convention, fabric scripts should be named `fabfile.py`, just in the same way that you name your ANT script `build.xml`, so let’s create a one:

from fabric.api import *
from fabric.contrib.console import confirm
 
def deploy() :
	puts("Hello World!")

You can now invoke it by issuing the following at the command line (ensuring your are in the same directory you’ve saved your fabfile.py script).

fab deploy

fab-hello-world

Getting Some S3 Action With Boto

Python really is awesome, not only is it a very well thought out language, but you can also get hold of a module for nearly anything! Point in case, Boto is a Python library for interacting with Amazon Web Services; so let’s get it installed so we can use it in our Fabric script!

easy_install boto

Well that was easy ;)

Posted in Uncategorized | Tagged , , , | Leave a comment

Installing YUM on a Centos 5 VPS

I’ve had to do this a couple of times now, so, mainly to save myself the effort next time, here’s how to get YUM up an running on a CentOS 5 VPS.

Download the following RPMs from a CentOS Mirror, making sure you match your architecture (eg: x86_64, or i386). If the mirror doesn’t contain the exact version listed below you should be OK grabbing a newer one :)

  • libxml2-2.6.26-2.1.2.8.el5_5.1.x86_64.rpm
  • m2crypto-0.16-6.el5.8.x86_64.rpm
  • python-elementtree-1.2.6-5.x86_64.rpm
  • python-iniparse-0.2.3-4.el5.noarch.rpm
  • python-sqlite-1.1.7-1.2.1.x86_64.rpm
  • python-urlgrabber-3.1.0-6.el5.noarch.rpm
  • rpm-python-4.4.2.3-22.el5.x86_64.rpm
  • sqlite-3.3.6-5.x86_64.rpm
  • yum-3.2.22-33.el5.centos.noarch.rpm
  • yum-fastestmirror-1.1.16-14.el5.centos.1.noarch.rpm
  • yum-metadata-parser-1.1.2-3.el5.centos.x86_64.rpm

Once you’ve downloaded them all, install them using the following command:

rpm -Uvh *.rpm

Have fun :)

Posted in Uncategorized | Tagged , , | Leave a comment

Converting XML into Objects – Data Marshalling in ActionScript 3

Data Marshalling is a common task that nearly every ActionScript 3 developer will face at some point; put simply it is the process of converting an Object into a data interchange format (for example XML, JSON or AMF) and likewise converting it back into an Object that your application can use again. This tutorial will focus on XML.

Data Modelling

So let’s start nice and simple, with the XML that we want to unmarshall into an ActionScript Object – this could be coming from a local file, or from a server (referred to as an endpoint).

The SlideShow XML Document

<slideshow title="LolCats">
	<slide url="http://checkmybelly.com/wp-content/uploads/2007/11/lolcat-funny-picture-moderator1.jpg" caption="Moderator Kitteh" />
	<slide url="http://www.lolcats.com/images/u/07/24/lolcatsdotcom5x02srq751692std.jpg" caption="Wait... I'll fix it" />
	<slide url="http://icanhascheezburger.files.wordpress.com/2007/01/i-can-has-cheezburger.jpg" caption="Can Has Cheezburger?" />
</slideshow>

So, we need to start by looking at what Objects we create when the parse this XML. This one is quite easy; the XML document defines a Slideshow which contains a number of slides; with this in mind it would seem appropriate that we create two Classes, one which represents a single Slide, and another which represents the entire SlideShow.

The Slide model is straight forward as it just needs to contain the URL of the image and the caption; both of these can be represented as Strings which keeps everything very straight forward:

The Slide Model Object

package slideshow.model
{
	public class Slide
	{
		private var url : String;
		private var caption : String;
 
		/**
		 * Creates a new Slide Model Object which represents a single image in a SlideShow.
		 * 
		 * @param url The URL of the image which makes up this Slide.
		 * @param caption Text which accompanies this Slide.
		 */
		public function Slide(url : String, caption : String) {
			// Ensure this object does not get instantiated with invalid data.
			if (url == null) throw new ArgumentError("url must not be null");
			if (caption == null) throw new ArgumentError("caption must not be null");
 
			this.url = url;
			this.caption = caption;
		}
 
		/**
		 * The URL of the image which makes up this Slide.
		 */
		public function getUrl() : String {
			return url;
		}
 
		/**
		 * Text which accompanies this Slide.
		 */
		public function getCaption() : String {
			return caption;
		}
 
		public function toString() : String {
			return "[Slide url=" + url + ", caption='" + caption + '"]';
		}
	}
}

The model is nice and straight forward; there are a couple of points to note from the design of my Slide Model Object:

  • The URL and Caption properties are passed in the constructor; this way I can ensure that my Slide Model is immutable and can not be changed once is has been created.
  • When the URL and Caption are supplied in the constructor I perform a null reference check to ensure that non-null values were passed; this is important because it means that any other object (known as a “client”) which makes use of my Slide object knows that it will never get a null value back from the getUrl() and getCaption() methods.
  • The Slide Model provides a toString() method – this will be called automatically whenever a Slide model object is concatenated to a String – for example in a trace() statement – this will aid debugging and development.

Next up is the SlideShow model; we know from the XML that a SlideShow has a title and a number of Slides; my SlideShow Class looks like this:

The SlideShow Model Object

package slideshow.model
{
	public class SlideShow
	{
		private var title : String;
		private var slides : Array;
 
		/**
		 * Represents a collection of Slide images which make up a SlideShow.
		 * 
		 * @param title Description of this SlideShow.
		 * @param slides Array of Slide model instances which make up this Slideshow. 
		 */
		public function SlideShow(title : String, slides : Array) {
			// Ensure this object does not get instantiated with invalid data.
			if (title == null) throw new ArgumentError("title must not be null");
			assertSlides(slides);
 
			this.title = title;
			this.slides = slides.concat();	// Take a defensive copy.
		}
 
		/**
		 * Custom assertion method which ensures that the supplied Slide array is in a valid state.
		 */
		private function assertSlides(slides : Array) : Array {
			if (slides == null) throw new ArgumentError("slides must not be null");
 
			// Check that the supplied Slides array contains only Slide models.
			for each (var slide : Slide in slides) {
				if (slide == null) throw new ArgumentError("slide array must only contain instances of slideshow.model.Slide."); 
			}
 
			// Everything is OK, return the supplied Slides array for convenience.
			return slides;
		}
 
		/**
		 * Description of this SlideShow.
		 */
		public function getTitle() : String {
			return title;
		}
 
		/**
		 * An Array of Slide model instances which make up this SlideShow, note that this is a copy, so any changes
		 * made will not persist.
		 */
		public function getSlides() : Array {
			return slides.concat();		// Return a defensive copy.
		}
 
		public function toString() : String {
			return "[SlideShow title='" + title + "', slides={" + slides.join(", ") + "}]";
		}
	}
}

Like the Slide model, the SlideShow model is immutable; it achieves this by ensuing that all of the data that it encapsulates (contains) can not be modified once the object has been constructed and that all the supplied data is valid upon construction; as we saw in the Slide model, this is nice and easy with String values, however, as you can see from the SlideShow class definition; it’s a bit trickier to achieve this with an Array as it’s a complex data type.

  • First, in the constructor, we ensure that the supplied slides Array is valid; as this is more involved than a simple null check, we pass it off to a helper function, assertSlides() – if assertSlides() encounters invalid data, it will throw an Error which will prevent the instance from being constructed.
  • Next, we take a defensive copy of the supplied slides Array with the line: this.slides = slides.concat(). This is to prevent modifications to the supplied slide array from modifying the state of our SlideShow model object, here’s an example of this in action:

The Dangers Of Not Taking Defensive Copies of Complex Data Types

// Create a new Array of Slide models.
const slides : Array = new Array();
slides.push(new Slide("http://img.com/cat.png", "A Cat"));
slides.push(new Slide("http://img.com/dog.png", "A Dog"));
 
// Create a new SlideShow.
const slideShow : Slideshow = new SlideShow("Animals", slides);
 
// Outputs [SlideShow title='Animals', slides={
//      [Slide url=http://img.com/cat.png, caption='A Cat'], 
//      [Slide url=http://img.com/dog.png, caption='A Dog']
// }]
trace(slideShow);
 
// Add a new slide to our slides Array - should this change the contents of the SlideShow model?
slides.push(new Slide("http://img.com/car.png", "A Car (not an animal!)"));
 
// Yes it does! Our SlideShow model object now looks like this:
// [SlideShow title='Animals', slides={
//      [Slide url=http://img.com/cat.png, caption='A Cat'], 
//      [Slide url=http://img.com/dog.png, caption='A Dog'],
//      [Slide url=http://img.com/car.png, caption='A Car (not an animal!)']
// }]
trace(slideShow);
  • We also return a defensive copy of the slides Array in the getSlides() method – this is done for exactly the same reason – if we didn’t return a defensive copy then our SlideShow model would no longer be immutable, for example, what would happen to our SlideShow model if the client called: slideShow.getSlides().length = 0?

UnMarhshalling – Converting the XML into a Model Object

OK, so now we have both our transmission format (XML) and our ActionScript Model Objects (SlideShow and Slide) which represent the data in our application – let’s look at how we go from one to the other (and back again!); let’s start by unmarshalling – converting from the transmission format to the ActionScript Objects – this will be handled by our SlideShowMarshaller.

The XMLSlideShowMarhshaller Class

package slideshow.model
{
	public class XMLSlideShowMarshaller implements SlideShowMarshaller
	{
		/**
		 * Converts the supplied SlideShow transmission format document into a SlideShow Model object.
		 */
		public function unmarshall(transmissionFormat : *) : SlideShow {
			// First we need to convert the incoming transmission format data to an XML Object so we can parse it.
			const slideShowXML : XML = new XML(transmissionFormat);
 
			// Now we can parse the data...
			const title : String = slideShowXML.@title;
			const slides : Array = parseSlides(slideShowXML..slide);
 
			// Ensure that the require attributes have been set.
			if (title == "") throw new Error("SlideShow XML was missing @title attribute");
 
			// And finally return the new SlideShow model object.
			return new SlideShow(title, slides);
		}
 
		/**
		 * Parses an Array of Slide model objects from the supplied XMLList, if there are no slides in the supplied
		 * XMLList, an empty Array will be returned.
		 */
		private function parseSlides(slidesXML : XMLList) : Array {
			const slides : Array = [];
			for each (var slideNode : XML in slidesXML) {
				// As the Slide model will throw an error if supplied with invalid data, we need to wrap it in a 
				// try/catch block and log that an error occured - note that we do not consider this to be "fatal"
				// to the Unmarshalling operation as we can recover from it (skip over the offending slide).
				try {
					slides.push(new Slide(slideNode.@url, slideNode.@caption));
				}
				catch (e : Error) {
					trace("Failed to parse Slide node: " + slideNode.toXMLString());
				}
			}
			return slides;
		}
	}
}

Note how our XMLSlideShowMarshaller implements the SlideShowMarshaller interface; this is done so we can create future implementations should we wish to change our transmission format. The XMLSlideShowMarshaller class is pretty straight forward, first it converts the incoming raw data into an XML Object, and then it sets about creating and returning a new SlideShow instance. Should anything go awry during this process, an Error will be thrown which the Client will need to handle. Talking of Clients, let’s take a look at the Service object which will make use of our SlideShowMarshaller:

The SlideShowLoaderService Class

package slideshow.service
{
	// imports omitted...
 
	public class SlideShowLoaderService extends EventDispatcher
	{
		private var loader : URLLoader;
		private var slideShow : SlideShow;
		private var slideShowMarhsaller : SlideShowMarshaller;
 
		/**
		 * Static factory method which should be used to load XML SlideShow Data.
		 */
		public static function createXMLLoader() : SlideShowLoader {
			return new SlideShowLoader(new XMLSlideShowMarshaller());
		}
 
		/**
		 * Creates a new SlideShowLoaderService which will use the supplied SlideShowMarshaller object to convert the
		 * loaded data into a SlideShow model.
		 * 
		 * @param slideShowMarhsaller Converts the raw data at the service endpoint into a SlideShow model object.
		 */
		public function SlideShowLoader(slideShowMarhsaller : SlideShowMarshaller) {
			this.slideShowMarhsaller = slideShowMarhsaller;
		}
 
		/**
		 * Begins the load operation; if the load operation is successful Event.COMPLETE will be dispatched, should it
		 * fail, ErrorEvent.ERROR will be dispatched.
		 * 
		 * @param endpointUrl URL which returns the SlideShow transmission data which will be converted into a 
		 * SlideShow Model object.
		 */
		public function load(endpointUrl : String) : void {
			// Clear out any pre-existing state.
			slideShow = null;
 
			loader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onLoaderComplete);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onLoaderError);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoaderError);
 
			try {
				loader.load(new URLRequest(endpointUrl));
			}
			catch (e : Error) {			{
				handleError(e.message);
			}
		}
 
		private function onLoaderComplete(event : Event) : void {
			removeLoaderListeners();
 
			// Use our marshaller to create the SlideShow model instance from the loaded data.
			try {
				slideShow = slideShowMarhsaller.unmarshall(loader.data);
				handleComplete();
			}
			catch (e : Error) {
				handleError("Marshalling error: " + e.message);
			}
		}
 
		private function removeLoaderListeners() : void {
			loader.removeEventListener(Event.COMPLETE, onLoaderComplete);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onLoaderError);
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoaderError);
		}
 
		private function onLoaderError(event : ErrorEvent) : void {
			removeLoaderListeners();
			handleError("Loading error: " + event.text);
		}
 
		private function handleError(message : String) : void {
			dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
		}
 
		private function handleComplete() : void {
			dispatchEvent(new Event(Event.COMPLETE));
		}
 
		/**
		 * Returns a SlideShow model object which was parsed from the service endpoint; note that this method will 
		 * always return null unless a succesful call to load() was made.
		 */
		public function getSlideShow() : SlideShow {
			return slideShow;
		}
	}
}

The SlideShowLoaderService class provides a clean and simple Facade to ActionScript’s own URLLoader class and our SlideShowMarshaller class; it serves as a specialisation of these two objects, providing a simple interface which only deals with loading, and marshalling from the Slide Show transmission format into a SlideShow Model Object; the Client (the class which makes use of the SlideShowLoaderService) doesn’t need to know that a URLLoader or an XMLSlideShowMarshaller are being used.

One interesting choice about the design of the SlideShowLoaderService is the way that the default constructor requires the Client to supply an instance of the SlideShowMarshaller interface. The reason is does this is to make the SlideShowLoader as flexible as possible; if we are loading our SlideShow data from XML, then we would invoke it like so:

Creating a SlideShowLoaderService instance which works with XML

const slideShowLoader : SlideShowLoaderService = new SlideShowLoaderService(new XMLSlideShowMarhshaller());
slideShowLoader.addEventListener(Event.COMPLETE, onSlideShowLoaderComplete);
slideShowLoader.addEventListener(ErrorEvent.ERROR, onSlideShowLoaderError);
slideShowLoader.load("slideshow.xml");

Likewise, if we needed to work with a JSON service endpoint, we could modify our client code to provide a JSONSlideShowMarshller (of course, you would need to create this class first!) – but you will notice that the SlideShowLoader works in exactly the same way!

Creating a SlideShowLoaderService instance which works with JSON

const slideShowLoader : SlideShowLoaderService = new SlideShowLoaderService(new JSONSlideShowMarhshaller());
slideShowLoader.addEventListener(Event.COMPLETE, onSlideShowLoaderComplete);
slideShowLoader.addEventListener(ErrorEvent.ERROR, onSlideShowLoaderError);
slideShowLoader.load("slideshow.json");

To make the developer’s life easier, we supply a Static Factory Method, SlideShowLoaderService.createXMLLoader() – this means the Client doesn’t have to know that they need to provide an XMLSlideShowMarhshaller instance in the constructor, the difference is subtle, but it makes it much easier to use:

Creating a SlideShowLoaderService instance using the Static Factory Method

const slideShowLoader : SlideShowLoaderService = SlideShowLoaderService.createXMLLoader();
slideShowLoader.addEventListener(Event.COMPLETE, onSlideShowLoaderComplete);
slideShowLoader.addEventListener(ErrorEvent.ERROR, onSlideShowLoaderError);
slideShowLoader.load("slideshow.xml");

 

Marhshalling – Converting the Model Object into XML

OK, so now we’ve seen how to unmarshall the transmission format into an ActionScript Object, let’s look at how to do the reverse and convert our Object back into the transmission format so we can send it over to a server. As a side note, you may know this concept as serialisation; however there is a very subtle difference between the two (at least according to the Java world); in my own view, serialisation concerns converting the object into a ByteArray (raw bytes) which is transmitted to the service layer, whereas marshalling deals with converting the object into a transmission format (which in itself is turned into raw bytes, but by another layer). This aside, lets look at how we get our SlideShow model back into XML; as we are still dealing with the marshalling process, let’s add a new method to our XMLSlideShowMarshaller in the form of marshall(slideshow):

Adding the marshall Method to XMLSlideShowMarshaller

// ... rest of class omitted for brevity
 
/**
 * Converts the supplied SlideShow model object into an XML representation.
 */
public function marshall(slideShow : SlideShow) : * {
	const result : XML = <slideshow title={slideShow.getTitle()} />;
	for each (var slide : Slide in slideShow.getSlides()) {
		result.* += <slide url={slide.getUrl()} caption={slide.getCaption()} />;
	};
	return result;
}

By making use of E4X we make light work of creating the XML representation of the Slideshow; this is also helped by the fact that we have guaranteed immutability of both the SlideShow and Slide objects, we know they are both in a valid state which certainly makes things easier and more concise.

Making use of this marhshall() method is nice and straight forward; all we need to do is pass a populated SlideShow model and we get the XML back:

Invoking the SlideShow Marshaller

// Create a SlideShow Model object instance.
const slideShow : SlideShow = new SlideShow("LolCats", [
	new Slide("http://checkmybelly.com/wp-content/uploads/2007/11/lolcat-funny-picture-moderator1.jpg", "Moderator Kitteh"),
	new Slide("http://www.lolcats.com/images/u/07/24/lolcatsdotcom5×02srq751692std.jpg", "Wait… I'll fix it"),
	new Slide("http://icanhascheezburger.files.wordpress.com/2007/01/i-can-has-cheezburger.jpg", "Can Has Cheezburger?")
]);
 
// Convert the SlideShow Model object to our transmission format.
const xml : XML = new XMLSlideShowMarshaller().marshall(slideShow);
 
// Outputs:
// <slideshow title="LolCats">
//    <slide url="http://checkmybelly.com/wp-content/uploads/2007/11/lolcat-funny-picture-moderator1.jpg" caption="Moderator Kitteh"/>
//    <slide url="http://www.lolcats.com/images/u/07/24/lolcatsdotcom5×02srq751692std.jpg" caption="Wait… I'll fix it"/>
//    <slide url="http://icanhascheezburger.files.wordpress.com/2007/01/i-can-has-cheezburger.jpg" caption="Can Has Cheezburger?"/>
//</slideshow>
trace(xml.toXMLString());

To wrap up the marshalling phase, let’s have a look at a potential client, for this example I’ve created a SlideShowSaverService which could be used to transmit a user generated SlideShow to a server.

The SlideShowSaverService Class

package slideshow.service
{
	// imports omitted...
 
	public class SlideShowSaverService extends EventDispatcher
	{
		private var loader : URLLoader;
		private var slideShow : SlideShow;
		private var slideShowMarshaller : SlideShowMarshaller;
 
		/**
		 * Static factory method which will transmit the SlideShow to the service endpoint as XML.
		 */
		public static function createXMLSaver(slideShow : SlideShow) : SlideShowSaverService {
			return new SlideShowSaverService(slideShow, new XMLSlideShowMarshaller());
		}
 
		/**
		 * Creates a new SlideShowSaverService which will send the supplied slideShow Model Object to a service endpoint
		 * in the transmission format dictated by the supplied SlideshowMarshaller.
		 *
		 * @param slideShow The SlideShow instance to transmit to the service endpoint. 
		 * @param slideShowMarhsaller Converts the SlideShow model object into a transmission format.
		 */
		public function SlideShowSaverService(slideShow : SlideShow, slideShowMarshaller : SlideShowMarshaller) {
			this.slideShow = slideShow;
			this.slideShowMarshaller = slideShowMarshaller;
		}
 
		/**
		 * Contacts the Service Endpoint; if the operation is succesful Event.COMPLETE will be dispatched, should the
		 * operation fail, ErrorEvent.ERROR will be dispatched.
		 * 
		 * @param endpointUrl URL to transmit the marhshalled SlideShow Model object to.
		 */
		public function save(endpointURL : String) : void {
			const request : URLRequest = createURLRequest(endpointURL, slideShowMarshaller.marshall(slideShow));
 
			loader.addEventListener(Event.COMPLETE, onLoaderComplete);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onLoaderErrror);
			loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoaderErrror);
			loader.load(request);
		}
 
		/**
		 * Creates a URLRequest object which will be used by the URLLoader instance, this default implementation
		 * will make use of a POST request, the body of which will be the transmission data format. 
		 */
		protected function createURLRequest(endpointURL : String, data : *) : URLRequest {
			const request : URLRequest = new URLRequest(endpointURL);
			request.method = URLRequestMethod.POST;
			request.data = data;
			return request;
		}		
 
		private function onLoaderComplete(event : Event) : void {
			removeLoaderListeners();
			dispatchEvent(new Event(Event.COMPLETE));
		}
 
		private function removeLoaderListeners() : void {
			loader.removeEventListener(Event.COMPLETE, onLoaderComplete);
			loader.removeEventListener(IOErrorEvent.IO_ERROR, onLoaderErrror);
			loader.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoaderErrror);
		}
 
		private function onLoaderErrror(event : ErrorEvent) : void {
			removeLoaderListeners();
			handleError("Loader error: " + event.text);
		}
 
		private function handleError(message : String) : void {
			dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, message));
		}
	}
}

 

Next Steps

To complete this example I’ve created a simple GUI which allows you to see the SlideShowLoaderService and SlideShowMarshaller in action, you can download the complete project here; to recompile the project you will need to modify the user.properties file and point the FLEX_HOME property at your Flex SDK. It makes use of Keith Peter’s excellent MinimalComps UI library.

There are plenty of avenues to explore from here as this has just scratched the surface; you could start by extending the application to load, and marshall JSON data; prehaps taking advantage of the Adobe JSON Serialisation library (part of AS3 CoreLib), or you could reduce the amount of code you need to write by annotating your Model with Metadata and using an automatic marshalling library like ASAXB. I hope to cover these topics in later blog posts (time permitting :)

Posted in ActionScript 3 | Tagged , , | Leave a comment

Eventual Assertions in FlexUnit 4

After a conversation with a work colleague about EventuallyMatchers in Specs (a BDD Testing Framework for Scala). The basic idea behind Eventually Matchers is that you have a condition you with to assert against which won’t be met until some time in the future. For example, a Tween will take some time to complete and you want to check that the target MovieClip has reached a specific position. Using FlexUnit 4′s Async.delayCall() you can create a test which meets this condition, it would look something like this:

[Test (async)]
public function spriteTweensToTargetPosition() : void
{
	// This is the client class which is under test.
	const shape : MovingShape = new MovingShape();
 
	// This is where we expect the Shape to end up.
	const expectedPosition : Point = new Point(300, 200);
 
	// This function will be invoked when the Async.delayCall() time elapses.
	const assertionCallback : Function = function() : void {
 
		// Check to see if the shape is at the expected position.
		Assert.assertEquals("Shape is at the expected x position", expectedPosition.x, shape.x);
		Assert.assertEquals("Shape is at the expected y position", expectedPosition.y, shape.y);
 
	};
 
	// OK, let's get this shape moving.
	shape.tweenTo(expectedPosition);
 
	// Wait for 1000ms and then invoke the assertionCallback function.
	Async.delayCall(this, assertionCallback, 1000);
}

So, the above test passes, but according to the Test Runner it took 1.05 seconds to run – that’s not so good. The reason for this is because the Async.delayCall() will wait until the supplied delay value (1000) has elapsed before making the assertions defined in the assertionCallback. The EventuallyMatchers improve upon this situation by constantly polling the assertion until it is either eventually true (in which case the test passes) or the timeout arrives (in which case the test fails). Here’s the same testcase again but making use of my own bash at an EventuallyMatcher in ActionScript:

[Test (async)]
public function spriteTweensToTargetPosition() : void
{
	const shape : MovingShape = new MovingShape();
	const expectedPosition : Point = new Point(300, 200);
 
	shape.tweenTo(expectedPosition);
 
	assertEventuallyEquals(this, "Shape is at the expected x position", expectedPosition.x, function() : * { 
		return shape.x; 
	});
	assertEventuallyEquals(this, "Shape is at the expected y position", expectedPosition.y, function() : * { 
		return shape.y; 
	});
}

This testcase only takes 0.26 seconds to execute which is great, but legibility has suffered a fair bit due to the rather clunky way we declare closures in ActionScript. I’ve pushed this code to my FlexUnit branch on github; hopefully a cleaner syntax can be worked out, or someone else finds it useful :)

Posted in ActionScript 3 | Tagged | 1 Comment

Delcare Your FLEX_HOME Environment Variable in Windows

When you compile your Flash applications using ANT, you’ll often come across the fun problem of having to point to a Flex SDK to get access to the MXMLC, COMPC and ASDOC jars. One approach is to simply hard-code the location of the SDK into the ANT file; sure, it will work for you, but it’s not going to work for anyone else :)

A quick and easy solution is to simply create a new Environment Variable, named FLEX_HOME which points to your working Flex SDK – in Windows 7 you can do this easily by selecting:

Right Click My Computer -> Properties -> Advanced System Settings -> Environment Variables

Now enter a new User variable called FLEX_HOME which points to your Flex SDK folder.

flex-home-env-variable-windows

Once you’ve done this, you can verify it has worked by issuing the following command on the Command Prompt:

echo %FLEX_HOME%

Now, all you have to do to reference your Flex SDK path in your ANT script is to include the following line:

<property environment="env" />
<taskdef resource="flexTasks.tasks" classpath="${env.FLEX_HOME}/ant/lib/flexTasks.jar" />
Posted in ActionScript 3, Windows | Leave a comment

Maven and ANT – Managing Your Flash Project’s Build Dependencies

Project build dependency management and resolution is one of the more difficult problems you’ll face as your project grows in size; however even the smallest of projects (and teams) can benefit greatly from getting automatic dependency resolution in place.

So What Are My Project’s Build Dependencies?

Most of us are aware of dependencies in object orientated programming – these are the objects that our class in question needs to operate and most of us know the design patterns which we can use to externalise these dependency. Project build dependencies aren’t radically different; instead of referring to objects and instances; we are talking about the source code files (.as) that your project needs when it compiles. Any source code that you haven’t directly written for your project is a build dependency, here’s an example:

A project with a build dependency in FDT

hardcoded-build-dependency

In the screenshot above you can see an example of a (very simple!) project which makes use of TweenLite. However, you can also see that the source files (.as) for the TwenLite library have been copied into the source folder (src). Now if this were a real project it would result in the greensock code also being committed to our SVN repo. So, what’s the problem with this? Here’s a couple of potential issues:

  • The project compilation time will be increased as MXMLC will be forced to recompile all the greensock code
  • Developers need to checkout all the source code for TweenLite even tho they will never be editing it – furthermore, some developers may get over excited and decide to start making modifications to this code (at which point it stops being a 3rd party library!)
  • If your project consists of multiple modules (ie: Other SWFs which are loaded at runtime) you will need to make sure they all have exactly the same copy of the TweenLite source code available on the source-path due to the way Flash manages loaded Class Definitions in LoaderContexts.

Using Linked Resource Folders To Share Dependencies Across Projects

Nearly all IDEs allow you to create Linked Resource Folders; the concept is pretty simple – projects can import other projects source folders to allow them to share code – sounds great – however in practice it can cause lots of headaches!

An example of Linked Resource Folders in FDT 4

build-dependencies-linked-libraries

In the above screenshot you can see three projects:

  • 3rdparty – This project doesn’t compile or create anything, it simply serves as a dumping ground for all application’s shared dependencies, in this case, TweenLite.
  • main – This is our application’s Main project (hence the name!) this makes use of TweenLite and also loads in other module SWFs at runtime.
  • module – This is a module which the Main application will load in at runtime – it also makes use of TweenLite (let’s face it, what Flash app doesn’t!)

Both the ‘main’ project and the ‘module’ project make use of a Linked Resource named ‘ThirdParty’ which in turn resolves to the location of the ’3rdparty’ project in our workspace. This allows them to include the TweenLite source code without having to copy/paste it into each project. This solves one of the major problems we’ve outlined above – all our application’s projects (including the modules) will now make use of the exact same version of their dependencies thanks to the ‘ThirdParty’ Linked Resource folder – also, when we want to update to a newer version of a library we just have to update the library in a single place and recompile everything – easy.

However, apart from not solving the other two issues (slower compilation and the fact we are checking in raw source code that we don’t wish to maintain) we have also just created a new, much uglier problem with our project – it’s no longer easy to build!

When creating a large project you should always strive to make the build as simple and easy as possible; I try and keep the following things in mind:

  • You should be able to check the entire application’s source out of version control with a single command; no more.
  • You should be able to create a fresh build of the application (including all modules) with a single command (eg: by issuing ant package from a fresh checkout of the source code
  • Developers should be able to work on the project using whichever IDE or tool they wish; don’t rely on a particular environment use, such as FlashBuilder or FDT

By using linked resources we have broken these rules – the whole Linked Resource concept is tightly coupled to a given IDE; even if you check in all your .project and .settings files it isn’t going to work if someone decides they want to give IntelliJ a spin.

SWCs To The Rescue!

When ActionScript 3 became available, Adobe provided Flash developers with a new tool, the SWC. SWCs are just zip files in disguise (if you don’t believe me, rename the extension from .swc to .swc.zip and then open it) which contain a SWF file and an XML catalouge which allows your IDE to parse all the class definitions the SWF contains. All the major Actionscript IDEs provide tools for working with SWC files; below is an example of the same project making use the greensock.swc file which is included in the TweenLite bundle.

A project making use of a SWC in FDT 4

hardcoded-build-dependency-swc

SWCs are preferable to just dumping the source code into your project for a number of reasons – infact they solve nearly all the points we listed above…

  • Compilation becomes faster as SWCs are already pre-compiled
  • Instead of checking the entire source tree of the 3rd party library into SVN we are now only checking a single, compressed file – this makes checkout faster and also means that developers won’t be able to start modifying the library.

But one thing is not checked off – what about projects which make use of multiple modules – it would appear we still have the same problem that all of our modules must use the exact same version of the library – now you could just solve this by making use of a LinkedResource which points to a bunch of SWCs but that’s still not great; and when it really comes down to it – should these SWCs really be in version control at all – after all you are in not in control of their development and you don’t decide when they get updated.

Automatically Managing Your SWCs with Maven

So, it’s now becoming clear that you and your application have some serious dependency issues when it comes to 3rd Party SWCs; don’t worry, the first step is admission – let’s start by declaring them. This article is going to focus on using Maven to declare and resolve your project’s dependencies – other solutions are available :)

Maven’s dependency management work on the simple premise that the dependencies your application relies upon (in our case, SWCs) exist out on the Internet on a special type of file server, known to Maven as a Maven Repository. Maven Repositories can either be public facing (in the case of the Central Maven Repo.) or internal on a company’s own Intranet. Maven Repositories sole purpose is to house and catalogue build artefacts so that they can be fetched (resolved) during a project’s build. Instead of checking your applications dependencies into version control, you instead just list the dependencies in your project and then Maven will fetch them when required.

So, let’s start with a very simple application which consists of a single project which has a single build dependency on AS3Commons Logging. (I would have used TweenLite as an example, but it’s not available on any public Maven repositories). The first thing we need to do is get a simple build script on the go – I’m going to use ANT to perform the build (Maven, which describes itself as a project management tool is more than capable of both compiling and managing your project’s dependencies, but this article is is just focuses on using Maven for managing dependencies). Maven and ANT get along just fine (although their user’s doing always see eye to eye on the Internet!); all we need to do is grab a copy of the Maven ANT Tasks JAR, add it to our project and reference it in our ANT Script:

A Skeleton ANT Build Script Which Makes Use Of the Maven ANT Tasks

<project name="maven-dependencies" xmlns:artifact="antlib:org.apache.maven.artifact.ant">
 
	<!-- Inclde the Maven ANT Tasks -->
	<path id="maven-ant-tasks.classpath" path="maven-ant-tasks-2.1.1.jar" />
	<typedef resource="org/apache/maven/artifact/ant/antlib.xml" 
		uri="antlib:org.apache.maven.artifact.ant" 
		classpathref="maven-ant-tasks.classpath" />
 
	<!-- Include the FlexSDK ANT Tasks -->
	<taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" /> 
</project>

In the example above I have copied the maven-ant-tasks.jar file into my project; however another approach is to copy the maven-ant-tasks.jar file into your ANT_HOME folder (if you’re on Windows this will be Users{username}.antlib). For more information on getting the Maven ANT Tasks setup on your machine, please refer to the Maven ANT Tasks Installation Documentation.

Now that we have access to the Maven ANT Tasks in our application’s build, the next thing we want to do is list, and resolve our dependencies. This is accomplished by in the “resolve” target shown below:

The Resolve ANT Target which Lists and Pulls Down Dependencies

	<!-- ================================= 
          target: resolve
          Uses the Maven ANT Tasks to define and resolve all the dependencies require to build
          this application.               
         ================================= -->
	<target name="resolve" description="Resolve the project's dependencies">
 
		<!-- The pathId value 'resolves.swcs.classpath' will be an ANT FileSet which points to all the 
			SWC files we are about to define -->
		<artifact:dependencies filesetId="resolved.swcs.classpath" versionsId="resolved.swcs.versions">
 
			<!-- This is where we list our dependency on as3commons-logging version 2.0; by adding this
				line here, we are telling Maven that our application depends upon this SWC -->
			<dependency groupId="org.as3commons" artifactId="as3commons-logging" type="swc" version="1.2" />
 
			<!-- This is where we provide Maven with the URL of the remote repository where some, or all of
				our dependencies can be retrieved from - if you work with a team you will probably want to 
				setup your own Maven Repository in house -->
			<remoteRepository id="adobe-opensource" url="http://opensource.adobe.com/svn/opensource/cairngorm3/maven-repository" />
 
		</artifact:dependencies>
 
		<!-- Copies all the files resolved in the task above into the "libs" folder -->
		<copy todir="libs">
			<fileset refid="resolved.swcs.classpath" />
 
			<!-- This Mapper will remove all the folder heirarchy and version numbers from the resolved SWCs --> 
			<mapper classpathref="maven-ant-tasks.classpath" classname="org.apache.maven.artifact.ant.VersionMapper"
				from="${resolved.swcs.versions}" to="flatten" />
		</copy>
	</target>

The above target breaks down into two major parts – the artifact:dependencies task lists and resolves the project’s dependencies and the copy task then copies these dependencies into the “libs” folder in the project. The two interesting lines int he artifact:dependencies task are the dependency line which lists as3commons-logging as a dependency (note how we specify the type as “swc” (Maven defaults the type to “jar”) and the version at 1.2). and the remoteRepository line which tells Maven which Maven Repository the dependency should be resolved from – in this project’s case we are using Adobe’s OpenSource Maven Repository; however as mentioned in the comments, you will probably want to create and maintain your own Maven Repo to house your project’s artifacts in (I’m hoping to cover how to setup your own Repo in another post).

Right, if you’re still following then it’s time to play along at home. Start off by downloading the above project. Once you have extracted the zip file have a quick peek inside an notice how there is no as3commons-logging.swc (if you’re using an IDE, it should complain about errors in Main.as as it can’t resolve the import statements). This is the missing dependency that Maven will resolve for us.

To compile the project (and generate Main.swf in the “target” folder, issue:

ant build

The ANT output should show that the as3commons-logging SWC was fetched (it will also complain that the as3commons-logging POM file could not be resolved, you can ignore this one as it would appear Adobe forgot to include it in the repo!). If you now have a peek inside the “libs” folder you should find a single file, as3commons-logging.swc – magic!

Next Steps

The above is really just the tip of the iceberg; if you want to really get to grips with dependency management through Maven then you are going to want to start listing your dependencies (and the Maven Repositories they can be resolved from) in a POM file (Project Object Model). POM files not only serve as a place to list dependencies and the URLs of Repositories, but they can define the entire build cycle of the project when using Maven (and in the case of Flash, FlexMojos) to compile. POM files include an inheritance model (so a Modules’ POM file can extend the main Project’s POM file) allowing you to keep all your dependency definitions in a central place.

Also, this tutorial hasn’t touched on one of the most powerful feature of Maven, transitive dependency resolution. A quick example would be if your project depends on the RobotLegs Framework; from the example above you can see how you could define a dependency on RobotLegs:

<dependency groupId="org.robotlegs" artifactId="robotlegs" type="swc" version="1.4.0" />

Now, you would expect Maven to pull down RobotLegs.swc for you – but those of you familiar with RobotLegs will remember that RobotLegs itself has a dependency upon SwiftSuspenders.swc – Maven will automatically pull down both RobotLegs.swc AND the required version of the SwiftSuspenders.swc for you, even tho you only listed RobotLegs as a dependency! However, in order for this to work, RobotLegs needs to be uploaded to a Maven Repo along with a POM file which lists SwiftSuspenders as a dependency (and where it can be fetched from in turn) – The Java community is all over this and it works like magic – unfortunatley the Flash community is lagging quite far behind – it would be amazing if FlashDevs started pushing their SWCs up to the Central Maven Repo (it would certainly save people from having to setup and maintain their own local repos!)

Posted in ActionScript 3 | Tagged , , | 3 Comments

FlexUnit 4 assertAfter Async Helper

Update: Ah, there we go, there was a native method in FlexUnit for this! You can instead make use of Async.delayCall().

One of the things I aim for when writing unit tests is to make the test cases as easy as possible to read. One way I achieve this is by reducing the amount of “clutter” code which can creep in; this is especially true when working with asynchronous test cases as you often end up having to create a Timer object to perform the assertion for you.

The following helper method, assertAfter, hides away all the clutter and aims to make your async test case as clean as possible. It achieves this by encapsulating all the Timer and callback logic into a single function.

package uk.co.jonnyreeves.flexunit
{
	import org.flexunit.async.Async;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
 
	/**
	 * FlexUnit 4.1 Async Testcase helper which will invoke the supplied assertion delegate function after a delay.
	 * 
	 * @param testCase The TestCase instance, supplied to Async.handleEvent; 99% of the time you will just want
	 * to pass 'this' when invoking the function.
	 *
	 * @param delayInMs Delay in milliseconds before the supplied assertion delegate function will be invoked 
	 * and your TestCase completes.
	 *
	 * @param assertionDelegate Function reference which will be invoked after the supplied delay has elapsed.  This 
	 * function should expected zero arguments and perform all your assertion logic.
	 * 							
	 * @example The following code provides an example of how to use this method from within a FlexUnit 4.1 TestCase:
	 * <listing version="3.0">
	 * 		[Test (async)]
	 * 		public function performAsyncTestcase() : void {
	 * 			const startTime : int = getTimer(); 
	 * 			
	 * 			assertAfter(this, 500, function() : void {
	 * 				assertTrue("Some time has passed!", getTimer() > (startTime + 300));
	 * 			});
	 * 		}
	 * </listing>
	 * 
	 * @author Jonny Reeves - http://jonnyreeves.co.uk
	 */
	public function assertAfter(testCase : Object, delayInMs : uint, assertionDelegate : Function) : void
	{
		const assertionTimer : Timer = new Timer(delayInMs, 1);
		Async.handleEvent(testCase, assertionTimer, TimerEvent.TIMER_COMPLETE, function(event : Event, passThru : Object) : void {
			assertionTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, arguments["callee"]);
			assertionDelegate.apply(); 
		}, delayInMs + 500);
		assertionTimer.start();		
	}
}

Here’s an example TestCase which makes use of the assertAfter function:

package uk.co.jonnyreeves.flexunit
{
	import org.flexunit.asserts.assertTrue;
	import flash.utils.getTimer;
 
	public class TestAssertAfter
	{
		[Test (async)]
		public function performAsyncTestcase() : void
		{
			const startTime : int = getTimer();
 
			assertAfter(this, 500, function() : void {
				assertTrue("Some time has passed!", getTimer() > (startTime + 300));
			});
 
		}
	}
}

You can download these two files right here.

As a side note, I really dislike the concept of the passThru object which gets supplied when you use FlexUnit 4′s Async.handleEvent() – I don’t really see the point in using it (and it adds a lot of clutter to the code) when you could just use an inline function instead.

Posted in ActionScript 3 | Tagged , , | Leave a comment

Revisiting the Builder Pattern in ActionScript for Immutable Models

A while back I made a post on using the Builder Pattern to create Fluent Constructors – the principle being that instead of having a Model object with a bajillion (in practice, more than 3) arguments, you make use of a companion Builder class which creates the instance. Now, the implementation of this pattern in ActionScript 3 is always going to be a little bit ‘unique’ as we lack useful constructs such as private constructors; however, over the past few months I have been making use of these Builders and have settled at the following design:

The Model Object

package nutrition.model {
	public class NutritionFacts {
		private var _servingSize : uint;
		private var _servings : uint;
		private var _calories : uint;
		private var _fat : uint;
		private var _salt : uint;
		private var _carbohydrate : uint;
 
		/**
		 * Static construction method which returns a NutritionFactsBuilder which you can use to create your instance
		 * of NutritionFacts model object in a fluent fashion.
		 */
		public static function builder(servingSize : uint, servings : uint) : NutritionFactsBuilder {
			return new NutritionFactsBuilder(servingSize, servings);
		}
 
		/**
		 * Please make use of NutritionFacts.builder() instead of using this Class constructor.
		 * @private
		 */
		public function NutritionFacts(builder : NutritionFactsBuilder) {
			_servingSize = builder._servingSize;
			_servings = builder._servings;
			_calories = builder._calories;
			_fat = builder._fat;
			_salt = builder._salt;
			_carbohydrate = builder._carbohydrate;
		}
	}
}

This model object is then accompanied by the Builder which is referenced in the static factory method NutritionFacts.builder(). This class is package-internal so it can not be instantiated by the client (presuming the client is outside the nuturion.model package that is!) – as a result it can only be accessed via the static factory method NutritionFacts.builder().

The Companion Builder Object

package nutrition.model {
	internal class NutritionFactsBuilder {
		internal var _servingSize : uint;
		internal var _servings : uint;
		internal var _calories : uint;
		internal var _fat : uint;
		internal var _salt : uint;
		internal var _carbohydrate : uint;
 
		public function NutritionFactsBuilder(servingSize : uint, servings : uint) {
			_servingSize = servingSize;
			_servings = servings;
		}
 
		public function withCalories(value : uint) : NutritionFactsBuilder {
			_calories = value;
			return this;
		}
 
		public function withFat(value : uint) : NutritionFactsBuilder {
			_fat = value;
			return this;
		}
 
		public function withSalt(value : uint) : NutritionFactsBuilder {
			_salt = value;
			return this;
		}
 
		public function withCarbohydrate(value : uint) : NutritionFactsBuilder {
			_carbohydrate = value;
			return this;
		}
 
		public function build() : NutritionFacts {
			return new NutritionFacts(this);
		}
	}
}

Finally, we can see an example of the Builder being used in the following client class – notice how the client requests an instance of the NutritionFactsBuilder via the static builder() method – it is forced to do this because the NutritionFactsBuilder class is package-internal so it can not instantiate it.

An Example of a Client object using the Companion Builder

package nutrition {
	import nutrition.model.NutritionFacts;
 
	public class Client {
		const colaNutritionFacts : NutritionFacts = NutritionFacts.builder(330, 1)
			.withCalories(303)
			.withSalt(0)
			.build();
	}
}

You can download the example code above as a .zip file right here.

Posted in ActionScript 3 | Tagged , , , | 1 Comment