Flex Hero RSL Enhancements and Monkey Patching

Posted on August 30, 2010 | 5 comments

In my last post “Using Flex Hero RSL Enhancements” I discussed some of the new Flex Hero features around RSL Enhancements. I wanted to finish off the discussion with some information about the new “include-inheritance-dependencies-only” addition to compc, which added to make monkey patching with RSL’s easier. Lets just say it made one manual step easier, the whole process is still a bit complex.

The main goal of Runtime Shared Libraries (RSL) and monkey patching is to be able to leverage the Adobe official RSL’s with custom RSL’s that only include the few classes that you are changing. This means you need to understand what classes are in what official libraries.

There is a bunch of information on RSL’s and monkey patching explaining the more manual way of figuring out the exact classes you wanted in your monkey patched RSL. It involves a bunch of getting what classes to include and exclude from different compiles of mxmlc and compc. Here is a good resource on the subject over at Darrell Loverin’s blog. I need to give a shout out to Darrell for helping me work through the new feature and how to make this all work in Flash Builder 4. Which is the approach I wanted to try and make work instead of the more common method of build scripts. Some parts of the Flash Builder 4 approach might change in the future as the IDE changes, and some parts are easier with using custom flex-config.xml and ANT builds. But if you don’t know or have an ANT setup or don’t know about flex-config.xml it doesn’t make a difference and I wanted to show how to do it without all that.

Source Code Used in the Post

Flex Hero SDK
RSLCommon.fxpl
RSLPatchHero.fxpl
RSLTestHeroMonkeyPatch.fxp

The three Flex projects included above are the main Flex project “RSLTestHeroMonkeyPatch” and two Flex Library projects “RSLCommon” and “RSLPatchHero“. The RSLPatchHero is where the monkey patch class is and the RSLCommon holds the com.renaun.preloader.TimedPreloader class from the previous post (which provides us with a way to see RSL load ordering). Now for the fun stuff.

RSLPatchHero and creating a Monkey Patched RSL

For the monkey patching I created the RSLPatchHero Flex Library project. Then copied the spark.components.Button class from the Flex Hero SDK. Opening up the spark.components.Button class I added my code patch by adding an override method of the label setter, see below:

override public function set label(value:String):void
{
    // label property is just a proxy to the content.
    // The content setter will dispatch the event.
    content = "Monkey Patched FlexHero: " + value;
}

There will be some compile errors because the ButtonIcon in the metadata and the Version.as file are not in my source path. I went ahead and commentted these out, alternatively I should have copied the files over to the project with the right paths. Now that I have a monkey patched spark Button I need to get the compiling right. Lets first check out the defaults. With the Flex SDK defaulting to “Use default(external)” linking of the framework libraries and adding a compiler argument to output a link report I find out that the swc only includes our custom Button class and a bunch of “external-defs” (see link.rpt).

NOTE: Let me step back and try and give the context of libraries and the complexity of linking. The main goal is to figure out the exact amount of classes needed allow for loading of those classes before any other class by the same name (as first loaded rules). Next figuring out what classes are in which libraries to figure out ordering of library loading. We can’t just have a swc with Button in it because its based on ButtonBase, and if we want our swc to load before the spark.swc, which is where ButtonBase is we need to make sure ButtonBase is in our custom swc. But any classes that Button use that are in framework.swc can be linked externally because it can be loaded first. Depending on how much monkey patching you are doing be aware of these kind of relationships. There is a swcdepends tool in the Flex SDK that can help with this.

Now to get the classes that the custom Button class depend on into the swc I needed to merge the libraries into the project instead of using the default external linking setting.

With the merged link type on I looked at the link.rpt. What I found was the swc included a bunch of classes. By comparison this project with “Merged into code” setting:

  • Flex 4 SDK – 600kb
  • Flex Hero SDK – 361kb

The difference is in the fact that with Flex Hero the framework.swc was separated into two swc’s, framework.swc and mx.swc. The next step is to use the new Flex Hero feature -include-inheritance-dependencies-only. Go into the project’s properties -> Flex Compiler -> Additional compiler arguments input box and add -include-inheritance-dependencies-only. The result now is:

  • Flex 4 SDK – 600kb
  • Flex Hero SDK – 361kb
  • Flex Hero SDK – 85kb (with -include-inheritance-dependencies-only)

Cool now the swc only has the classes that have to be around for Button to work. Looking at the link.rpt I discovered there are classes from spark.swc and framework.swc that are included into the custom swc. Now I know that I want the framework.swc classes to be loaded through the official framework RSL, and since my monkey patched Button class is a spark component it has to be before the spark.swc RSL. This means I can go tell framework.swc to not be merged into my custom swc. This also tells me the ordering in which the RSL’s have to be loaded: framework.swc, RSLPatchHero.swc, and then spark.swc. First lets remove framework.swc classes from the custom swc by opening project properties -> Flex Build Path -> Libraries tab -> then opening to the Link Type of the framework.swc, shown below in the image:

Select the Link Type row and click the Edit button. Now uncheck the “Use the same linkage as framework” and then select Link Type of External. Now the custom swc will only hold the needed classes from all the libraries beside framework.swc. This creates a swc size of only 16kb.

  • Flex 4 SDK – 600kb
  • Flex Hero SDK – 361kb
  • Flex Hero SDK – 85kb (with -include-inheritance-dependencies-only)
  • Flex Hero SDK – 16kb (with -include-inheritance-dependencies-only and optimized library linking)

Using the RSLPatchHero in an application and RSL Load Ordering

I created a RSLTestHeroMonkeyPatch project and added references to both the RSLPatchHero and RSLCommon Flex Library projects. The main application is just a default spark Application with a single spark Button:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               preloader="com.renaun.preloader.TimedPreloader">
    <fx: Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx: Declarations>
    <s:Button label="Test Button" />
</s:Application>

If you run the application right now without any changes it will not show the monkey patched spark Button because it loads the RSLPatchHero RSL last. I know the ordering needs to be framework.swc, RSLPatchHero.swc, and then spark.swc. Its kind of a process to make this work in Flash Builder 4, here are my steps I followed (and the ordering of these steps are important):

  1. Navigate to project properties -> Flex Build Path -> Library Path
  2. Made all the libraries load as RSL (except RSLCommon).
  3. Deselected the “Automatically determine library ordering based on dependencies” check box.
  4. Select Flex 4.5 and hit the Remove button
  5. Repeat these sub-steps for framework.swc, textLayout.swc, RSLPatchHero library (use Add Project instead of Add SWC), and spark.swc
    1. Click on “Add SWC…” button and added the framework.swc directly from its location in the Flex Hero SDK ($FLEX_HOME/framework/libs/framework.swc)
    2. Select framework.swc library, expand and select Link Type, then hit Edit
    3. In popup set Link Type to “Runtime shared library (RSL)”
    4. Select “Digests (recommend)” and hit the “Add…” button
    5. Keep defaults and click “Ok”. NOTE: For production builds you’ll want to come back in an added the proper policy file URL’s for both the offical RSL’s and roll over values. These can be found in the corresponding Flex SDK’s flex config.xml. But since Flex Hero is not official there is no live official RSL’s to use.
  6. Click on the “Add Flex SDK” button
  7. Expand the Flex 4.5 library and remove framework.swc, spark.swc, and textLayout.swc
  8. Selecting the libraries move them up and down to have an order as seen in the picture below.

Here is the picture of what the final settings of the project are:

At this point the Flex project will run and display the monkey patched Button. Download the source projects and give it a try for yourself.

  • NLW

    The least size mentioned are those swc sizes or swf sizes?
    Flex 4 SDK – 600kb
    Flex Hero SDK – 361kb
    Flex Hero SDK – 85kb (with -include-inheritance-dependencies-only)
    Flex Hero SDK – 16kb (with -include-inheritance-dependencies-only and optimized library linking)

    • http://www.renaun.com Renaun Erickson

      Those are SWC sizes. The actually RSL swf size on the release build of RSLPatchHero.swf is 6kb.

  • Pingback: Swf.hu 2.0 – flash és webfejlesztés » Flex Hero végre elérhet?

  • http://blog.mosessupposes.com Moses Gunesch

    Renaun, thanks so much for addressing this huge pain point in Flex. I hope this process becomes a lot easier in the future.

    There’s a somewhat bitter taste to this subject knowing that developers have been crying out about Adobe’s overuse of the private namespace for many years, and that if they’d changed that practice with Spark the framework would simply be extensible instead of requiring backflips to hack and patch, but at any rate I’m glad there’s someone on their team pulling for the rest of us now!

    Thanks also for pushing out the upcoming Spark components in Hero early — I’ve just recently built my own global thumbnail caching and prioritized load-queuing for the nth time and am thrilled to see it added to the framework. I’m guessing you had a personal role in getting those early-released and wanted you to know that those efforts are very much appreciated! :-)

    • http://www.renaun.com Renaun Erickson

      The Flex Team has been working hard on a lot of improvements, the credit is due to them. We should see more exciting stuff at MAX also.

  • http://blog.mosessupposes.com Moses Gunesch

    Renaun,

    I got this to work great for a Spark patch but can’t seem to get it to work for mx, specifically ListBase. I tried using the same methodology of breaking it out of the SDK into an RSL but it didn’t grab. Perhaps that class is included in frameworks.swc or something. Let me know if you can suss out a way to patch an mx class, thanks!