Flex’n'AIR
Learn and interact with other Flex professionals

(RED)Wire Teaser Site Released

The teaser site for the AIR application (called “(RED)Wire”) that I have been working tirelessly on for the last several months was just released this evening. Check it out at: http://www.getredwire.com

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on November 19th, 2008 :: Filed under General, News: Flex & Air, RIA News

Handling Advanced Item Renderers for List-based Components in Flex and AIR

Recently I was charged with the responsibility of creating a very complex visual interface in Flex that looks more like something you’d expect to see built with Flash because of the animation and 3D effects. Flex was clearly the better choice for developing this piece of the application, but I learned a number of things regarding the limitations of Item Renderers, particularly those having to do with the Flex TileList component.

The Requirement
The primarily component needed to display a tiled list of objects that represented a group of media objects. Each item renderer in the TileList had to have 3 images, each representing a different piece of media, and when the user hovered over one of the items, a parallel effect that combined one Zoom effect, 3 Move effects, and 2 Rotate effects. The top image ultimately needed to zoom in and have a DropShadow filter applied to it to give it a 3D-like effect, and the middle and bottom images needed to fan out to the left and right using the combined rotate and move effects on each one.

Getting the Data
Getting the data in the first place was a task in and of itself. My first several iterations of the code involved a lot of looping through the massive collection of media “packages” that is returned from the server, in order to get the sets of preview images from each media package object that i needed for the item renderers. I eventually came to realize that I could cut the amount of code I was using for this thing into a fraction by simply using the standard , with the data provider set to this massive collection of objects being sent from the server. This, however, required a complex and well-planned item renderer component written in ActionScript. The item renderer component extended the Flex TileListItemRenderer class and implemented the IListItemRenderer and IDropInListItemRenderer interfaces.

In this solution, each Item Renderer automatically receives one of the media package objects from the large collection that is sent from the server. This functionality is already built into the ListBase, so all I needed to do was find the array of images that from the object, then loop through the array and determine the “role” that each image should play in the item renderer (eg. top image, middle image, or bottom image) and discard anything else that I didnt need.

The Major Problem
The big problem I ran into, was the fact that the complicated effects that i built for the mouse over and mouse out required the item renderer display object to overlap the surrounding display objects in the tilelist. This, unfortunately, was completely impossible, and after studying all of the classes that TileList is extended from and how the TileList component automatically lays out the objects within the list, I found that it was impossible to prevent clipping of the images from occurring when the effects were generated.

The Quick-and-Dirty Solution
Due to time constraints, I needed a solution that i could implement quickly, and as long as it looked pretty, we were ok. In other words, an elegant hybrid component was simply not an option. I should also note that other possible solutions, like using a repeater with a Grid container, were not options either for reasons that are beyond the scope of this article/blog.

I created an mxml component based on the Canvas container that took 3 images as properties, dropped shadow filters on the images and included 2 parallel effects for the over and the out events. When the mouse over (or mouse out) occurs on an item renderer, this additional component that holds the effects is added to the stage with this.parentApplication.addChild(_effectContainer). So essentially, a new iteration of the item renderer that fired the event is being created as an overlay and the effect can then play and is free to run over any display objects in its way, since it is ultimately automatically added to the stage with an index that is higher than all other display objects on the stage.

In order to get this right however, the positioning of this canvas has to be pristine. In other words, when the new child (the effect container) with the duplicated images is added to the stage, the x,y coordinates of the initial state of the image stack (which is with only the top image displayed, assuming the other two images are of the same size and have the same x,y values) must be EXACTLY the same as the x,y position of the item renderer that generated the new instance of the display object responsible for displaying the effects. This ultimately makes it look as if the animation is playing on the actual item renderer, when in fact the item renderer is merely still lying directly beneath it’s double.

To be honest, the final product is pretty bad-ass and gives a flash-like quality to a data-driven Flex UI component. However, this is not the most elegant solution, as the ideal thing would be to create a hybrid TileList-like component that includes DYNAMIC layout constraints on each item renderer. Therefore, the component would automatically recognize that a display object inside of one of the item renderers was pushing on the boundaries of the container that was allocated to it and resize itself automatically until the animation stopped by placing calling super.invalidateProperties or super.updateDisplayList on the UIComponent class on each ENTER_FRAME event until the internal display objects of the item renderers stopped pushing on the layout bounds. There is a little caveat to this however, and that is - resizing the layout constraints of the item renderer must NOT change the layout of the component as you would expect. In other words, we could suspect that implementing such functionality into a hybrid TileList component would by default push the other item renderers around to compensate for the renderer that was resized. This assumes however, that we do NOT want the item renderer to overlap the surrounding renderers, which in the case of this requirement, is untrue. When the user rolls off the item renderer’s effect double, the rollover animation should basically play in reverse and then simply remove itself from the parent’s display list. Thus, the original layout of the TileList is never changed by the effects rendering.

My feeling is that we will build such a component eventually, probably for a future version of this application, but we’ve got a deadline to meet right now, and sometimes making the right business decision means quick and dirty is the answer.

As much as I’d love to actually show the code for this view state that I have described here, I must respect certain nondisclosure and intellectual property rights and restrictions considering the nature of the application we are building. However, I will provide a generalized code example of a specific element described in this article if there is something in particular that you would like to understand in greater detail by actually seeing it. I am very quick to respond to comments, so feel free to ask if there is anything in particular you would like to see.

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on November 10th, 2008 :: Filed under Adobe AIR Tutorials, Flex Topics & Commentary, Flex Tutorials, News: Flex & Air, Patterns & Best Practices
Tags :: , , , , ,

Streaming Video with the F4V File Format

Adobe’s long awaited update to the FLV streaming video format, now called F4V, has finally come to fruition. It is true that F4V was supported as of version 9.0.r115 of the Flash player, but options were extremely limited as far as how to encode a video in that format. Included with each version of Creative Suite 4 (and Flash CS4 if purchased separately) is what Adobe is referring to as “Adobe Media Encoder CS4″. This is a substantial upgrade to the original “Flash Video Encoder” that has been around since Flash 8 was released, and includes a number of enhancements and major bug fixes. The most notable of these is the ability to encode to the new F4V format, which uses the H.264 video codec. This means that we can stream our videos in HD using a native Adobe Flash video format. Word on the street is that Flash Media Server 3 will get a significant upgrade any day now to support streaming of F4V files. It is unknown at this time whether or not this upgrade will actually be referred to as FMS4.

To get started with the F4V format, simply open the Flash Media Encoder CS4 program, and click “Add”. Now select a video file. Select the first arrow icon under “Format”. You should see the following (Figure 1):

Figure 1: First, select a video file from your hard drive

Figure 1: First, select a video file from your hard drive

The file that I selected was a .MOV file. However, assuming I want to use the F4V file format, I need to have “FLV | F4V” selected. Next, click the arrow icon under “Preset”, and choose “Edit Export Settings…” (Figure 2).

Figure 2: Select "Edit Export Settings..." at the bottom of the drop down menu under "Preset"

After selecting the Edit Export Settings option, a new window is brought up with a wide array of settings to customize the encoding. This is where we really see the enhancements that have been made with the new encoder (figure 3).

Figure 3: A new windows is displayed when selecting the Edit Export Settings option

Figure 3: A new windows is displayed when selecting the "Edit Export Settings" option

Now select the “video” tab in the middle of the window (figure 4).

Figure 4: Selecting the Video tab reveals a number of customization options

Figure 4: Selecting the "Video" tab reveals a number of customization options

After you’ve finished customizing the encoding options, select “OK” and then “Start Queue”. Your video will now start encoding with the options you selected. It is worth noting that you can save your customizations as a preset for easy access later.

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 19th, 2008 :: Filed under Flash and Flash Video, RIA News, Reviews
Tags :: , , ,

Adobe Releases CS4

I’ve definitely had my hands full these last few days testing out the release of Creative Suite 4 and the new Adobe AIR, version 1.5 (not publicly available yet). I will publish information on the new version of AIR 1.5 after it has been released by Adobe. In the meantime, here is a summary of my findings with CS4 so far…

Adobe Creative Suite 4
Adobe is referring to CS4 as the company’s biggest release in its 25-year history. So far, I just might have to personally agree. Of particular interest, is the new 3D capabilities of Flash Pro CS4. Additionally, Photoshop CS4 Extended and Illustrator CS4 have both gotten upgrades to complement the new 3D capabilities of Flash.

Other new features of Flash include the “Bones” tool, which makes animating objects quicker and more realistic by creating relationships between connected objects using pivot points. For example, I could tell flash that my stick-man’s arm, forearm, and hand is connected and the elbow and wrist are the pivot point. I can then set certain parameters which let Flash know how these objects are related and what the movement restrictions are. Therefore, if my stick-man’s hand moves forward and up at an angle, the forearm and upper arm will automatically move with it. It’s pretty sweet once you figure out how to leverage the power of this tool.

Integration with Photoshop Extended and Illustrator has gotten better as well. For example, you can easily create a 3D object in Illustrator or Photoshop, and then Export it to Flash, where you can add your 3D animations to the object.

I anticipate publishing a number of articles and tutorials here as I continue learning how to leverage these knew features and enhancements, so be sure to stay tuned!!!

In the meantime, here is the AdobeTV broadcast, celebrating the release of CS4…

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 18th, 2008 :: Filed under Flex Topics & Commentary, General, RIA News, Reviews
Tags :: , ,

Simple Papervision3D


Seb Lee-Delisle - Papervision3D Simplified from Peter Elst on Vimeo.

This is an excellent session by Seb Lee-Delisle from the PaperVision3D team, at this year’s Flash on the Beach. Thanks to Peter Elst for posting this on his blog at peterelst.com.

Possibly Related Posts:

  • None found

Share/Save/Bookmark


Posted by Dan Orlando on October 15th, 2008 :: Filed under Actionscript 3D
Tags :: ,

Add Animated Transitions and Custom Navigation to Your Flex Viewstack Components

One of my biggest issues with the Flex Viewstack element is the lack of built-in transitions to choose from. So in this demonstration, I will show you how to create your own. We will first create a reusable animation factory class that we can call from anywhere in our application. Then, I will demonstrate how we can put the animation factory to work by creating a slide transition for a viewstack component. Note that Flex has a built in Slide object, and if you don’t mind mixing up your ActionScript behaviors with your MXML display, then that is also a viable option worth looking into for accomplishing the same end result. Just like anything you’ll find on this site though, we want to build abstraction and reusability into our code.

Step 1: Create the Animation Factory

Our first step is to create the animation factory class. We can instantiate this object from anywhere in an application and call the animateTo method, passing it the x, y position that we want it to end at, and the duration in milliseconds that we want the animation to last.

ObjectSlider.as

package {

   import flash.display.DisplayObject;
   import flash.events.Event;
   import flash.events.TimerEvent;
   import flash.utils.Timer;
   import flash.utils.getTimer;

   /**
    * @author Dan Orlando
    */
   public class ObjectSlider
   {
        // The object being animated
	private var _target:DisplayObject;
	 // Each time an animation starts we record its start time
	private var _startTime:Number;
	 // The duration of the animation in milliseconds
	private var _duration:Number;
	 // Record the target's start position
	private var _startX:Number;
	private var _startY:Number;
	 //  Record the difference between the starting and ending positions
	private var _deltaX:Number;
	private var _deltaY:Number;

	public function ObjectSlider() { }

   // Starts an animation that moves the target object from its current
   // position to the specified new position over a specified period of time.
	public function animateTo(target:DisplayObject, toX:Number,
           toY:Number, duration:Number):void {
	   //store where the target was when the animation started
	   _target = target;
	   _startX = _target.x;
	   _startY = _target.y;
	   // calculate difference between target's start position
           // and final destination
	   _deltaX = toX - _target.x;
	   _deltaY = toY - _target.y;
	   _startTime = getTimer();
	   //store how long the animation should take
	   this._duration = duration;
	   //update target's position each time a screen update occurs
	   _target.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
	}

   // Updates the target's position on each ENTER_FRAME event
	private function enterFrameHandler(event:Event):void {
	   var elapsed:Number = getTimer()- _startTime;
	   var percentDone:Number = elapsed/_duration;
	   if (percentDone < 1) {
	      updatePosition(percentDone);
	   }
	   else {
	      updatePosition(1);
	      _target.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
	   }
	}

   // Sets the position of the target object
	private function updatePosition(percentDone:Number):void {
	   _target.x = _startX + (_deltaX * percentDone);
	   _target.y = _startY + (_deltaY * percentDone);
	}

   }
}

Step 2: Create the MXML component
For our MXML display component, we will create a simple canvas that initializes a “helper” class that contains all of the behavior and functionality for the component in ActionScript. Note that when we instantiate the helper class, we pass it the current instance of our canvas component as a display object argument using the this keyword. We also place two left and right arrow buttons here, which we will use to move the viewstack back and forward by changing the selectedIndex value of the ViewStack when one of the buttons is clicked.

CustomCanvas.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="750" height="550"
   creationComplete="init()">
   <mx:Script>
      <![CDATA[
      import com.danorlando.util.ViewStackHelper;

      private var _helper:ViewStackHelper;

      private function init():void {
         _helper = new ViewStackHelper(this);
      }
      ]]>
   </mx:Script>

// place additional mxml components that should not be part
// of the viewstack here, like buttons, labels, etc...
   <mx:HBox x="693" y="56" horizontalGap="5">
      <mx:Button x="64" y="13" id="backBtn" styleName="iconButtonBack"
         width="16" height="16"/>
      <mx:Button x="85" y="13" id="forwardBtn" styleName="iconButtonForward"
         width="16" height="16"/>
   </mx:HBox>
</mx:Canvas>

ViewStackHelper.as

package com.danorlando.util
{
   import com.danorlando.display.components.CustomCanvas;
   import com.danorlando.effects.animation.ObjectSlider;
   import flash.display.DisplayObject;
   import flash.events.MouseEvent;
   import mx.containers.ViewStack;

   public class ViewStackHelper
   {
      private var _parent:CustomCanvas;
      private var _viewStack:ViewStack;
      private var _currentIndex:Number;
      private var _slider:ObjectSlider = new ObjectSlider();

      public function ViewStackHelper(canvas:Canvas) {
            _parent = object;
            addListeners();
            createChildren();
      }

   // add event listeners to the forward and back buttons
      public function addListeners():void {
       _parent.backBtn.addEventListener(MouseEvent.CLICK, viewStackBack);
       _parent.forwardBtn.addEventListener(MouseEvent.CLICK, viewStackForward);
      }

   // create and add the viewstack and it's children
      public function createChildren():void {
         _viewStack = new ViewStack();
         _parent.addChild(_viewStack);
         _viewStack.selectedIndex = 0;
         _viewStack.x = 39;
         _viewStack.y = 72;
         _viewStack.width = 675;
         _viewStack.height = 402;
         var vsChild1:Canvas = new Canvas();
         _viewStack.addChild(vsChild1);
      // add other components and params to the 1st index/child here
         var vsChild2:Canvas = new Canvas();
         _viewStack.addChild(vsChild2);
      // add additional components and params to the 2nd index/child here
         var vsChild3:Canvas = new Canvas();
         _viewStack.addChild(vsChild3);
      // add additional components and params to the 3rd index/child here
      // get the first child that is about to be displayed in the viewstack
         var curChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
      // set the x-position of the child to the x-pos of the viewstack + 600
         curChild.x = _viewStack.x + 600;
      // now slide the child into view
         _slider.animateTo(curChild, _viewStack.x-40, 0, 500);
      }

   // event handler for the back button in the parent container
      private function  viewStackBack(event:Event):void {
         if(_currentIndex > 0) {
            _currentIndex = _currentIndex - 1;
            var newChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
         // set the x-position of the new child 600 pixels to the right
            newChild.x = _viewStack.x + 600;
         // use the animateTo method of our animation factory to slide the new
         // child into position
            _slider.animateTo(newChild, _viewStack.x-40, 0, 500);
         // set the new index
            _viewStack.selectedIndex = _currentIndex;
         // set the forward button to visible if it is hidden
            if (!_parent.forwardBtn.visible) {
               _parent.forwardBtn.visible = true
            }
         // if the _currentIndex property is 0, then hide the back button
            if (_currentIndex == 0) {
                _parent.backBtn.visible = false;
            }
         }
      }

   // event handler for the forward button
      private function viewStackForward(event:Event):void {
         // get the highest index value of the viewstack
         var lastIdx:Number = _viewStack.numChildren-1;
         if(_currentIndex < lastIdx) {
            _currentIndex = _currentIndex + 1;
            var newChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
          // place the incoming child 600px to the left
            newChild.x = _viewStack.x - 600;
          // slide the new child into position using our animation factory
            _slider.animateTo(newFaq, _viewStack.x-40, 0, 500);
          // set the new index of the viewstack
            _viewStack.selectedIndex = _currentIndex;
          // make the back button visible if it is hidden
            if(!_parent.backBtn.visible) {
               _parent.backBtn.visible = true }
          // hide the forward button if we are at the last index
            if (_currentIndex == lastIdx) {
               _parent.forwardBtn.visible = false;
            }
         }
      }

   }
}

Ok, so we’ve got a few things going on here in the helper class. The first thing we do is set the Canvas object that was passed in the constructor to our local (i.e. private) canvas property which is of type CustomCanvas. We then add the event listeners to the forward and back buttons of the parent container - which is the Canvas object that was passed in the constructor - with the addListeners method. We then instantiate the ViewStack and add its children with the createChildren method. You will see the use of our animation factory with the call to _slider.animateTo. Notice that we are initially setting the position of the child off to the left or the right, depending on which button was clicked, then we slide the child into place. Lastly, in order to ensure that we never get a runtime error because the forward button was clicked when we were already viewing the last child, or the back button was clicked when we were already on the first child, we simply set the visible property to false for the respective button based on said conditions.

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 14th, 2008 :: Filed under Adobe AIR Tutorials, Flex Tutorials
Tags :: , , , , , , , ,

“Virtualizing” RIA Data Services

I recently learned the value of virtualizing the web server that you use for your RIA data services. Unfortunately, this was not a pleasant experience. Basically, we had outgrown the server that we were on and needed to move to something bigger, better, faster, and stronger. I was under the impression that the drives would just be moved from server A to server B. However, since they were in a SCSI RAID-5 configuration, this meant imaging was not an option. Don’t get me wrong, I know there are several ways to do this, but it wasn’t an option for the guys that were tasked with the job either because they did not know how or simply because they were lazy. Nonetheless, they only tarred up the file directories and transferred those, which meant we lost 3 years worth of custom tweaks and configurations on this server. This inevitably meant that when the new server was brought up, there was stuff broken all over the place. It has been a week now since this happened, so I decided that while the other guys are working around the clock fixing things, I would build a custom virtual machine based on our unique configuration that could be moved around, transferred between machines, duplicated onto more machines to run clusters of servers, etc, etc.  The benefits of doing this have already proven immeasurable. Once finished, I will publish the process that I used for completing this task.

The requirements are as follows:

- Must be a LAMP server (Linux/Apache/MySQL, PHP), preferably with CentOS as the Linux O/S, PHP 5, and MySQL 5.2)

- Must include some sort of webhost manager, preferably cPanel, but might end up being Plesk

- Must also include FFMPEG media encoding software for the encoding of uploaded videos through the Avijax system

- Must include ImageMagick, and a few other tools and utilities (still working on that list)

- Must include a number of tweaks to the php.ini and httpd.conf files

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 11th, 2008 :: Filed under General
Tags :: , , ,

New Technology for ActionScript Data Communications

I spent a large portion of this week learning a new technology based on a collaboration between Adobe and Zend Technologies for data communications and an unified workflow for PHP RIA developers. My assignment was to write up an article/tutorial on implementing the new technology into Flex/AIR applications. Since it is a new technology that has yet to be released to the public, the setup and configuration process was naturally a bit daunting. After I got it up and running though, I was pretty impressed with what this new technology offers. The article is set to be published initially at OnLamp.com immediately following the public announcement and release of this new technology. I will provide more details and additional information on getting up and running with this new technology here, but for now, mum’s the word.  :-)

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 10th, 2008 :: Filed under General
Tags :: , , , , ,

Using Events to Instantiate Display Objects in an Ordered Fashion

For larger applications that have an ordered process by which objects are instantiated, you are sometimes required to position your objects on the stage using only Actionscript, at a certain time. For example, let’s say your business logic needs to gather all of its data and run through a series of tasks before the user interface can be displayed. It then must dispatch a custom event to notify the display layer that it is ready. However, you do not want display objects that are defined in your mxml to be instantiated prematurely, resulting in the infamous flex 1009 error, “Cannot access a property or method of a null object reference”. In this case, our best bet is to instantiate these objects through actionscript when the “ok, im ready now!” event is dispatched from our controller class. Let’s take a look at an example:

First, we’d want to add a listener on our controller for the “I’m Ready!” event, which we will call MODEL_INITIALIZED, like so:

private var _uiCtrl:UIController;

private function init():void {
     _uiCtrl = new UIController();
     _uiCtrl.addEventListener(ControllerEvent.MODEL_INITIALIZED, createDisplayObjects);
}

Here we assume that our UIController class has an event in it of type ControllerEvent, and dispatches the ControllerEvent.MODEL_INITIALIZED when it has completed all of its background work and is ready for the user interface to be displayed.

Our createDisplayObjects handler function would then look something like the following:

private function createDisplayObjects(event:ControllerEvent):void {
     createControlBar();
     createCanvas();
     createGrid();
}

Here we are simply calling a series of methods to create our display objects. The function takes event:ControllerEvent as an argument. If this is not included, we will get a runtime error that says “Expecting 0 arguments, received 1″.

Here is an example of what our display object instantiation methods would then look like:

private function createControlBar():void {
     var bar:CustomApplicationControlBar = new CustomApplicationControlBar();
     addChild(bar);
     bar.dock = true;
     bar.uiController = this._uiCtrl;
}

private function createCanvas():void {
     var canvas:Canvas = new Canvas()
     addChild(canvas);
     canvas.percentWidth = 100;
     canvas.percentHeight = 100;
     canvas.x = 10;
     canvas.y = 10;
}

private function createGrid():void {
     var grid:CustomDataGrid = new CustomDataGrid();
     canvas.addChild(grid);
     grid.x = 0;
     grid.y = 0;
     grid.width = 500;
     grid.height = 500;
     grid.dataProvider = _uiCtrl.gridData;
}

I should first point out that the example above is meant to provide a “real-world” example of what this might look like, so allow me to explain what is going on here. In the first method, createControlBar, we are instantiating a custom component that extends the Flex ApplicationControlBar component. The ApplicationControlBar component has a property called “dock”, which docks it to the top of the stage in such a way that it is always on top, and the stage’s 0,0 point is now directly under the ApplicationControlBar so no display object will ever get covered up by the control bar. Our CustomApplicationControlBar component has a property of “uiController”, which is the current instance of the UIController class. This gives our component access to the data model within the application.

The createCanvas method is pretty straight-forward and probably requires no explanation. The createGrid method however, has a few things going on. In this example, the CustomDataGrid component extends DataGrid. We are then adding this component to the canvas that we created above it. Lastly, we set the dataProvider property to an ArrayCollection, which was part of the data model that was created when the UIController was instantiated. Since we can access our entire data model through our UIController class, we can directly bind the dataProvider of our CustomDataGrid to any of the collections within our model.

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on October 1st, 2008 :: Filed under Adobe AIR Tutorials, Flex Tutorials, Patterns & Best Practices
Tags :: , ,

Layering Code for Large-Scale Flex, Air, and Actionscript 3.0 Applications

With all of the books that I’ve read on Flex and Actionscript 3.0 development, I find it interesting that none of them go into detail about the organizational structure of an enterprise level RIA application built with Flex. Perhaps Flex is still too immature and has not really evolved enough yet to write on such topics. Nonetheless, that is exactly what we are going to discuss in this article. More specifically, we will go into detail on how one might want to structure an RIA application that he or she expects to grow very large in size. In other words, we will pay particular attention to designing an application foundation that is scalable in nature.

In order to cultivate a development environment that caters to ultimate scalability, we must start by separating our code into clearly defined layers. By layering our code, we are able to entertain a high level of abstraction in the logic. Most RIA applications are split into 3 initial layers by nature: the server side logic and database, the client side logic (and database also if we’re working with an AIR app that uses a client-side DB as well), and the medium that is used for client-server communication. Here are two examples that come straight from the two big projects I am currently part of:

Project 1
Client-side: AIR desktop app & SQLlite
Server-side: Java/Jboss with MySql Enterprise
Client-server communication: Custom Java REST service and JVM (Java Messaging Service)

Project 2
Client-side: Flex application (runs through web browser)
Server-side: PHP (custom built PHP framework) & MySql
Client-server communication: AMFPHP/Remote Object, Flash Media Server

As you can see, this kind of layering is inherent to any RIA application by nature, but our focus is splitting the client-side logic further into an additional set of layers. It is important to note that this is generally what you want to be considering before starting any development work on the project. Of course, that’s easier said than done, which is why a large number of applications in any language are overhauled once or even twice a year because there just wasn’t enough scalability built into the previous version. Nonetheless, using this article as a resource when you first begin the design of a what could become a fairly large application will definitely put you a step ahead. The same also applies to smaller applications that require a lot of custom functionality (i.e. using the built-in flex components are not really an option).

Layer 1: The Business Layer

The business layer is the core of the client side application and is completely encapsulated in such a way that nothing is ever brough up to the user interface level. In other words, it is completely hidden and works entirely behind the scenes. It’s job is to feverishly work to make sure that the user interface always has the data that it needs, when it needs it. The business layer should include: the data model, a set of value object classes, an event model, its own internal services layer for communication with the client side database (if applicable) and the server, and a primary controller class for the user interface to hook into. We make this layer its own flex library project because it has no dependency on display whatsoever.

Layer 2: Custom Component and Behavior Layer

This is the “middleman” of our user interface, and is often composed of classes built with the factory design pattern. Its job is to listen for events fired from the business layer and instantiate it’s built-in event handlers, which may be to display a popup component, change the application state, or shout out commands to particular components like “do this animation!”, or “move to here and show this data!”…you get the idea. Things you might see in the component and behavior are: custom actionscript components, use of the drawing api, programmatic animation and movement, programmatic skinning, and factory classes that ultimately control all of the behavior of the display components. We create a separate Flex library project for this layer as it is not directly part of the display. Note that we can even place some of our mxml components in this layer and still keep it as a separate library because we can just call those components from the display layer if we wanted to. Whether or not you do this however, largely depends on the size of the application. Otherwise, I suggest keeping all of the mxml in the display layer.

Layer 3: The Display Layer

This is what we can refer to as “the UI layer”, in that it defines our user interface. This is typically where you will find most, if not all of the mxml files. This is our Flex or Air application project, and it includes the business layer and component/behavior layer libraries by referencing them accordingly (see below, under “Setting it Up”). Very little actionscript should be needed in these mxml files, as they are like “dummy” files that simply define the layouts of the different states of our application. They are more like “wireframes” than anything, as our actual design should be defined either in CSS stylesheets or on layer 2 for programmatic skins. My suggestion is also to do some research on the flex component plugins for Illustrator, Flash, Photoshop, and Fireworks if you haven’t already. Using these nifty little tools that Adobe created for us, we can let the design application compile a single swf for us after you’re done creating your skin, with all of the images inside of that single swf file, then import it into Flex Builder by going to File->import->skin artwork and selecting the skins you want to import. This will save you a considerable amount of time, and allows you to take the abstraction of your application one step further by separating the design from the layout on the display layer.

Setting it Up

When you setup the layer 1 and 2 projects, when you go to File - new flex project, make sure that “flex library project” is selected in the configuration window that pops up. When you setup the Display Layer project (I would suggest choosing a different name than “Display Layer” by the way, but that’s up to you), make sure that Flex Application is selected. Then go to the project properties for the Display Layer project in flex builder, click “Flex Library Build Path”, select the Library Path tab, and click “Add Project” (as opposed to add swc) and add the layer one and two libraries that way. I suggest adding swc’s or adding a swc folder (which you then place your swc libraries into, usually called “lib”) only for components or libraries that are complete in their entirety and you will not be making changes to. The “Crypto” or “Corelib” swc libraries offered by adobe for data serialization and data encryption are examples of when you would add a swc or swc library folder (and place your swcs inside of it, which is the best way to go). That is not to say that you can’t use the swc’s for your libraries, as whenever the swc is recompiled, it will automatically be updated in the main application project, but Flex still has some bugs with regard to this functionality, so my recommendation would be to steer clear of it for now unless the library does not need to be modified.

Final Thoughts

It is worth noting that this structural pattern caters very nicely to multiple-developer environments, and each layer could even be split further into additional libraries, where each developer has their own library project, and because so little development is really happening on the display layer (it should only account for maybe 5 to 10% of the application at most), developers rarely run into each other because they are mostly working on their own library project. Each developer can additionally test their code by running the main application mxml file in the Display Layer application locally, which has all of the libraries referenced. Source control is obviously critical for this to work though.

Hopefully this article sparked some new ideas, and feel free to leave a comment describing how you might alter this structure with your own ideas and design patterns.

Happy Flexing!

Possibly Related Posts:


Share/Save/Bookmark


Posted by Dan Orlando on September 29th, 2008 :: Filed under Flex Tutorials, Patterns & Best Practices
Tags :: , , , , , , ,