Flex Pasta » Modules
I’m kind of into automation. If I have to do something more than a few times a day, it needs to be automated to work for me. I originally wanted to write a flexpasta.bat file that would just write this post and code it for me, but that seemed a bit overboard.
One thing most web developers encounter in a day is testing their code. This usually involves reloading the page each time a code change in made and published. With Flex, we are having to reload the whole app, then probably make a bunch of clicks to get to the part of the application we are testing. This has become a pain, especially when making nit picky UI changes. Which brings me to the automation part. What if, when we make changes to code, it automatically reloads the flex module I am working on so that I can see the changes right away with no reload/type/click action? Making UI changes would be so much nicer.
To do this I have created DynamicModuleLoader.as. Basically, it extends ModuleLoader. Every 5 seconds it will ping the server to find out if the module has changed. If it has changed, it dumps the old module and loads the new one. Works best with two monitors. Just stating the obvious, but this is not for a production environment! Just helps for development.
package com.flexpasta.modules
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.utils.Timer;
import mx.modules.Module;
import mx.modules.ModuleLoader;
public class DynamicModuleLoader extends ModuleLoader
{
public function DynamicModuleLoader()
{
super();
}
private var timer:Timer = new Timer(5000,50000);
override public function addChild(child:DisplayObject):DisplayObject
{
var disp:DisplayObject = super.addChild(child);
if(child is Module && !timer.running)
{
timer.addEventListener(TimerEvent.TIMER, checkForNewModule);
timer.start();
}
return disp;
}
private function checkForNewModule(event:TimerEvent):void
{
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, httpResult);
var urlReq:URLRequest = new URLRequest(url);
urlLoader.load(urlReq);
}
private var byteAmount:Number
private function httpResult(event:Event):void
{
if(isNaN(byteAmount))
{
byteAmount = event.currentTarget.bytesTotal;
}
else if(byteAmount!=event.currentTarget.bytesTotal)
{
byteAmount = event.currentTarget.bytesTotal;
unloadModule();
loadModule(url);
}
}
}
}
Have you used modules for your Flex applications? If you haven’t, modules are simply a way to split your application into pieces. Rather than having one giant SWF file based on an mx:Application tag, you have multiple “module” SWF files which are loaded at runtime by the main SWF application. The modules know at compile time which classes the master application SWF file will have, thus reducing the amount of compiling needed on the child module SWF files. This makes Flex with modules a great way to reduce compile times. I would like to see improvements in Flex Builder and the Flex SDK to support easier modularized Flex development. Modules are a critical piece to the enterprise Flex landscape. Anyone creating a large application with Flex has probably seen lengthy compile times when using a single mx:Application tag(so modules are important!!!). Here are my top 5 improvements for Flex 4 and modules.
5. Create a new Flex Modules “View” window in Flex Builder
It would be great to have a tree view window showing the modules being built in a project. Let’s have a window that shows the modules name, time last built, module size, compile time length, and a tree view of all the classes included in the module. If a developer makes a coding mistake, or even leaves an unused import in the wrong module, it can result in a module with a bloated number of classes that it doesn’t need. It is very hard to track down this problem once it has happened, and it is too time consuming to keep up with. The whole point of modules is to reduce compile and run times. Developers need the tools to support modules.
4. Better documentation and example applications with modules
Modules are a complicated topic, especially when you throw in things like Cairngorm, Penne, Mate, or whatever other framework you might be using. Therefore, it would be nice to see some examples of real applications using modules sucessfully.
3. When Flex Builder does a compile, show the output of the compiler arguments for ant and maven.
When Flex Builder makes a call to mxmlc, there are certainly arguments passed in just like when running a command line build with mxmlc. When doing a deployment, either through ant or maven, figuring out the command line arguments for the build can be quite tricky. And that is just when building one Flex application. When doing an ant or maven compile with modules, the problems are compounded. To do a command line compile with modules, first you must build the main application file, outputting a link report xml file. The linking file then must be a parameter for the build of each module, letting the compiler know that the main application file already has some of the classes it needs. Coming up with the syntax for all of this takes at bit of googling to say the least. I think it would be fairly simple feature request for Flex Builder to dump the compiler arguments to the console.
2. Make Flex and modules work like Java class files
If I have 50 Java class files and I modify one, only the .class file for that Java class is recompiled and deployed to my local server. It makes it quick to test and keep right on developing. I would like to see a feature that has the Flex compiler compile each as/mxml file individually and then deploy it to a local server. The SWF file would load each as/mxml file on an as need basis. By compiling on a file by file basis, it would all but eliminate compile times. I realize that this feature might be difficult to add. It may even be impossible since the SWF file could potentially be loading hundreds of classes at a time. I’m not advocating deploying an application like this to a user base, you would use an RSL for this. What I am suggesting is for development purposes. To reduce compile times and make developers lives easier.
1. Fix all the compiler/Flex Builder bugs related to modules
Certainly the Flex team has put in a lot of time and effort into modules, and they have done a good job with the Flex modules platform. But please don’t stop investing in the development of module support. There are a good number of bugs with modules. You will see morbid errors at runtime that even a clean doesn’t fix. For example:
VerifyError: Error #1014: Class mx.containers::HDividedBox could not be found.
at flash.display::MovieClip/nextFrame()
at mx.core::FlexModuleFactory/deferredNextFrame()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:467]
at mx.core::FlexModuleFactory/update()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:295]
at mx.core::FlexModuleFactory/moduleCompleteHandler()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:542]
at flash.display::MovieClip/nextFrame()
at mx.core::FlexModuleFactory/deferredNextFrame()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:467]
at mx.core::FlexModuleFactory/update()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:295]
at mx.core::FlexModuleFactory/moduleCompleteHandler()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:542]
at flash.display::MovieClip/nextFrame()
at mx.core::FlexModuleFactory/deferredNextFrame()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:467]
at mx.core::FlexModuleFactory/update()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:295]
at mx.core::FlexModuleFactory/moduleCompleteHandler()[C:\Adobe\source\sdk\branches\3.x\frameworks\projects\framework\src\mx\core\FlexModuleFactory.as:542]
There are compile errors that don’t show up in the Flex problems window. Charts can randomly turn black in a module. Embedded fonts are nearly imposible to use. And if you would like to really bang your head against a wall, try refactoring code used across multiple modules(try it out if you don’t believe me). Please help Flex developers out by knocking out some of these bugs.
I was using an embedded font today with modules and charts. My embedded font is declared in the css file and is only referenced in the main application page and not in each module. When embedding the font in the main application, I would expect the font to be carried over into each module, the same way all the other styles work with modules. For some reason though, the labels on the axes of the column chart don’t appear when the chart is in a module using an embedded font. I have opened a bug with Adobe regarding this issue. I’m not sure if it’s the chart doing something weird or the Flex compiler(or maybe me!). In any case, I don’t think the labels should disappear.
Run the example and see for yourself the behavior: Charting.swf
Panel 1 is a column chart declared in the main application and Panel 2 is the exact same column chart in a module. There is an embedded font ‘Verdana’ in the main application.
Charting.mxml
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”horizontal” xmlns:local=”*”>
<mx:Style>
Application
{
font-family: Verdana;
}
@font-face {
src:url(”font/verdana.ttf”);
fontFamily: Verdana;
advancedAntiAliasing: true;
}
@font-face {
src:url(”font/verdanab.ttf”);
fontFamily: Verdana;
fontWeight: bold;
advancedAntiAliasing: true;
}
@font-face {
src:url(”font/verdanai.ttf”);
fontFamily: Verdana;
font-style: italic;
advancedAntiAliasing: true;
}
</mx:Style>
<local:ColumnChart width=”50%” height=”100%” title=”Chart 1″/>
<mx:ModuleLoader url=”ChartModule.swf” width=”50%” height=”100%”/>
</mx:Application>