Creating RSLs from your 3rd party libs

RSLs can really come in handy. Unfortunatley not all libraries are available as rsls. So is there a way to make rsls out of our swcs? 

The answer is "Yes we can" (Wonder where I heard that before) ;-)

Here come the steps needed to do so:

  1. Unpack the swc
  2. Optimize the swf that the swc contained
  3. Update the digests
  4. Manually deploy the swf
  5. Update the dependencies in your poms

For sake of simplicity I am assuming the swc is contained in a directory called "myroot"

Initial Directory Structure
/myroot/mylib.swc

Unpack the swc

SWC files are nothing else than zip files containig a swf file and a lot of metadata. For the RSL it seems that only the SWF itself is of interest, so we have to extract this from the SWC. 

On Windows I tend to simply rename the mylib.swc to mylib.zip and then to use any zip tool to extract the data. (Let's call the directory containing the content of the swc "lib-dir" from now on)

the name of the swf inside lib-dir is allways "library.swf" no matter what the name of the original swc file was. 

After this we will have something similar to this:

/myroot/mylib.swc
/myroot/mylib/library.swf
/myroot/mylib/catalog.xml

Some swcs might contain additional resourced in the /myroot/mylib directory. (spark or mx directory, css files, ...) but these are not of interest at the moment.

Optimize the swc

Ok ... here comes the fun part. In order to do this next step you will need an installed Flex SDK somewhere, because this contains all the tools needed to continue. Assuming you have the Adobe Creative Suite or the FlashBuilder installed, you would probably have a SDK in (in my case) "C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.5\sdks\4.5.1". I'll call this FLEX_HOME from now on. I tend to add the bin directory of the newest SDK I have installed to the systems path so I can call the commandline tools directly anywhere.

By executing the following command you optimize the library.swf and make an rsl from it:

{FLEX_HOME}/bin/optimizer -keep-as3-metadata="Bindable,Managed,ChangeEvent,NonCommittingChangeEvent,Transient" -input /myroot/mylib/library.swf -output /myroot/mylib.swf

This takes the original library.swf and creates an optimized rsl called optimized.swf (RSLs have the file ending "swf")

Problems with 64BIT JDKs

If you are getting strange errors "Error loading: C:\Program Files\Java\jre6\bin\server\jvm.dll" (or similar) you probably have configured your JAVA_HOME to point to a 64Bit JDK/JRE and the Flex SDK is allways a 32Bit version (Never seen a 64Bit version). In order to execute the command you need JAVA_HOME to point to a 32Bit Java Runtime. So by simply setting JAVA_HOME to a 32Bit version should do the trick.

Update the digests

If you use the current version of the rsl your application will probably build fine with it. Unfortunately the Flash player will deny their usage, because the digest information is not valid. In order to fix this, you have to use a second tool in the Flex SDK "digest".

With this the digest information in the original swc /myroot/mylib.swc will be updated with the correct information from the optimized /myroot/mylib.swf. This way the digest information of the loaded rsl will match the ones the compiler saved when linking the application.

Using the following command the digests of the previously created rsl are updated:

{FLEX_HOME}/bin/digest -digest.rsl-file /myroot/mylib.swf -digest.swc-path /myroot/mylib.swc

One thing I missed now was that this command didn't update the digest information in the swf to match the swc, but it actually updated the information in the swc. This means that the mylib.swc file is not the same we initially used. In order to correctly use the library as rsl both the mylib.swc and mylib.swf have to be deployed and the application has to be recompiled with them.

Manually deploy the swf and swc

Now comes something that I found relatively strange. Deploying the freshly created rsl.

Flexmojos seems to ignore the packaging of a pom and seems to be interested only in the file-ending. So if you have no scope or scope "compile" then it looks for a "swc"-File, if you have scope "rsl" then it looks for an "swf" and if you have "caching" a "swz"-File is fetched. 

In order to deploy an RSL I did the following on a Nexus:

  1. Maually upload a new artifact. 
    1. Set Group-Id, Artifact-Id, version and packaging of the swc
    2. Upload the updated swc as type swc
    3. Upload the converted rsl as type swf 

Update the dependencies in your poms

The last step needed, is to switch your build to actually use the new rsl version of your library. This is done by simply appending a "scope=rsl" to that dependency.

Simply change:

<dependency>
    <groupId>de.cware.libs</groupId>
    <artifactId>coollib</artifactId>
    <version>1.2.3</version>
    <type>swc</type>
</dependency>

To this:

<dependency>
    <groupId>de.cware.libs</groupId>
    <artifactId>coollib</artifactId>
    <version>1.2.3</version>
    <type>swc</type>
    <scope>rsl</scope>
</dependency>

Ok ... I know this seems to be confusing, that by defining a swc-dependency with scope rsl results in flexmojos fetching a swf-dependency from maven, but that's the way it goes.

Happy RSLing (smile)

Problems with rsls and classifiers

I had some strange errors when trying to rslify the flexlib-2.5 library. Usually you reference that library as like this:

<dependency>
    <groupId>com.google.code.flexlib</groupId>
    <artifactId>flexlib</artifactId>
    <version>2.5</version>
    <classifier>flex4</classifier>
    <type>swc</type>
</dependency>

So I deployed the corresponding rsl artifact as:

<dependency>
    <groupId>com.google.code.flexlib</groupId>
    <artifactId>flexlib</artifactId>
    <version>2.5</version>
    <classifier>flex4</classifier>
    <type>swc</type>
</dependency>

Unfortunately Flexmojos will return errors, because it seems that the classifier is ignored when copying the resources of rsls. So I had to omit the classifier and deploy the artifact as follows:

<dependency>
    <groupId>com.google.code.flexlib</groupId>
    <artifactId>flexlib</artifactId>
    <version>2.5</version>
    <type>swc</type>
</dependency>

Problems with dependencies of rsls

I just resolved some problems I was having with an swc that I converted to an rsl. To name it I was rslifying the Flexicious Ultimate Datagrid. Whenever I started my application I got the following error:

„VerifyError: Error #1014: Klasse mx.controls.advancedDataGridClasses::AdvancedDataGridColumn wurde nicht gefunden.“

Strangely the advancedgrids library was included in my distribution. 

Searching the web for a solution of this problem showed me that if an rsl library depends on another one, that the other one has to be listed before the one that depends on this. In my case I had Flexmojos include the Framework classes using a self-activating profile in my master pom. Unfortunately Flexmojos generated the compiler config to output those dependencies after the ones of the current lib. In order to resolve this error I had to additionally add a reference to advancedgrids before my ultimategrid dependency. After this the error I mentioned was no more.