June 14, 2007
How I Debug with Flex Modules
When you create modular application in Flex 2.0.1, you lose the ability to debug within the loaded modules. This can be overcome by using a simple technique that a friend encouraged me to post after I shared it with him.
Essentially, modules are loaded into an application via the ModuleLoader class. A typical example looks like this:
<mx:ModuleLoader id="moduleLoader" url="myModule.swf" />
The problem with this approach is that the URL is hard-coded to always load the non-debug version of the module .swf file. Whenever you create an application/module in FlexBuilder, two .swf files are generated: the release version which just ends in ".swf", and the debug version which ends in "-debug.swf"). When you launch a debug session, the debug .html file launches which instructs Flash Player to load the debug .swf file. The debug .swf contains additional information to help the debugger along so you can examine the running application in detail.
In the case of debugging with modules, when you debug the debug version of the main application is loaded and the debugger launches, but the release version of the modules are loaded because of the hard-coded reference to the module's URL. This means that you can't get debugging information from your modules because the release .swf which loads does not contain the debugging information.
The fix is pretty straightforward. When you need to debug the application you have to load the "-debug.swf" module, and when you want to create a release version you have to load the normal .swf file. Rather than constantly changing the URL on each ModuleLoader instance, I've been using a static getter "constant" that makes the process transparent:
public final class Constants { /** The path to the swf file for my module. */ public static function get MY_MODULE_SWF():String { // Check to see if the application is the debug version, and if // so then use the debug module... if ( Application( Application.application ).url.indexOf( "debug" ) >= 0 ) { return "MyModule-debug.swf"; } // ...otherwise use the release module return "MyModule.swf"; } }
The ModuleLoader then needs to have the url property set via ActionScript. If you try to use binding in the MXML tag itself, you'll get a warning about not being able to detect changes in the { } binding syntax, and trying to make the getter [Bindable] will complain that you can't create bindable static functions. It's a minor annoyance, but I hardly notice it since I control module loading via ActionScript anyway:
moduleLoader.url = Constants.MY_MODULE_SWF; // Load the module var module:IModuleInfo = ModuleManager.getModule( Constants.MY_MODULE_SWF ); module.load();
A nice side effect of using this simple technique is being able to use a "constant" to reference the module from anywhere via the ModuleManager.getModule method.
Now, no matter if you run or debug, the correct version of the module gets loaded and the fact that you're using modules becomes transparent. I believe this is an area that Adobe is hoping to improve upon in Flex 3 (Moxie) and in the future as well, but the above is a good workaround in the near term.
I've been using modules quite a bit for the past few months on my current project. Hopefully I'll have some time in the future to share a few more tips and tricks like this for creating modular architectures in Flex RIAs.
Tags: Flex 2, Modules
Comments