Flex Monkey Patching and Framework RSLs

The Flex Framework RSLs (Runtime Shared Libraries) are a great way to reduce download time for your Flex application. But they have an unfortunate side effect… They break the ability to monkey patch Flex framework classes. The reason for this is the way that the Flex compiler structures a SWF file. Every Flex application has two frames. You can think of a “frame” as a container for compiled ActionScript classes. The Flex compiler puts as few things into the first frame as possible. This is so that the loading progress bar can come up quickly (as soon as the first frame has loaded). If you put too much on the first frame then you wouldn’t see anything happening until the whole first frame is loaded. When you monkey patch a Flex Framework class it usually will go into the second frame. The problem with monkey patching and the framework RSLs is that the RSLs get loaded in the first frame. The Flash Player’s class loader won’t overwrite classes so when the preloader finishes loading and then starts loading frame two (where the monkey patched class is) it will not overwrite the class loaded from the RSL.

The solution is to get your monkey patched class onto frame one. The easiest way to do this is to create a custom preloader that contains a reference to the monkey patched class. Here’s a simple one in which my monkey patched class is mx.controls.Button:

package
{
	import mx.controls.Button;
	import mx.preloaders.DownloadProgressBar;
 
	public class MyPreloader extends DownloadProgressBar
	{
		public function MyPreloader()
		{
			super();
 
			if (0)
			{
				var b:Button = new Button();
			}
		}
 
	}
}

Make sure you then tell your application to use your custom preloader:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preloader="MyPreloader">

Now since Button is referenced from the preloader the Flex compiler will put Button and all of its dependencies on frame one. The monkey patched Button class will then be loaded BEFORE the RSLs thus making monkey patching work again! But the big caveat here is that now you have a ton of stuff on frame one (Button and all its dependencies – which we are trying to leave out of our SWF in the first place). And now the user won’t see the preloader progress bar until all of frame one is loaded – which now takes significantly longer than before.

While this works, it’s not ideal. What we need is a way to shove a single class into frame one. I’ve tried every way I can think of to do this but to no avail. What I’d hoped would work was to put my monkey patched class but none of its dependencies into a SWC and then use the -compiler.include-libraries mxmlc compiler flag to shove the monkey patched class into my SWF. But I couldn’t get compc to put just my monkey patched class into the SWC. Here is what I tried:

${FLEX_SDK}/bin/compc -source-path=src -debug=false -o=build/monkey.swc \
-external-library-path=${FLEX_SDK}/frameworks/libs,${FLEX_SDK}/frameworks/libs/player/9/playerglobal.swc \
-include-classes mx.controls.Button

But it appears that since compc sees the mx.controls.Button class in the -external-library-path it decides it doesn’t need to put my monkey patched Button in the SWC despite me telling it to.

Maybe someone else has some tricky way of getting just the monkey patched class into a SWC or onto frame one of the SWF. Otherwise please go vote for bug #19735.

This entry was posted in Flex. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

13 Comments

  1. Christian H. Mosveen
    Posted March 11, 2009 at 6:01 am | Permalink

    Wild guess: Could you do something with the Frame metadata? http://blogs.adobe.com/rgonzalez/2006/06/modular_applications_part_2.html

  2. Astor Digital
    Posted March 11, 2009 at 11:58 am | Permalink

    in your compiler arguments you can use -ic=com.adobe.utils.Library

    where Library is a class containing the reference to Button class.
    //Library.as
    package com.adobe.utils
    {
    import mx.controls.Button;

    public class Library
    {
    //create instance
    var button:Button;
    }
    }

  3. Posted March 12, 2009 at 3:04 am | Permalink

    Great info, never cross my mind before, thanks.

  4. Posted March 12, 2009 at 11:18 am | Permalink

    Thanks Christian and Astor. I tried both ideas. Couldn’t get either to work. I need someone with a bigger brain to figure this out. :)

  5. Darrell Loverin
    Posted March 13, 2009 at 5:35 am | Permalink

    You can load your monkey patched class before the Flex RSL without bloating frame 1.

    1. Use compc to compile Button into a SWC.
    2. Make an RSL from the SWC.
    3. Load the monkey patched RSL before the Flex RSL.

    This doesn’t solve the “only add the Button class without its dependencies” problem but it will make frame 1 smaller.

  6. Posted March 13, 2009 at 7:24 am | Permalink

    Thanks Darrell. That’s a good point. And a great reason to get bug #19735 fixed. :)

    I assume that you would also have to move the RSL / Library up in the Library Path in order to get it to load before the Framework RSLs. Or does the Flex Preloader always load custom RSLs before the Framework RSLs?

    -James

  7. Posted June 4, 2009 at 4:35 am | Permalink

    I looked at the bug and it is closed. But I am not able to generate swc file with a single component. I get the following error say in case of a Button:
    Error: could not find source for class mx.controls:Button.

    Are you able to generate swc ? Is it really fixed ?

  8. Posted June 11, 2009 at 11:15 am | Permalink

    Hi Chetan,

    I think it’s been fixed for Flex 4.

    -James

  9. Posted October 4, 2009 at 5:16 pm | Permalink

    I’ve come up with better solution of monkey patches and RSLs which solves the problem of unnecessary class importing. You can check it out in my blog

  10. Posted October 4, 2009 at 11:49 pm | Permalink
  11. Posted January 25, 2010 at 9:36 am | Permalink

    Here are more details on my comment posted on 03/13/2009.

    http://blogs.adobe.com/dloverin/2010/01/how_to_monkey_patch_when_using_flex_rsls.html.

    The preloader loads RSLs in the order specified by the -runtime-shared-library-path options. There is no special treatment of custom RSLs. RSLs with digests and those without digests (specified via -runtime-shared-libraries) cannot be intermingled. RSLs without digests are always loaded after the RSLs with digests. The -runtime-shared-libraries option is maintained for backwards compatibility.

  12. Tom Gruszowski
    Posted March 2, 2010 at 5:56 pm | Permalink

    Can we monkey patch using the Flex 4 compc but include a Flex 3 file?

  13. Posted March 3, 2010 at 7:55 am | Permalink

    @Tom

    Maybe. It depends on what you are including.

2 Trackbacks

  1. [...] James Ward – RIA Cowboy » Flex Monkey Patching and Framework RSLs (tags: flex hack) This entry was posted on Wednesday, March 11th, 2009 at 7:08 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. « links for 2009-03-10 [...]

  2. [...] One of the possible solutions of this problem is creating a custom preloader (which is a must for a professional-looking application) and creating references to monkey patched classes there. That way these classes (and all their dependencies) are included in the first frame of the application. But this increases size of the preloader significantly and actually defeats it’s purpose, so I don’t think that solution is appropriate. This solution is described in detail by James Ward in his blog. [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Subscribe without commenting

  • About James Ward



    View James Ward's profile on LinkedIn

  • First Steps in Flex by James Ward and Bruce Eckel




  • Twitter Updates


  • Tour de Flex