Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: format

...

  1. Excluding classes that are allready loaded by a parent module
  2. Using Runntime Runtime Shared Libraries
  3. Using Signed RSLs (only applicable for the Flex framework RSLs)
  4. Using the Apparat Framework to optimize

...

You could manually exclude classes you know that are allready loaded by a parent module by hand using an "excludeClasses" section in the modules flexmojo config:

Code Block
<plugin>
				
   <groupId>org.sonatype.flexmojos</groupId>
				
   <artifactId>flexmojos-maven-plugin</artifactId>
				   <extensions>true</extensions>
				<configuration>   <configuration>
   ...

      <excludeClasses>
         <excludeClass>de.cware.cweb.module.Login</excludeClass>
            ...<excludeClass>de.cware.cweb.module.User</excludeClass>
         ...
      </excludeClasses>
      ...
    </configuration>
        <excludeClasses>
                                        <excludeClass>de.cware.cweb.module.Login</excludeClass>
                             </plugin>

But this can be a very booring and error prone task.

Here Flexmojos has an automatism that will handle this for you.

By setting the "linkReport" option to true, Flexmojos will generate a file "target/[module-name]-[module-version]-link-report.xml. This contains all information about which classes in which libraries are required by the current module.

In a Module that will load other modules:

Code Block
<plugin>
    <groupId>org.sonatype.flexmojos</groupId>
    <artifactId>flexmojos-maven-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
          <excludeClass>de.cware.cweb.module.User</excludeClass>
                  <linkReport>true</linkReport>
                      ...
    </configuration>
                                </excludeClasses></plugin>

You can now reference a link report of a modules parent module and Flexmojos makes sure these classes are not added to the current module, as it can assume these have allready been loaded.

In a Module that is loaded by another module:

Code Block
<plugin>
   <groupId>org.sonatype.flexmojos</groupId>
   <artifactId>flexmojos-maven-plugin</artifactId>
   <extensions>true</extensions>
   <configuration>
    ...
      <loadExterns>
         <loadExtern>
            <groupId>[parent-module-groupId]</groupId>
       ...      				</configuration> 			</plugin>

But this can be a very booring and error prone task.

Here Flexmojos has an automatism that will handle this for you.

By setting the "linkReport" option to true, Flexmojos will generate a file "target/[module-name]-[module-version]-link-report.xml. This contains all information about which classes in which libraries are required by the current module.

In a Module that will load other modules:

Code Block
<plugin>
				<groupId>org.sonatype.flexmojos</groupId>
				<artifactId>flexmojos-maven-plugin</artifactId>
				<extensions>true</extensions>
				<configuration> <artifactId>[parent-module-artifactId]</artifactId>
               <version>[parent-module-version</version>
         </loadExtern>
      </loadExterns>
        ...
                                     <linkReport>true</linkReport>

                                    ...

				</configuration>
			</plugin>

You can now reference a link report of a modules parent module and Flexmojos makes sure these classes are not added to the current module, as it can assume these have allready been loaded.

In a Module that is loaded by another module:

Code Block
<plugin>
				<groupId>org.sonatype.flexmojos</groupId>
				<artifactId>flexmojos-maven-plugin</artifactId>
				<extensions>true</extensions>
				<configuration>

                                    ...

                                    <loadExterns>
                                        <loadExtern>
                                            <groupId>[parent-module-groupId]</groupId>
                                  </configuration>
</plugin>

This will use the linkage-report of the parent module and omit all classes that are referenced there from the current module.

In my Case I usually have one really dumb main Application that loads several other modules in parallel. This means that the main loader doesn't contain too much of the classes that a lot of the child modules share. So in this case the benefit of this approach is minimal.

(warning)  Using this option will result in problems if you are using the Maven Release Plugin, as this doesn't update the versions in the loadExtern references. So if you are using the Maven Release plugin you allways have to manually update your poms. In my case this fact resulted in major problems.

Using Runntime Shared Libraries

Runntime Shared Libraries (RSLs) can be thought of as a Flex equivalent of DLLs or Jar-Files in Java. They are a SWC that is not statically linked into the binary but will be loaded at runntime by the Flash Player.

As mentioned in the last Chapter, a lot of my applications consist of a very simple and dumb application core, that loads the actual logic in multiple modules that exist parallel to each other. Therefore reusing the parents classes will not be very usefull and a lot of classes would still be loaded multiple times.

Using RSLs is a major improvement in this case, as the first module requiring a library will cause the Flash player to load that library and the loaded classes are then used by multiple modules.

Using RSLs is realy easy with Flexmojos, as all you have to do, is to specify a scope of "rsl" to dependencies that should be loaded from an RSL and tell the compiler the URL pattern from where it can actually load the rsls from:

Code Block
<plugin>
   <groupId>org.sonatype.flexmojos</groupId>
   <artifactId>flexmojos-maven-plugin</artifactId>
   <version>${flexmojos.version}</version>
   <configuration>
      ...
      <rslUrls>
         <artifactId>[parent-module-artifactId]</artifactId><url>rsl/{artifactId}-{version}.{extension}</url>
      </rslUrls>
       ...
   </configuration>
      ...
</plugin>
...
<dependencies>
   ...
   <dependency>
       <version><groupId>[parentrsl-module-version<groupId]</version>groupId>
          <artifactId>[rsl-module-artifactId]</artifactId>
      <version>[rsl-module-version]</version>
      <type>swc</type>
        <scope>rsl</scope>
      </loadExtern>dependency>
                                    </loadExterns>
                                    ...

				</configuration>
			</plugin>

This will use the linkage-report of the parent module and omit all classes that are referenced there from the current module.

In my Case I usually have one really dumb main Application that loads several other modules in parallel. This means that the main loader doesn't contain too much of the classes that a lot of the child modules share. So in this case the benefit of this approach is minimal.

(warning)  Using this option will result in problems if you are using the Maven Release Plugin, as this doesn't update the versions in the loadExtern references. So if you are using the Maven Release plugin you allways have to manually update your poms. In my case this fact resulted in major problems.

Using Runntime Shared Libraries

Runntime Shared Libraries (RSLs) can be thought of as a Flex equivalent of DLLs or Jar-Files in Java. They are a SWC that is not statically linked into the binary but will be loaded at runntime by the Flash Player.

As mentioned in the last Chapter, a lot of my applications consist of a very simple and dumb application core, that loads the actual logic in multiple modules that exist parallel to each other. Therefore reusing the parents classes will not be very usefull and a lot of classes would still be loaded multiple times.

Using RSLs is a major improvement in this case, as the first module requiring a library will cause the Flash player to load that library and the loaded classes are then used by multiple modules.

Using RSLs is realy easy with Flexmojos, as all you have to do, is to specify a scope of "rsl" to dependencies that should be loaded from an RSL and tell the compiler the URL pattern from where it can actually load the rsls from:

Code Block
<plugin>
                    <groupId>org.sonatype.flexmojos</groupId>
                    <artifactId>flexmojos-maven-plugin</artifactId>
                    <version>${flexmojos.version}</version>
                    <configuration>

                        ...

                        <rslUrls>
                            <url>rsl/{artifactId}-{version}.{extension}</url>
                        </rslUrls>

                        ...

                    </configuration>

                    ...

                </plugin>
    ...

    <dependencies>

        ...

        <dependency>
            <groupId>[rsl-module-groupId]</groupId>
            <artifactId>[rsl-module-artifactId]</artifactId>
            <version>[rsl-module-version]</version>
            <type>swc</type>
            <scope>rsl</scope>
        </dependency>

        ...

    </dependencies>

This will make the linker link the classes of that library as RSL loaded class.

The Flexmojos "copy-flex-resources" goal in the "war" module will now create a directory called "rsl" in the resulting war, that will contain the RSL binaries referenced in the probject.

In one of my projects without any optimization of this kind, all generated SWFs had a size of 25MB and by simply loading the Flex Framework as RSLs reduced the size to 6,5MB ... I would call this a significant optimization.

(warning)  I Strongly recommend to set the rslUrl to that value, as Flexmojos uses a slightly different one per default. The FM default is "/{contextRoot}/rsl/{artifactId}-{version}.{extension}". Usually I don't have "contextRoot" set and this results in invalid urls for rsl loading. By changing the url to the above value you also have a lot less problems if you use the standallone player/debugger to run your application as with this setting it will look relative to the path the swf was loaded from and this works when using http in a browser AND using file in the standallone player/debugger.

Using Signed RSLs

Now when using RSLs there will be some RSLs that will propably be loaded most: The Flex Framework RSLs. With introduction of the caching capabilities of the Flash-Player Adobe allowed to download officially signed Framework RSLs from Adobe and to install them on a client machine. This way the Framework RSLs are only loaded once and are reused the next time they are needed (Even if they were initially loaded from a different application/website). The cool thing is that the signed RSLs are first loaded from an Adobe Server in the web. Only if this fails, the local Webserver is queried. There are several things I find specially interestig in this approach:

  1. It dramatially reduces the size of an application
  2. It dramatically reduces the traffic on your applications webserver as the traffic for loading the Flex Framework is handled by Adobes Servers.

In general the only difference to the RSL approach is that you have to name the scope "caching" instead of "rsl" and that the resulting files in your wars "rsl" directory have a different file-ending.

As I mentioned above the caching mechanism only applies to libraries officially distributed by Adobe so when using custom libraries you will have to stick to the normal RSL approach.

Unfortunately you can't use the relatively easy way to reference all Flex Framework libraries by referencing the "framework" pom-dependency. This would include all Framework libs the default way. The solution I chose for now was to explicitly reference the framework libraries BEFORE the framework-pom.

Code Block
<dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>framework</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
        </dependency>

Was then replaced by (for a Flex 4.5 SDK >= Build 18261)

Code Block
<dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>textLayout</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>framework</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>spark</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>sparkskins</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>mx</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>rpc</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>charts</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>advancedgrids</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>flex-framework</artifactId>
            <version>${flex.version}</version>
            <type>pom</type>
        </dependency>

Or for an older SDK ("datavisualization" was split up into "charts" and "advancedgrids" in 18261)

Code Block
<dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>textLayout</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>framework</artifactId>
            <version>${flex.version}</version>
            <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
        ...
</dependencies>

This will make the linker link the classes of that library as RSL loaded class.

The Flexmojos "copy-flex-resources" goal in the "war" module will now create a directory called "rsl" in the resulting war, that will contain the RSL binaries referenced in the probject.

In one of my projects without any optimization of this kind, all generated SWFs had a size of 25MB and by simply loading the Flex Framework as RSLs reduced the size to 6,5MB ... I would call this a significant optimization.

(warning)  I Strongly recommend to set the rslUrl to that value, as Flexmojos uses a slightly different one per default. The FM default is "/{contextRoot}/rsl/{artifactId}-{version}.{extension}". Usually I don't have "contextRoot" set and this results in invalid urls for rsl loading. By changing the url to the above value you also have a lot less problems if you use the standallone player/debugger to run your application as with this setting it will look relative to the path the swf was loaded from and this works when using http in a browser AND using file in the standallone player/debugger.

Using Signed RSLs

Now when using RSLs there will be some RSLs that will propably be loaded most: The Flex Framework RSLs. With introduction of the caching capabilities of the Flash-Player Adobe allowed to download officially signed Framework RSLs from Adobe and to install them on a client machine. This way the Framework RSLs are only loaded once and are reused the next time they are needed (Even if they were initially loaded from a different application/website). The cool thing is that the signed RSLs are first loaded from an Adobe Server in the web. Only if this fails, the local Webserver is queried. There are several things I find specially interestig in this approach:

  1. It dramatially reduces the size of an application
  2. It dramatically reduces the traffic on your applications webserver as the traffic for loading the Flex Framework is handled by Adobes Servers.

In general the only difference to the RSL approach is that you have to name the scope "caching" instead of "rsl" and that the resulting files in your wars "rsl" directory have a different file-ending.

As I mentioned above the caching mechanism only applies to libraries officially distributed by Adobe so when using custom libraries you will have to stick to the normal RSL approach.

Unfortunately you can't use the relatively easy way to reference all Flex Framework libraries by referencing the "framework" pom-dependency. This would include all Framework libs the default way. The solution I chose for now was to explicitly reference the framework libraries BEFORE the framework-pom.

Code Block
<dependency>
   <groupId>com.adobe.flex.framework</groupId>
            <artifactId>spark</artifactId>
        <artifactId>framework</artifactId>
   <version>${flex.version}</version>
   <type>swc</type>
</dependency>

Was then replaced by (for a Flex 4.5 SDK >= Build 18261)

Code Block
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
   <type>swc<<artifactId>textLayout</type>artifactId>
     <version>${flex.version}</version>
   <type>swc</type>
  <scope>caching</scope>
     
  </dependency>
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
  <artifactId>framework</artifactId>
 <dependency>
 <version>${flex.version}</version>
  <type>swc</type>
  <scope>caching</scope>
</dependency>
<dependency>
   <groupId>com.adobe.flex.framework</groupId>
  <artifactId>spark</artifactId>
  <version>${flex.version}</version>
  <type>swc</type>
  <scope>caching</scope>
<artifactId>sparkskins<</artifactId>dependency>
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
     <artifactId>sparkskins</artifactId>
  <version>${flex.version}</version>
  <type>swc</type>
  <scope>caching</scope>
</dependency>
<dependency>
    <type>swc</type><groupId>com.adobe.flex.framework</groupId>
  <artifactId>mx</artifactId>
  <version>${flex.version}</version>
  <type>swc</type>
   <scope>caching</scope>
      
 </dependency>
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
  <artifactId>rpc</artifactId>
 <dependency>
 <version>${flex.version}</version>
   <type>swc</type>
  <scope>caching</scope>
</dependency>
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
  <artifactId>charts</artifactId>
  <version>${flex.version}</version>
  <type>swc</type>
  <scope>caching</scope>
<artifactId>mx<</artifactId>dependency>
<dependency>
  <groupId>com.adobe.flex.framework</groupId>
     <artifactId>advancedgrids</artifactId>
  <version>${flex.version}</version>
         
  <type>swc</type>
  <scope>caching</scope>
</dependency>
<dependency>
       <scope>caching</scope>
 <groupId>com.adobe.flex.framework</groupId>
  <artifactId>flex-framework</artifactId>
   <version>${flex.version}</dependency>version>
  <type>pom</type>
</dependency>

Or for an older SDK ("datavisualization" was split up into "charts" and "advancedgrids" in 18261)

Code Block
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <dependency><artifactId>textLayout</artifactId>
    <version>${flex.version}</version>
      <type>swc</type>
    <scope>caching</scope>
</dependency>
<dependency>
     <groupId>com.adobe.flex.framework</groupId>
            <artifactId>rpc<    <artifactId>framework</artifactId>
               <version>${flex.version}</version>
    <type>swc</type>
    <scope>caching</scope>
</dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
       <type>swc</type>
            <scope>caching</scope>
        </dependency>
        <dependency>
            <artifactId>spark</artifactId>
    <version>${flex.version}</version>
    <type>swc</type>
    <scope>caching</scope>
</dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>sparkskins</artifactId>
    <version>${flex.version}</version>
    <type>swc</type>
         <artifactId>datavisualization</artifactId>
           <scope>caching</scope>
</dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>mx</artifactId>
    <version>${flex.version}</version>
                <type>swc</type>
                <scope>caching</scope>
 
      </dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>rpc</artifactId>
    <version>${flex.version}</version>
 <dependency>
               <type>swc</type>
 <scope>caching</scope>
</dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>datavisualization</artifactId>
    <version>${flex.version}</version>
    <type>swc</type>
    <scope>caching</scope>
</dependency>
<dependency>
    <groupId>com.adobe.flex.framework</groupId>
    <artifactId>flex-framework</artifactId>
                <version>${flex.version}</version>
                <type>pom</type>
        </dependency>

(warning)  If you are getting "Error: #2032" messages, you probably setup your rslUrls wrong. Initially I let the urls start with "/" but this caused #2032 Errors in a different project when loading classes-swz. Investigating the error made me find out that the flashplayer allready installed the other swzs from loading another application and therefore I only got errors with charts (which I didn't use in the other application). In my case removing the leading "/" resolved the issue. So if you are encountering #2032 Errors check if the urls to your RSLs are correct and dont let yourself get confused that other libs seem to load correctly.

...