Adobe Flex 3 Help

Modular applications overview

About modules

Modules are SWF files that can be loaded and unloaded by an application. They cannot be run independently of an application, but any number of applications can share the modules.

Modules let you split your application into several pieces, or modules. The main application, or shell, can dynamically load other modules that it requires, when it needs them. It does not have to load all modules when it starts, nor does it have to load any modules if the user does not interact with them. When the application no longer needs a module, it can unload the module to free up memory and resources.

Modular applications have the following benefits:

  • Smaller initial download size of the SWF file.
  • Shorter load time due to smaller SWF file size.
  • Better encapsulation of related aspects of an application. For example, a "reporting" feature can be separated into a module that you can then work on independently.

Benefits of modules

A module is a special type of dynamically loadable SWF that contains an IFlexModuleFactory class factory. This allows an application to load code at run time and create class instances without requiring that the class implementations be linked into the main application.

Modules are similar to Runtime Shared Libraries (RSLs) in that they separate code from an application into separately loaded SWF files. Modules are much more flexible than RSLs because modules can be loaded and unloaded at run time and compiled without the application.

Two common scenarios in which using modules is beneficial are a large application with different user paths and a portal application.

An example of the first common scenario is an enormous insurance application that includes thousands of screens, for life insurance, car insurance, health insurance, dental insurance, travel insurance, and veterinary pet insurance.

By using a traditional approach to rich Internet application (RIA) design, you might build a monolithic application with a hierarchical tree of MXML classes. Memory use and start-up time for the application would be significant, and the SWF file size would grow with each new set of functionality.

When using this application, however, any user accesses only a subset of the screens. By refactoring the screens into small groups of modules that are loaded on demand, you can improve the perceived performance of the main application and reduce the memory use. Also, when the application is separated into modules, developers' productivity may increase due to better encapsulation of design. When rebuilding the application, the developers also have to recompile only the single module instead of the entire application.

An example of the second common scenario is a system with a main portal application, written in ActionScript 3.0, that provides services for numerous portlets. Portlets are configured based on data that is downloaded on a per-user basis. By using the traditional approach, you might build an application that compiles in all known portlets. This is inefficient, both for deployment and development.

By using modules, you can establish an interface that contains portal services, and a generic portlet interface. You can use XML data to determine which modules to load for a given session. When the module is loaded, you obtain a handle to a class factory inside the module, and from that you create an instance of a class that implements the portlet interface. In this scenario, full recompilation is necessary only if the interfaces change.

Module API details

Modules implement a class factory with a standard interface. The product of that class factory implements an interface known to the shell, or the shell implements an interface known to the modules.

By using shared interface definitions, these shared interfaces reduce hard dependencies between the shell and the module. This provides type-safe communication and enforces an abstraction layer without adding significantly to the SWF file size.

The following image shows the relationship between the shell and the module's interfaces:

The relationship between the shell and the module's interface.

The ModuleManager manages the set of loaded modules, which are treated as a map of Singletons that are indexed by the module URL. Loading a module triggers a series of events that let clients monitor the status of the module. Modules are only ever loaded once, but subsequent reloads also dispatch events so that client code can be simplified and rely on using the READY event to know that the module's class factory is available for use.

The ModuleLoader class is a thin layer on top of the ModuleManager API that is intended to act similarly to the mx.controls.SWFLoader class for modules that only define a single visual UIComponent. The ModuleLoader class is the easiest class to use when implementing a module-based architecture, but the ModuleManager provides greater control over the modules.

Module domains

By default, a module is loaded into a child domain of the current application domain. You can specify a different application domain by using the applicationDomain property of the ModuleLoader class.

Because a module is loaded into a child domain, it owns class definitions that are not in the main application's domain. For example, the first module to load the PopUpManager class becomes the owner of the PopUpManager class for the entire application because it registers the manager with the SingletonManager. If another module later tries to use the PopUpManager, Adobe ® Flash® Player throws an exception.

The solution is to ensure that managers such as PopUpManager and DragManager and any other shared services are defined by the main application (or loaded late into the shell's application domain). When you promote one of those classes to the shell, the class can then be used by all modules. Typically, this is done by adding the following to a script block:

import mx.managers.PopUpManager;
import mx.managers.DragManager;
private var popUpManager:PopUpManager;
private var dragManager:DragManager;

This technique also applies to components. The module that first uses the component owns that component's class definition in its domain. As a result, if another module tries to use a component that has already been used by another module, its definition will not match the existing definition. To avoid a mismatch of component definitions, create an instance of the component in the main application. The result is that the definition of the component is owned by the main application and can be used by modules in any child domain.

Because a Flex module must be in the same security domain as the application (SWF) that loads it, when you're using modules in an AIR application any module SWF must be located in the same directory as the main application SWF or one of its subdirectories, which ensures that like the main application SWF, the module SWF is in the AIR application security sandbox. One way to verify this is to ensure that a relative URL for the module's location doesn't require "../" ("up one level") notation to navigate outside the application directory or one of its subdirectories.

For more information about application domains, see Using the ApplicationDomain class.

Module applications

To create a modular application, you create separate classes for each module, and an application that loads the modules. Adobe® Flex® Builder™ provides some mechanisms for making module use easier.

Create a modular application

  1. Create any number of modules. An MXML-based module file's root tag is <mx:Module>. ActionScript-based modules extend either the Module or ModuleBase class.
  2. Compile each module as if it were an application. You can do this by using the mxmlc command-line compiler or the compiler built into Adobe Flex Builder.
  3. Create an Application class. This is typically an MXML file whose root tag is <mx:Application>, but it can also be an ActionScript-only application.
  4. In the Application file, use an <mx:ModuleLoader> tag to load each of the modules. You can also load modules by using methods of the mx.modules.ModuleLoader and mx.modules.ModuleManager classes.