Displaying Animated GIFs in Flex

This morning, I found myself wanting to add a nice-looking, but quick loading indicator into a Flex application. In the Ajax world, it’s simple…just use an animated GIF that can be downloaded from any number of sites. In Flex, it’s not quite that easy. The default Image component in Flex does not support animated images, nor does Flex itself.

A quick Google search turned up the as3gif library, which provides support for playing animated GIFs. The download did not include a SWC, so I pulled the source code into Flex Builder and quickly compiled one, which I then included in my Flex project.

To enable animated GIF images, I extended the Image component to utilize as3gif as follows:

package iamjosh.samples.components
{
	import flash.net.URLRequest;
	
	import mx.controls.Image;
	import mx.core.UIComponent;
	
	import org.gif.player.GIFPlayer;

	public class AnimatedGIFImage extends Image
	{
		private var _gifImage  : UIComponent;
		
		public function AnimatedGIFImage()
		{
			super();
			this._gifImage  = new UIComponent();
		}
		
		override public function set source(value : Object) : void
		{
			if (!value is String)
			{
				throw new ArgumentError("Source must be of type String");
			}
			
			super.source = value;
		}
		
		override protected function createChildren() : void
		{
			super.createChildren();
			var player : GIFPlayer = new GIFPlayer();
			player.load(new URLRequest(this.source as String));
			this._gifImage.addChild(player);
		}
		
		override protected function updateDisplayList(unscaledWidth : Number, unscaledHeight : Number) : void
		{
			this.addChild(this._gifImage);
			super.updateDisplayList(unscaledWidth, unscaledHeight);
		}
	}
}

This class simply pulls in the source for the image and then utilizes the as3gif library. Using the AnimatedGIFImage component is as simple as:

<components:AnimatedGIFImage source="assets/images/loading.gif"/>

Although I have not tested it thoroughly, the class should also support the basic capabilities of the Image component as well.


Adding Ant to Flex Builder 3

I wanted to use Cairngen in a recent project and quickly noticed that the standalone version of Flex Builder 3 does not have Ant support available by default.  Getting it set-up is pretty easy though:

  1. In Flex Builder, Help -> Software Updates -> Find and Install…
  2. Select “Search for new features to install” and click Next
  3. Pick “The Eclipse Project Updates” and click Finish
  4. Expand “The Eclipse Project Updates” and “Eclipse 3.3.2”
  5. Select “Eclipse Java Development Tools 3.3.2…” and click “Finish”
  6. When prompted, select “Install All”
  7. Restart Flex Builder

When Flex Builder starts up again, you will have Ant support available (e.g. any build.xml files will have a little ant on the icon).  You can also verify by selecting Window -> Other Views… and checked if an Ant directory exists.


Embedding Flash in Flex

I recently ran into user interface design that included a component better built in Flash than Flex due to the high degree of interaction required (my time is short these days as well, so one of our designers will be building it). This raised the question of how to embed a Flash movie in a Flex application and enable interaction between the two.

This is actually fairly straightforward when working with Flash Player 9 and ActionScript 3. I started by building a very simple Flash component (I know nothing about Flash) – it simply contains a slider and a label that changes with the value of the slider:

My goal is to embed this component in a simple Flex application that can read/display the current value of the slider.

Next, I created a new Flex application and included both the SWF and FLA file for my Flash component in the “src/assets” directory. I then used a SWFLoader to load the Flash component into the application and position it properly on the screen. I also added a few simple Flex components to display the currently selected value, etc.:

Now, we need to wire everything together. To do this, we need access to the Flash component from the SWFLoadervia the content property. With access to the component, we have access to public properties/methods, can listen for events, etc. In fact, to synchronize the currently selected value between Flash and Flex, the slider in the Flash component will dispatch an event on change that the Flex component listens for. Pertinent code snippets:

Flash Action Code (remember, I’m not a Flash programmer):

slider1.addEventListener(SliderEvent.CHANGE,dispatchSliderEvent);
function dispatchSliderEvent(evt : SliderEvent) : void
{
    dispatchEvent(new SliderEvent(SliderEvent.CHANGE, evt.value, null, null));
}
// returns the current value of the slider
function get sliderValue() : Number
{
    return slider1.value;
}

Flex

<mx:Script>
<![CDATA[
    import mx.events.SliderEvent;
    private var _mainTimeline : *;
    [Bindable] private var _sliderValue  : Number = 0;

    private function swfLoaded(event:Event) : void
    {
        this._mainTimeline = this.swfLoader.content;
        this._mainTimeline.addEventListener(SliderEvent.CHANGE, updateValue);
        this.updateValue();
    }

    private function updateValue(evt : Event=null) : void
    {
        this._sliderValue = this._mainTimeline.sliderValue;
    }
]]
</mx:Script>

<mx:SWFLoader id="swfLoader" y="73" x="10" source="assets/Simple Flash Component.swf"
    complete="swfLoaded(event);"/>

Two items of note:

  • I did not explicitly assign a type to the _mainTimeline object in order to be able to arbitrarily call methods on it (e.g. no compile-time checking)
  • There is a strange problem in trying to directly call the _mainTimeline.sliderValue() method in which the Flash component did not render properly, hence why I used an intermediate variable (_slideValue).

That’s it, it really is fairly straightforward. Although I have not tested it yet, Flex should be able to set values in the Flash component in much the same way.

References


Data Services with Server-Side Validation

Out of the box, Flex provides a set of great validators for client-side validation of form input (e.g. for phone numbers), but for instances in which we need to involve the server, things become a bit trickier. Before we get into the how though, a quick discussion of the why. There are numerous situations in which server-side validation is not only nice, but a must. Consider an application that asks users to register themselves. The application might ask the user to create a username, but that username must be unique. We don’t want to send our entire list of username to the client, so instead we’ll utilize validation code on the server. In a previous post, I detailed my approach for server-side validation.

In general, the design follows a similar pattern to Rails – we store a map of errors in an object within the model object itself. Persistent classes that implements the Validateable interface can be validated by our framework and an instance of ValidateableErrors will be injected into the object with a map of validation errors. If the validation framework encounters an error, it halts execution and sends the invalid object (with errors) back to the client.

Once Flex receives the updated object, the application needs to be able to display those errors. To do this, we’ll utilize a custom implementation of the mx.validators.Validator class. Before we dig into the validator class, let’s take a quick look at the ActionScript implementation of the ValidateableErrors class:

    [Bindable]
    public class ValidateableErrors
    {
        private var _errors : Object;

        public function ValidateableErrors(errors : Object) : void
        {
            this._errors = errors;
        }

        public function getFieldErrors(field : String) : Array
        {
            return this._errors[field] == null ?
                [] : [ this.createValidationResult(this._errors[field]) ];
        }

        private function createValidationResult(msg : String) : ValidationResult
        {
            return new ValidationResult(true, "", "SERVER_ERROR", msg);
        }
    }

The first thing to note is that instead of using a Dictionary, we are in fact just using a plain old object as this is how LCDS deserializes Java Maps on the Flex side. Each of the keys in the map are now properties for this object. We can this utilize the “[]” notation to retrieve the value of a given property. The validation message is wrapped in a ValidationResult object, which is utilized by the validator to display error messages in the UI.

Let’s now take a quick look at the validator implementation:

    public class ServerErrorValidator extends Validator
    {
        private var _errors : ValidateableErrors;
        public var field : String;

        public function ServerErrorValidator()
        {
            this._errors = null;
            super();
        }

        public function set errors(errors : ValidateableErrors) : void
        {
            this._errors = errors;
            validate();
        }

        override protected function doValidation(value : Object) : Array
        {
            return this._errors.getFieldErrors(this.field);
        }
    }

Our validator simply accesses the ValidateableErrors object referenced by the “errors” property for a given field. It then displays the error message via the return ValidationResult object. We can make this a clearer by looking at an example:

    <validation:ServerErrorValidator id="firstNameValidator" field="firstName"
        errors="{ this._user.validationErrors }" listener="{ this.firstName }"/>
    <validation:ServerErrorValidator id="lastNameValidator" field="lastName"
        errors="{ this._user.validationErrors }" listener="{ this.lastName }"/>

    <mx:Label x="10" y="10" text="User Validation Test" fontSize="16" color="#FFFFFF" fontWeight="bold"/>
    <mx:Panel x="10" y="42" width="480" height="200" layout="absolute" title="Create User">
        <mx:Label x="10" y="10" text="First Name:"/>
        <mx:Label x="10" y="36" text="Last Name:"/>
        <mx:TextInput x="127" y="8" id="firstName"/>
        <mx:TextInput x="127" y="34" id="lastName"/>
        <mx:Button x="385" y="128" label="Create" click="createUser()"/>
    </mx:Panel>

The User instance (“_user“) is defined elsewhere. Although not ideal, we do need to instantiate one validator per field even though we only reference a single object. The response from the data service’s “createItem” method is an updated version of the user object with the associated validation errors. Flex takes care of updating the UI appropriately to display the errors.

This implementation has worked well thus far for my purposes; however, I do see room for improvement in displaying multiple errors messages per field and in making the solution as a whole more flexible. I do welcome feedback.


Aspect Oriented Validation in Java

This will be the first of a two part series that discusses my approach towards validation in a data service application. The first part (this post) will cover the server-side aspects of the validation framework and the second (coming soon, I hope) will detail how validation information is shared with the Flex application.

In designing the validation component, I wanted the following:

  1. Little to no impact on business logic (e.g. no validation code inline with business logic)
  2. Minimal configuration
  3. Able to send validation errors to Flex client

The first design principal lends itself to aspect oriented programming, which enables us to handle “cross-cutting” concerns (see my previous post for more details). In short, we’ll be implementing a “Validator” class (an aspect) that is called upon to validate persistent objects whenever a create or update method is called in the data access layer. For this application, I have used Spring with @AspectJ annotations to build AOP components and have previously documented details on the AOP configuration for the Validator.

For the most part, the Validator class is fairly straightforward, with the exception of it being Spring application context aware (e.g. it has access to our Spring configuration). By making the Validator context aware, we can configure validation beans via Spring and dynamically load them as needed.

    @Aspect
    public final class Validator implements ApplicationContextAware
    {
        private ApplicationContext appContext;

        @Around("iamjosh.samples.util.SystemArchitecture.onCreateOrUpdate()"
            + " && args(validateable)")
        public void validate(ProceedingJoinPoint called, Validateable validateable) throws Throwable
        {
            // returns simple name, e.g. "user"
            String beanType = validateable.getSimpleName();

            // try to load a validator bean for this object
            org.springframework.validation.Validator validator
                    = this.loadValidatorBean(beanType);
            // if we didn't get a validator back, stop trying to validate
            if (validator == null) return;

            // run the validation
            ValidateableErrors errors =
                new ValidateableErrors(validateable, beanType);
            validator.validate(validateable, errors);

            // check the result of the validation -- if there are errors, assign
            // them to the validateable object
            if (errors.hasErrors())
                validateable.setErrors(errors);
            else
                // proceed if valid, be sure to pass the validateable on
                called.proceed(new Object[] { validateable });
        }

        // need to implement this method to be application context aware
        public void setApplicationContext(ApplicationContext applicationcontext) throws BeansException
        {
            this.appContext = applicationcontext;
        }

        private org.springframework.validation.Validator loadValidatorBean(String validateableBeanName)
        {
            String validatorBeanName = validateableBeanName + "Validateable";
            org.springframework.validation.Validator validator = null;
            try
            {
                validator =
                    (org.springframework.validation.Validator)this.appContext.getBean(validatorBeanName);
            }
            catch(NoSuchBeanDefinitionException nsbde) { // do something }
            catch(BeansException be) { // do something }
            return validator;
        }
    }

In this case, I am favoring the idea of convention over configuration. The naming convention for my validator beans should be “modelClassNameValidator” or “userValidator” for the User class. This keeps things simple. In the future, I plan to add an option to override this default.

I won’t go into the details of the ValidateableErrors class, but it is just a wrapper around Spring’s BindingResult class that defers all method calls and adds a few others. For those familiar with Rails, this class and its relationship to the model are very similar to the Errors class in ActiveRecord classes. Each validateable model class has an “errors” property that references a ValidateableErrors object – this is what is eventually passed to Flex (more on this in a future post).

Any persistent model that is to be validated by our validation framework must implement the Validateable interface and extend the BaseValidateable abstract class.

Finally, a quick discussion of how the validation rules are defined. I wanted to avoid mixing validation code with business logic and partially achieved this by utilizing AOP to call my validation framework. But I also wanted to avoid defining validation rules in code as this can be become cumbersome and create extraneous classes. To that end, I chose to utilize the Valang validation language, which is part of the Spring Modules library, a set of extension to Spring. Details on Valang can be found in the references below, but it allows us to write succinct validation rules as part of the Spring configuration. For the user class our Valang code looks like this:

    <bean id="userValidator" class="org.springmodules.validation.valang.ValangValidator">
        <property name="valang">
            <value>
                <![CDATA[
                    { firstName : ? is not blank : 'First name is blank' : 'first_name_empty' }
                    { firstName : length(?) < 30 : 'First name too long' : 'first_name_length' : 30}
                    { lastName  : ? is not blank : 'Last name is blank' : 'last_name_empty' }
                    { lastName  : length(?) < 50 : 'Last name too long' : 'last_name_length' : 50 }
                    { email     : ? is not blank : 'E-mail is blank' : 'email_empty' }
                    { email     : email(?) == false : 'E-mail is invalid' : 'email_invalid' }
                    { email     : ? is blank or length(?) > 3 : 'E-mail is too short' : 'email_to_short' }
                ]]>
            </value>
        </property>
    </bean>

By naming the validation bean “userValidator” the validation framework will automatically identify this bean as the validation bean for the User class. We can then apply whatever Valang rules are deemed necessary by our requirements to implement server-side validation. Any errors are then inserted into the Validateable object as a ValidateableErrors object that will be sent back to Flex.

References


Flex in Application Logging

For an LCDS application that we are building, I wanted to be able to display log messages to the screen, such as “Sending request to server” and “Received server response: OK.” Although this has little to do with actual functionality, I wanted to document my efforts to create this component.

To utilize the Flex logging framework, we need to provide a Logger and a Log Target. The Logger, of course, does the logging itself based on two factors: (1) its category and (2) the logging level. This is similar to the operation of the popular Java logging framework Log4J. The Log Target defines where the messages are written. Flex comes with the TraceTarget predefined – this is the target for all trace() statements. For this example, I will also provide an MXML component that can be used to display log messages on screen.

First, the Logger class:

    public class Logger
    {
        //~ Instance Attributes -----------------------------------------------
        private var logger : ILogger;

        //~ Constructor -------------------------------------------------------
        /**
         * SingletonEnforcer parameter ensures that only the getInstance
         * method can create an instance of this class.
         */
        public function Logger(category : String, enforcer : SingletonEnforcer) : void
        {
            this.logger = Log.getLogger(category);
        }

        //~ Methods -----------------------------------------------------------
        public static function getInstance(category : String) : Logger
        {
            return new Logger(category, new SingletonEnforcer());
        }

        public static function addTarget(target : ILoggingTarget) : void
        {
            Log.addTarget(target);
        }

        public static function removeTarget(target : ILoggingTarget) : void
        {
            Log.removeTarget(target);
        }

        public function debug(message : String) : void
        {
            this.logger.debug(message);
        }

        // other logging methods by level (e.g. warn, error)

    }

With our Logger class in place, we can now define a LogTarget class that defines a TextArea to which the log messages will be written:

    // be sure to use the mx_internal namespace (and import it)
    import mx.core.mx_internal;
    use namespace mx_internal;

    public class LogPanelTarget extends LineFormattedTarget
    {
        private var console : TextArea;

        public function LogPanelTarget(console : TextArea)
        {
            super();
            this.console = console;
        }

        override mx_internal function internalLog(message : String) : void
        {
            this.console.text += message + "\n";
            }
        }
    }

Finally, our LogPanel MXML component brings everything together by (1) instantiating a new Logger and (2) providing a TextArea for log messages:

<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
        width="300" height="300" initialize="init()">
    <mx:Script>
        <![CDATA[
            import mx.logging.Log;
            import mx.logging.LogEventLevel;
            import mx.collections.ArrayCollection;

            public  var open   : Boolean = true;
            private var target : LogPanelTarget;
            [Bindable] private var targets : ArrayCollection;

            private function init() : void
            {
                this.target = new LogPanelTarget(output);
                // here we define which categories are written to our target
                this.target.filters = ["iamjosh.samples.*"];
                // and here which log levels are written
                this.target.level   = LogEventLevel.ALL;
                this.target.includeCategory = true;
                this.target.includeTime = true;
                Logger.addTarget(this.target);
            }

            private function setVerticalPosition() : void
            {
                this.output.verticalScrollPosition =
                        this.output.maxVerticalScrollPosition + 1;
            }
        ]]>
    </mx:Script>

    <mx:TextArea  id="output" x="0" y="0" width="100%" height="100%"
            editable="false" updateComplete="this.setVerticalPosition()"
            verticalScrollPolicy="on"/>
</mx:Canvas>

We can now include the LogPanel component anywhere we wish and log messages from anywhere in our code within the category “iamjosh.samples.*” will be written to it. For example:

    public class Foo
    {
        // notice that we provide a category here, this determines if the log
        // message will be written to a give LogTarget
        private var logger : Logger = Logger.getInstance("iamjosh.samples.Foo");

        public function logSomething() : void
        {
            this.logger.debug("I log because I can");
        }
    }

That’s it. Although I would prefer to define where my log messages go external to the code, Flex’s logging framework is fairly straightforward and easy to work with.

References


Flex Custom Preloader

I was getting a little tired of the aqua loading screen that appears by default in all of my Flex applications, so I took a stab at building a custom preloader. A Flex application is really a two frame Flash movie, with the first frame containing all of the initialization and the second the application itself. The preloader is part of the initialization frame and we can use it to create a custom loading screen for our application. I found a few articles on the topic, with the most promising being this one from Ted on Flex.

I wanted my custom preloader to contain two elements: (1) a graphical logo and (2) a progress bar. Ted’s article provides information on loading the graphic (a PNG) by utilizing a subclass of flash.display.Loader. Because our preloader will perform its actions during the initialization frame, those handy graphical Flex classes (e.g. Image, ProgressBar) will not be available to us. Instead, we will need to create these items on our own.

If you would like to follow along, I have posted my complete source code. Please note that I embedded an MP3 in the application purely to increase its download size. I would recommend that you include a 2-3MB MP3 in your application, otherwise, the progress will not be noticeable.

To get started, we will extend the mx.preloaders.DownloadProgressBar class as suggested by Ted. As explained in the Flex documentation, the DownloadProgressBar can be extended to provide user feedback on the download and initialization phases of our Flex application. Also of note is that we need to implement it as an ActionScript class and not in MXML as the latter loads to slowly at runtime.

The CustomPreloader class is very much like Ted’s sample code, the exception being that as the SWF is loaded, we calculate the percent complete and update the progress value in our custom loading screen (LoadScreen):

    private function SWFDownloadProgress(event : ProgressEvent) : void
    {
        var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
        if (this.loader)
            this.loader.progress = prog;
     }

On initialization of the CustomPreloader, we also utilize a Timer to ensure the stage is available before we try to add and position the load screen:

    override public function initialize() : void
    {
        super.initialize();

        this.loader = new LoadScreen();
        this.addChild(this.loader);

        this._timer = new Timer(1);
        this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
        this._timer.start();
    }

From here, we extend flash.display.Loader to provide the utility for loading our logo image and drawing the progress bar. We do this by drawing both the logo and the progress bar on screen by creating a BitMap and then using the PNGEncoder to write the image to the screen as a PNG image. We are actually creating an animation on the fly here:

    public function refresh() : void
    {
        this._logoData = this.draw();
        var encoder : PNGEncoder = new PNGEncoder();
        var bytes   : ByteArray  = encoder.encode(this._logoData);
        this.loadBytes(bytes);
    }

    private function draw() : BitmapData
    {
        // create bitmap data to create the data
        var data : BitmapData = new BitmapData(this.width, this.height, true, 0);

        // draw the progress bar
        var s : Sprite = new Sprite();
        var g : Graphics = s.graphics;

        // draw the bar background
        g.beginFill(_BarBackground);
        g.lineStyle(2, _BarOuterBorder, 1, true);
        var barX : int = (this.width - _BarWidth) / 2;
        var barY : int = _TopMargin + _LogoHeight + _Padding;
        g.drawRoundRect(barX, barY, _BarWidth, _BarHeight, 2);
        var containerWidth : Number = _BarWidth - 4;
        var progWidth : Number = containerWidth * this.progress / 100;
        g.beginFill(_BarColor);
        g.lineStyle(1, _BarInnerColor, 1, true);
        g.drawRect(barX + 1, barY + 1, progWidth, _BarHeight - 3);
        data.draw(s);

        // draw the logo
        data.draw(this._logo.bitmapData, null, null, null, null, true);
        return data;
    }

To bring everything together, we are utilizing a Timer instance in our CustomPreloader class to update and redraw the progress bar on each timer tick. This calls the refresh() method in LoadScreen, which then redraws the an updated progress image. Now, we just need to add the following to our as an attirbute of the Application tag in our application MXML file to utilize the our custom preloader:

  preloader="iamjosh.samples.preloader.CustomPreloader"

Finally, let’s change the background color of the application to match our logo a little better. Just add the following Flex compiler argument:

  -default-background-color #FFFFFF

References

Update: I just found an article that accomplishes a similar task to my own buried in the comments of one of Ted’s articles. I was a little happier with how he handled the graphics of drawing the progress bar, so I have updated my code and added the article as a reference.