Sunday, July 20, 2008

Web app to extract torrent files out of Blizzard Downloader

Diablo 3 was announced today and like many thousands of other gamers online right now I’m trying to download the 800mb high def gameplay trailer while putting up with the very clumsy Blizzard Downloader application. For those who don’t know, the Blizzard Downloader is just a mini BitTorrent client with a single torrent file baked in. I’m not a big fan of the downloader because I already have a BitTorrent client that’s much better at bandwidth allocation and my firewall’s already set up for that client. I’d much rather download the movie with my own client instead of Blizzards so I’ve written a little flash app to help facilitate that.


To use this, just point the app at the url of any Blizzard Downloader exe file online (I’m not sure if it’ll work with the .dmg files) and hit the ‘Extract’ button. A link will pop up below that you can click to save the torrent file. The file has no name by default so you’ll have to rename it ‘whatever.torrent’ after it finishes downloading. The resulting torrent will still connect to Blizzards tracker and you’ll download the same file you would be if you were using the Blizzard Downloader app.

This should work with all browsers other then IE 7 and below, since IE doesn’t support the data:URI scheme to create dynamic files.


View Source

Example URLs:
Diablo 3 Gameplay Downloader
Starcraft 2 Gameplay Downloader

More Info:
Blizzard Downloader Wiki


Introducing GUIMark - An RIA benchmark for Flex, Silverlight, HTML and more

If you’re wondering why I’ve been quiet the past few weeks it’s because I’ve been devoting most of my free time to finishing off a new benchmark I’m releasing today called GUIMark. GUIMark is kinda like an Acid3 test on speed that’s geared towards RIA technologies. The goal was to figure out how to implement a reference design in different runtimes and then benchmark how smoothly that design could be animated. So far I have implementations in DHTML, Flex, Java, Silverlight 1 and Silverlight 2. All the results and and implementation details can be found under the GUIMark page.


GUIMark shares alot in common with another RIA benchmark Bubblemark. I’ve written a bit about Bubblemark and why I think an alternative is necessary, but I do believe Bubblemark and GUIMark can coexist while serving 2 different purposes. Alexey Gavrilov stated it best in that he sees Bubblemark as a sortof ‘Hello World’ launchpad into comparing different environments and I agree with him. Bubblemark is a *very* accessible test suite and its easy for any kind of developer to jump in and play around with performance techniques. GUIMark takes a different approach by trying to benchmark the types of UI elements common in our Web 2.0 world. This includes things like vector redraws, alpha transparencies, text reflow, bitmap motion, and 9 scale slicing rules. From there I just fill up the render pipeline until it becomes so over-saturated that it becomes easy to visually distinguish which rendering engines are more efficient then others. As a result, the benchmark is more complicated on a visual level and requires a bit more time then Bubblemark to understand the implementation rules. Lastly with GUIMark I’ve tried to get into some of the lower level details behind how rendering engines work and how that’s affected the creation of this project.

I’m hoping that developers and designers will be able to use this test suite to identify any pros or cons to choosing a particular environment when visual transitions are a key element of the experience. I’m also hoping these benchmarks provide a spotlight for the community that we can turn toward the runtime engineers inside Sun or Adobe or Mozilla to demand better performance.

Go to GUIMark home page

From AS3 to Objective-C: Flex vs iPhone development

Recently I’ve been given the opportunity to work full time on commercial iPhone development at EffectiveUI. The most intriguing thing about the platform for me is having access to non traditional user input mechanisms. When I was playing around with Wii remote integration on the desktop, the potential was exciting, but the ubiquity was limiting. In the same way that pc game companies develop for the keyboard and mouse first and then provide hooks for joysticks after the fact, I knew that serious Wii remote integration in a desktop app was limited. Knowing that I can write software for the iPhone that always has access to multitouch and accelerometer data from the outset really allows for unique gestures as a first class citizen within an app.


After working with some code and spending time with the SDK itself, I couldn’t help but naturally compare UI development on the iPhone with GUI frameworks like Flex or Swing, heres the things that stand out so far.

  1. I’m really spoiled by higher level languages. A good high level language like ECMAScript, Ruby, or Java rides the fine line of “Making things as simple as possible, but no simpler”. I’ve never felt constrained by the language features in these technologies, only by the apis exposed. Stepping *back* into Objective-C certainly provides more power and flexibility in the language, but there’s a loss in productivity for me that I just can’t shake. Some of this loss comes from Objective-C’s design itself, and some of it just comes from XCodes introspection ability. For instance, I’m not sure if I’ll ever get to the point where I can read these lines of Objective-C as effeciently as their ActionScript counterparts would probably look.
    NSString *aString = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
    
    UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

  2. Closed source UI frameworks suck. Most of what I learned about custom UI development in Flex I learned by inspecting the source code for the bundled controls. Ripping open Containers to see how layout rules are determined, or Lists to see how delegates are passed around, or the Image control to see how different display types are handled provides invaluable gems about implementing Flash apis. It has also helped me optimize the interactions of an app knowing the intentions of the developer who created the UI controls. With the iPhone SDK, you’re given documentation for the visual components, but no source to help determine how they work.

  3. Core graphics and animation is really strong. Between Quartz and the OpenGL layer there’s alot of potential for getting easy access to some of the more complex visual hacks. Although I think 3D user interfaces are prone to usability issues, the iPhone is a much better device to explore them on then a standard keyboard and mouse interface.
  4. Data binding, event listeners, and mxml. The Flash Player and Flex model provide features on top of the ActionScript language that arguably optimize UI needs and keep development more declarative. Cocoa development could really benefit from a ‘gui compiler’ that takes Objective-C to a higher level and bakes in features that support common ui design patterns.
  5. Garbage Collection. Objective-C 2.0 provides a unique system that lets you create objects that will be automatically garbage collected, or you can continue to manually manage object allocation/deallocation yourself. The concept sounds cool, but I can imagine allowing both systems to be mixed within the same project is just begging for trouble.

So far I think that Objective-C has alot of power and some really awesome features that outclass GUI features in Flash, but compared to Flex development as a whole, I’d have to say that XCode and the included visual frameworks are not as sophisticated.

Updated ‘Elastic Racetrack’ for Flash 9 and AVM2

In 2005 Ted Patrick posted a great article on the frame execution model inside the Flash Player that he dubbed the ‘elastic racetrack‘. It’s served as a great reference for me over the years to help understand how code execution and rendering were balanced within the processing of a frame. Since the introduction of Flash Player 9 and the new AVM2, I’ve noticed a few changes to the elastic racetrack model and thought I’d share them. This information is based on research into Flash player internals as well as observations I’ve made playing around with the event and rendering model, but the full model hasn’t been confirmed by Adobe engineers.


The basic premise of the original elastic racetrack is still the same. Given a specific frame rate to operate on, the Flash player will devote the first segment of the frame to execute code, and the second segment to render display objects. Either segment can grow its part of the racetrack to accommodate more processing and effectively extend the duration of the frame.

Flash Player Elastic Racetrack

What changes from the previous model is how those segments look under a microscope and how they come together to form a ‘frame’.

AVM2 is controlled by what I’m going to call the Marshal. The Marshal is responsible for carving out time slices for the Flash Player to operate on. Its important to clarify up front that these time slices are not the same thing as the framerate compiled into a swf, but we’ll see below how the player ultimately synthesizes a framerate from these slices. Running a Flex compiled swf within Firefox under Mac OS X, the Marshal appears to be carving out 19-20 millisecond slices, but this can be different between platforms and browsers based on what I’ve observed as well as Adobe employees have hinted at. This can also change depending on how the swf was compiled, see some of the comments below. For the sake of the article lets assume we’re only talking about a 20 millisecond slice to make the math easy. This means the Marshal will attempt to generate and execute no more then 50 slices each second, and it may be less depending on the elasticity of code execution or rendering. Inside each slice, 5 possible steps are processed in the following order.

  1. Player events are dispatched - This includes events dispatched by the Timer, Mouse, ENTER_FRAMEs, URLLoader, etc…

  2. User code is executed - Any code listening to events dispatched by step 1 are executed at this stage.
  3. RENDER event is dispatched - This special event is dispatched when the user calls stage.invalidate() during normal user code operation.
  4. Final user code is executed - User code listening specifically for step 3 is executed at this point.
  5. Player renders changes to the display list.
p style="text-align: center;">AVM2 Marshalled Slice


The Marshal executes this 20 millisecond slice over and over and decides on the fly which actions to run. The exact actions processed within a slice will ultimately derive the 2 main racetrack segments (code execution and rendering) that constitute a ‘frame’. User actions and Invalidation actions fill up the code segment track, while Render actions fill up the render segment track. Its important to note that actions will only occur at times predetermined by the Marshal, so a if you have a short running User action, the Marshal will still wait a few milliseconds before moving on to the Invalidate and Render actions.


The best way to illustrate which actions are run and how the elastic racetrack is created, is to look at how those slices are processed on a swf running at 5 fps, 25, fps, and 50 fps.



Flash Frame Marshaling Diagram


As you can see, the elastic racetrack performs different actions per frame and requires a different visual illustration depending on the framerate that the player is trying to synthesize. So for a swf running at 5 fps, each frame processed 10 User actions, 1 Invalidation action, and 1 Render action. At 25 fps, each frame processed 2 User actions, 1 Invalidation action, and 1 Render action. At 50 fps, each frame processed 1 User action, 1 Invalidation action, and 1 Render action. Whats important to note in the above chart is that some events are only available in certain slices. For instance, the Event.ENTER_FRAME event will only ever be dispatched in a slice that occurs at the start of a frame.


So what does this all mean? Theres a couple quick ideas to take away from this.



  1. Long running code execution or render segments can extend a given slice beyond 20 milliseconds. Elasticity will be applied to that particular slice and the duration of the frame may or may not be extended as a result. The Marshal may drop the number of slices that constitute a frame in order to keep the active framerate close to the compiled framerate.

  2. A swfs real framerate won’t exceed the Marshals rate defined for the player instance. You can set your compiled framerate at 120fps, but Flash will still only process 50 slices max that generate 50 render calls (more or less depending on the system config).

  3. Code can be executed more often then the compiled framerate. A swf compiled at 1 fps can execute a Timer or Mouse event in every slice, even though it will only render in the last slice. Additionally, if you choose, you can render to the screen sooner then the compiled framerate by calling updateAfterEvent() , but only within a Mouse, Timer, or Keyboard event handler. In this instance though, the Marshal will consider that the end of the frame and start a new frame on the next slice. Lastly, Flash will force an automatic render when mousing over any Sprite that has had its visual properties (x,y,width,height,etc..) changed, naturally this still occurs at the end of the slice and any prerender logic will still run.

  4. Compiling a framerate that isn’t a multiple of the total number of slices per second for your platform will cause irregular rendering as it tries to divide up the slices. If you were to compile in a framerate of 20 on a platform executing 50 slices per second, then the player has to render 2 frames every 5 slices and would follow a 3-2-3-2-3-2 slice-to-render rate.



These 4 facts are moving targets though, since for this article we’re working on a 20 millisecond slice that’s processed 50 times per second. In reality you’ll see time slices as low as 5 milliseconds or as high at 100 milliseconds and some of the math will change as a result.


If you’d like to test this model for yourself, the easiest route is to create a swf running at 1 fps and another at 100 fps both with a Timer object set on a 1 millisecond interval. Inside the Timer event handler change the x property of a display object and hook a bunch of getTimer() traces up to different player events like Mouse, EnterFrame, and Render and watch the carnage unfold in your console. The rest of the information you can’t derive from the results comes from alot of context about the player I’ve learned over the past 2 years and so isn’t as easily visible. If anyone has any information to help add to or correct the above model, please submit it in the comments.


Thanks to several readers who have clarified some of the differences between Flex and Flash as well as how the Flash API is able to change the default behaviors described above.














Why Bubblemark is a poor ui benchmark




A few months ago someone on the Adobe boards asked why the Flex testcase in Bubblemark seemed to act so different in AIR versus in the browser. Yesterday, I saw the same question come up again and I figured I’d finally weigh in on the topic. The simple answer is that the test was created improperly, the complex answer has to do with the inherent limitations of the test itself.



First off, for those who don’t know what the Bubblemark test is, its a simple animation test case implemented in different GUI frameworks, its kinda like an Acid2 test for rendering speed. The charts should ideally give you a base number to understand how well one technology compares against another for rendering. As a GUI developer I’ve been a bit underwhelmed with the whole thing and heres why:



  1. The author doesn’t understand Flash’s rendering engine. The easiest way to illustrate how incorrectly the Flash test was designed, is to download the source and change the compiled framerate to 1 fps. Re-compile and run the test and you’ll notice the benchmark framerate running at ~50 fps. You can clearly see the balls only moving once per second, yet the test thinks its flying along. This is because the testcase makes the incorrect assumptions that changing the properties of a DisplayObject causes it to render right away. The reality is, Flash holds on to all display updates till the next render pass and applies all the latest changes at once. Changing the position of an object every 5 milliseconds is meaningless when Flash is bound by a 33 millisecond render pass (or whatever you’re framerate divided by 1000 happens to be). A correct test case would rely on an ENTER_FRAME handler to change x and y values and get rid of any Timer calls.

  2. Framerate tests above 60 fps are meaningless. Seriously, any GUI benchmark designed to test above 60 fps is bogus. In fact, a pretty simple optimization technique for Adobe or Sun would be to cap the paint requests that get forwarded to OS X or Windows, simply because the majority of computer users these days are on LCD panels which natively run at 60 fps. Some operating systems even go a step further and limit the effective framerate of paint requests it sends to the videocard (see Beam Sync on Mac). So when you see the Java test case fly up to 120 fps on Bubblemark, you can realistically only see 60 of those frames, and there might be a chance the other 60 are never even calculated by Javas layout engine.

  3. The test just moves balls around! This is my biggest beef with the benchmark because it only tests one simple aspect of the rendering engine in these technologies, which is bitmap translation. How do bitmaps moving around the screen tell you anything about the capabilities of the respective technologies? Do the JavaFX guys really think optimizing this usecase will make their technology relevant? The only thing Bubblemark will tell you is which runtimes might best handle bitmap particle emitters….thats about it. Theres a lot more that goes into both the layout engine and the rendering pipeline of these different technologies and its a shame that only the most basic aspect is being tested. The funny thing is, if you open up your task manager while running the tests, you’ll notice that several of them don’t even try to run at full speed, my CPU is sitting as low as 20% in some cases. This means the runtimes don’t even consider the test difficult enough to give it full attention and have opted for using less power over faster motion.



I don’t mean to cut down the developers responsible for Bubblemark because at least they came up with a simple way to help us all compare these different technologies, I just think its a bit misguided to put any meaning behind these numbers. When evaluating your options for a GUI framework in our flashy web 2.0 world, you need to consider how well a technology can handle object scaling, alpha transparencies, rotations, text reflow, along with basic x and y translation and dynamic redraws. Even more realistically, developers need to be aware of the limits in the 25-45 framerate region since this is where you can efficiently balance render complexity with smooth animation. I’ve uploaded a couple quick test cases in Flash, HTML, and Silverlight that I think provide a good foundation for stressing a rendering engine and hopefully I’ll get a chance to expand them more into a full test suite.














Kick starting the garbage collector in Actionscript 3 with AIR




During the final months of my work with eBay Desktop, my sights were set squarely on optimization, both memory and cpu. When it came time to start messing with the garbage collector, my sanity went from bad to worse. What I originally thought was going to be a straightforward way of releasing memory in AIR turned into a 2 month long testcase with some discouraging outcomes.


Memory usage in eBay Desktop was something that always lingered in the back of my mind during the entire development cycle. Because of the shifting nature of our requirements, the issue was only explored near the end, even though we knew in the beginning that memory usage had to go through valleys and peaks in a managed way while users spent time in it throughout the day. We had alerts that would open and close, we had an app that would run in the system tray, and we considered making a ‘lite’ mode that would sit on top of your desktop all day, each of which had different memory requirements. In the beginning we used a well known hack to test garbage collection until part way through the development of AIR and Flex 3 Adobe finally added support for calling the garbage collector directly. We knew at this point we had a viable route for managing memory since Adobe was now making the effort to acknowledge the need. So now all that was required was a simple call to



flash.system.System.gc()

and we were set to go….right?


Well, not exactly. First off we learned that a call to System.gc() only does a mark OR a sweep on any given object, but not both in the same call. So in order to have the effect of releasing memory back to the OS, we needed to call it twice in a row. One call to mark any dereferenced objects and sweep away old marks, and the second to now sweep away marks from the first call.


flash.system.System.gc();

flash.system.System.gc();

Now this seemed to be releasing memory back with pretty basic test cases, but it wasn’t working under production scenarios and we had to turn to Adobe engineers to help with the problem. What we learned was that you have to contend with 2 different kinds of pointers when working in AS3; pointers that exist in bytecode, and pointers that *may* exist in the Flash player itself that you’d never know about. What I started to realize was that the Flash player was never really engineered to be aggressive about memory usage. It was designed to plug memory leaks and manage memory plateaus, but not designed with an assumption that users would be interested in lowering those plateaus. It makes sense because most Flash content is viewed in the browser for a short amount of time before the plugin is destroyed and all memory is released when a user navigates away. With AIR, the rules changed since users are more conscience of discreet application memory usage and applications might not always need the same memory when launched vs after 2 hours of usage.


First up we found that the Flash player was always maintaining a reference to the last Sprite clicked, so if you destroyed an AIR window that the users had interacted with, you couldn’t get garbage collection to work until interacting with another window, which can become a big problem if you’re running in system tray mode and there are no windows to click in. Secondly we learned that you have to push any existing enterframe handler off the call stack by creating a new one. Adobe took care of the first problem, but to handle the second one we had to change our GC call a bit.


private var gcCount:int;

private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
}
}

Another facet we hadn’t considered was the affects of the Flex framework on garbage collection. Flex kept some of the same design philosophy as the player itself, mainly that end users were loading applications in the browser and then navigating away when done. Garbage collection was therefore considered on a micro level involving user components, but not at the framework level which could be guaranteed to exist throughout the life of the app. Adobe made strides on patching the framework to work better in discreet Windows, but ultimately some things couldn’t be changed. What we found was that CSS could not be defined in any <mx:Window> component. It had to be defined in the root <mx:WindowedApplication> which would take care of declaring CSS globally for all windows. Also we were forced to clear some global variables ourselves, which caused our code to now look like this.



private var gcCount:int;

private function startGCCycle():void{
ContainerGlobals.focusedContainer = this;
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
}
}

Lastly, not all features in AIR could be unhooked with our enterFrame trick, after another couple days of testing we found components that needed to be unhooked with Timers like the HTML component. One last tweak to our garbage collection cycle and we were home free.


private var gcCount:int;

private function startGCCycle():void{
gcCount = 0;
addEventListener(Event.ENTER_FRAME, doGC);
}
private function doGC(evt:Event):void{
flash.system.System.gc();
if(++gcCount > 1){
removeEventListener(Event.ENTER_FRAME, doGC);
setTimeout(lastGC, 40);
}
}
private function lastGC():void{
flash.system.System.gc();
}

We were now able to successfully garbage collect any objects that have been dereferenced in Flash. We had three things we had to look out for in the app now.



  1. All display objects that added listeners on to model data had to be weakly referenced or they wouldn’t be automatically dereferenced. This is because our architecture kept model data alive while individual window stages were being destroyed. I feel like I should point out that contrary to some beliefs, it is not a good idea to apply weak references by default throughout your entire app. Trust me when I say that its alot easier to debug an application with memory leaks due to strong listeners, then it is to debug an app in which users report random failures because underneath the hood weakly referenced objects are getting accidentally destroyed when the GC kicks in. You can never avoid bugs, so you should program in a way that makes them consistent to find.


  2. All asynchronous events needed to be explicitly shut down. This included Timers, Loaders, File and DB transactions. Setting these to be weakly referenced is not enough as all asyncronous objects in AS3 register themselves to the Flash player while they are running. It is impossible to access objects that have been dereferenced in code but continue to be referenced by the player like a running timer.

  3. No anonymous closures allowed.


After all this was taken care of we began to learn that garbage collecting objects in Flash didn’t translate so easily to releasing memory back to the OS. If you ever look at the memory graph in the Flex debugger and then open up the Task Manger or Activity Monitor to compare memory usage, you’ll notice a huge disparity between the two.


Flex Builder memory profiler

FlexBuilder reports only 15mb of AS3 object data


AIR system memory profile

AIR private memory really takes up 65mb on the system


The difference you’re seeing is Object Memory vs. Rendering Memory and the bulk of all memory used by the Flash player goes toward rendering. Displaying an empty stage in Flash can take up anywhere between 10mb and 20mb depending on the width and height and then it climbs by roughly 4k for each display object attached to the stage. This can add up quickly when using the Flex framework where even a simple button uses several display objects.


What we ultimately found was that even though we could successfully release AS3 objects, we couldn’t reliably get the Flash player to release render data. So an app that started at 20mb would climb to 100mb, and when the entire stage was destroyed, we’d go back down to only 80mb. You can actually test this for yourself by downloading a sample Flex 3 project and observing the effects. What I’ve learned from Adobe is that the player ends up fragmenting memory quite a bit. It probably goes back to the heart of the initial design of the Flash player I described above. All the effort was put into making a killer GUI environment that deferred memory management to whether the browser window was open or not, and as a result the memory system was not optimized for more aggressive use cases. I can only guess the problem comes from the fact that AS3 code is attached to the timeline of the player itself, and managed by the elastic racetrack. As a result both AS3 objects and render data get mixed in to the same memory page, and releasing just the render data doesn’t matter when model data is placed on the same page.



Adobe has assured me they are working on the problem but it realistically won’t make it in until after AIR 2.0, and its unclear whether those fixes will be merged into the the plugin player given that the need isn’t very high for web pages. Until then, you can not count on creating an application in AIR that releases memory back to the OS. The best approach is to reuse the smallest amount of displayobjects possible to achieve the desired workflow. Get used to adding and removing children without destroying them but instead sliding them off into a pool for later reuse, as this helps keep the memory plateau low during use.














Vampire Weekend




Vampire Weekend performed a pretty fun show at the Bluebird last night. People are going crazy over this band and now I see why. Tickets were originally going for $12 which must have sold out immediately cause up until last week people were willing to pay $100 for a pair.


Horrible blurry photo of Vampire Weekend


I still can’t figure out how to best describe their music , but whatever it is, it makes for a great live performance. I definitely recommend going if you can manage to find tickets still.



Blake’s got a new face!














Hacking width and height properties into Flex’s CSS model




As much as I love working with the Flex layout model, in many ways it feels inferior to its HTML cousin. I’ll take Flex’s container components over HTML tables and divs any day, but I’ve always been disappointed with the fairly weak CSS model found in Flex. From an architectural level the framework decisions makes sense and keeps internal logic fast and clean, but from an implementation standpoint, it becomes an annoying roadblock. Heres a quick example of the problem.


<mx:Style>

.navItem {
vertical-align: middle;
corner-radius: 5;
border-style: solid;
border-color: #F3CB19;
background-color: #A87500;
}
</mx:Style>
<mx:HBox styleName="navItem" height="30"/>

<mx:HBox styleName="navItem" height="30"/>
<mx:HBox styleName="navItem" height="30"/>

In this case, since height is a class property, it must be defined on the HBox instance and can’t be moved into CSS. It makes the code less manageable and adds restrictions to changing themes at runtime.


In order to define class properties with CSS we need to break some of the framework rules. Since we can’t have class metadata defining a value as both a CSS and a class property, we need to leave all metadata as-is, and ‘foward’ the css definitions on to the class. In practical terms what this means is that changing the height in css will change the height on the component, but changing the height directly on the component wont update the css definition. The code below illustrates how this plays out inside a custom component.


package com.craftymind.controls

{
import mx.containers.HBox;
import mx.styles.StyleManager;

public class extHBox extends HBox
{
override public function styleChanged(styleProp:String):void{
super.styleChanged(styleProp);
if(!styleProp || styleProp == "styleName"){ //if runtime css swap or direct change of stylename
var classSelector:Object = StyleManager.getStyleDeclaration("." + styleName);
if(classSelector != null){
applyProperties(classSelector, ["width", "height", "percentWidth", "percentHeight", "x", "y", "visible"]);
}
}
}
private function applyProperties(styleObj:Object, arr:Array):void{
for each (var item:String in arr){
var prop:Object = styleObj.getStyle(item);
if(prop != null) this[item] = prop;
}
}
}
}

When the HBox detects that the styleName or runtime definition has changed, it scans the classSelector for width, height, x, y and visible properties to be applied. You can add whatever properties you want in there including text labels or image sources depending on the component being extended. I haven’t fully tested it so I’m not sure if type selectors work, and I know that calling obj.setStyle(”height”, 10); definitely wont work, but your better off calling obj.height = 10 in that case anyway.


Heres a complex menu system controlled completely with css including y positioning, height changes, and header visibility.




View Source



We now have separation of content from style thats alot closer to what HTML offers, and as a bonus, all property-based databinding continues to work on the values passed through CSS.


<cm:extHBox styleName="header">

<mx:Label text="Header Text"/>
</cm:extHBox>
<cm:extHBox id="nav" styleName="navContainer">
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 1"/>

</cm:extHBox>
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 2"/>
</cm:extHBox>
<cm:extHBox styleName="navItem">
<mx:Label text="Nav Item 3"/>

</cm:extHBox>
</cm:extHBox>
<mx:Button label="Switch CSS" click="switchCSS()" y="{nav.y+nav.height+2}"/>

.header {

background-color: #000000;
border-style: solid;
border-color: #FFFFFF;
border-thickness: 2;
color: #FFFFFF;
x: 0;
y: 0;
percent-width: 100;
height: 20;
visible: true;
}
.navContainer {
background-color: #000000;
border-style: solid;
border-color: #FFFFFF;
border-thickness: 2;
vertical-align: bottom;
horizontal-align: left;
padding-left: 3;
x: 0;
y: 20;
percent-width: 100;
height: 50;
}
.navItem {
vertical-align: middle;
corner-radius: 5;
border-style: solid;
border-sides: "left top right";
border-color: #FFFFFF;
border-thickness: 2;
background-color: #000000;
padding-left: 3;
padding-right: 3;
color: #FFFFFF;
height: 30;
}













Image smoothing in Flex




The Flex Image control doesn’t expose Bitmap smoothing by default but can easily be added in through subclassing the component. Smoothing is a nice feature for removing jaggies from images that have been scaled either up or down, and in practice hasn’t caused any noticable cpu hangups to do the post processing. I’m writing up a patch to submit to the Flex Open Source initiative, but in the meantime, heres a quick and dirty hack to enable it in the Flex 2 and Flex 3 SDK.



Create a new MXML component and name it SmoothImage.mxml, then add the following code.


<?xml version="1.0" encoding="utf-8"?>

<mx:Image xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import flash.display.Bitmap;
override protected function updateDisplayList(unscaledWidth:Number,unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(content is Bitmap){
var bmp:Bitmap = Bitmap(content);
if(bmp && bmp.smoothing == false){
bmp.smoothing = true;
}
}
}
]]>
</mx:Script>

</mx:Image>

Now just use <local:SmoothImage source=”myimage.jpg”/> the same way you’d use a normal image component and you’re all set. This code will take care of smoothing both dynamically loaded images as well as embedded images in one simple script. It also handles broken images gracefully. Heres a quick sample showing the affects of scaling the Google logo with and without smoothing.






And the code used to create this…



<!-- Top Images -->

<mx:Image source="{googlelogo}" width="60" height="25"/>
<mx:Image source="{googlelogo}" width="200" height="90"/>
<mx:Image source="{googlelogo}" width="400" height="180"/>

<!-- Bottom Images -->
<local:SmoothImage source="{googlelogo}" width="60" height="25"/>
<local:SmoothImage source="{googlelogo}" width="200" height="90"/>
<local:SmoothImage source="{googlelogo}" width="400" height="180"/>














Saving class data to disk in AIR




For eBay Desktop we wrote a simple utility for reading and writing classes directly to disk. Using this method we’re able to load the users existing data from disk, or if its unavailable, create a new class with all the defaults.


First up is the utility class AIRUtils


package com.effectiveui.util

{
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;

public class AIRUtils
{
public static function readFileObject(fil:File):Object{
var amf:Object;
if(fil.exists){
var stream:FileStream = new FileStream();
stream.open(fil, FileMode.READ);
amf = stream.readObject();
stream.close();
}
return amf;
}
public static function writeFileObject(fil:File, obj:Object):Object{
var stream:FileStream = new FileStream();
stream.open(fil, FileMode.WRITE);
stream.writeObject(obj);
stream.close();
return obj;
}
}
}

These 2 static methods act as simple helper wrappers to read and write classes out to disk.


The example class we want to save below looks very similar to the type of class we use inside eBay Desktop.


package com.ebay.model

{
import com.ebay.model.SearchPreferences;

[Bindable]
[RemoteClass(alias="com.ebay.model.UserPreferencesModel")]
public class UserPreferencesModel
{
public static const STANDARD:String = "standard";
public static const SKINNY:String = "skinny";

public var logoutOnClose:Boolean = false;
public var viewState = STANDARD;
public var globalSearchFilters:SearchPreferences = new SearchPreferences();

private var _maxHistoryItems:uint = 1000;
public function set maxHistoryItems(max:uint):void{
_maxHistoryItems = max;
}
public function get maxHistoryItems():uint{
return _maxHistoryItems;
}
}
}


In order to write a class out to disk and read it back in, you have to add RemoteClass metadata to it. It doesn’t matter what the value is it just needs to be unique to the application. This provides Flash with an identifier for linking amf data to class definitions when its loaded back in. It doesn’t matter what value you put in the RemoteClass tag, but the best practice is to use the class name of the model you’re saving. Additionally, in this example we’d need to make sure both UserPreferencesModel and SearchPreferences model have RemoteClass metadata, since caching the UserPrefencesModel will automatically attempt to cache the SearchPreferences as a child model.

Only public variables will be cached to disk, so both the static values and the private var will be thrown out, but the public getter/setters will be cached.


Interacting with the cached data using AIRUtils looks like this.


private var fileRef:File = File.applicationStorageDirectory.resolvePath("UserPreferences.dat");

private var userPrefs:UserPreferencesModel;

private function loadPrefs():void{
userPrefs = AIRUtils.readFileObject(fileRef) as UserPreferencesModel || new UserPreferencesModel();
}
private function savePrefs():void{
AIRUtils.writeFileObject(fileRef, userPrefs);
}

When loadPrefs() is called, the cached class is read in and cast as a UserPreferencesModel. If no file exists in the users cache, we end up creating a new class and the defaults defined in the class will be used. This ensures we have something to work with, all within 1 tidy line of code. To save out the file we just pass the file reference and the class instance to AIRUtils.writeFileObject() and we’re done.

GUI Mark Home

Home | Detailed Analysis | Benchmark and Rendering Engine theory

GUIMark is a benchmark test suite designed to compare the rendering systems of several popular UI runtimes. In general it should be able to give designers and developers a good indication of which technologies can draw complex interfaces at a smooth rate of motion. The test mostly addresses RIA technologies like Flash, Silverlight, HTML or Java, but was designed to be easily ported to any 2D GUI environment. The basis for this project was inspired by the Bubblemark animation test, but was designed to heavily saturate the rendering pipeline and determine what kind of visual complexity is achievable in the sub-60 fps realm.

The Test

GUIMark referenceThe reference design was originally created in Flex and then ported to the technologies listed below. All results listed in the matrix as well as the detailed results page were run on the same Macbook Pro running Leopard for OS X, and running Win XP under a Boot Camp partition. Each test case was run 3 times in a new browser instance and the highest framerate observed was recorded. For the HTML test, the fastest performing browser on a each OS was used in the comparison matrix (Internet Explorer 7 and Safari 3 won for their respective OSes). All subsequent plugin based tests for the OS were tested in those browsers.

My hope is to port the benchmark to all the other untested technologies listed below and I fully welcome any optimizations or ports that readers want to contribute. I’m really curious to see if any community experts or platform engineers are able to speed up their technology of choice. Although the code is fairly simple at a glance, there are no easy optimization paths to be found (and no cheating by turning off anti-aliasing).

Results

Results for Win XP running on Macbook Pro Intel Core 2 Duo 2.33 GHz






Tech BaseVersionAverage FPSSource
BrowserHTML28.36 / IE 7Download
SVG--
Canvas--
FlashFlex 346.08Download
Flash 9--
JavaJava 5 Swing19.37Download
Java 6 Swing--
Processing--
JavaFX--
SilverlightSilverlight 1 / Javascript9.12Download
Silverlight 2 Beta / C#7.95Download

Results for OS X 10.5 running on Macbook Pro Intel Core 2 Duo 2.33 GHz







Tech BaseVersionAverage FPSSource
BrowserHTML18.20 / Safari 3Download
SVG--
Canvas--
FlashFlex 38.01Download
Flash 9--
JavaJava 5 Swing7.19Download
Java 6 Swing--
Processing--
JavaFX--
SilverlightSilverlight 1 / Javascript5.25Download
Silverlight 2 Beta / C#5.38Download

Findings

I’ve been surprised with the results so far between WinXP and OS X. On the same machine its very clear which vendors take more advantage of the underlying hardware. The results for the different plugin technologies aren’t too surprising since it’s regularly admitted that most companies spend their optimization time on Windows due to its larger install base. This argument doesn’t hold any water though when comparing html rendering on Safari/Mac against IE /Windows where there’s roughly a 1.6 : 1 advantage to the IE team. I can’t help but wonder if the core apis on the Mac platform are creating any unnecessary roadblocks. I’m also extremely surprised at the rendering speed that Flash is able to pull off on Windows. I developed this benchmark under OS X and after compiling the results I’m considered making the testcase more intensive since Flash is running so fast, but for now maybe the really poor Mac performance will give Adobe something to work on.

You can read more about rendering engine theory, the structure of the test case itself, and detailed analysis of the results on the sub pages within the site.

Updates

John Dowdell from Adobe brought up a valid point that plugin vendors are restricted by the browser environments they run in. This is true to an extent, but the limitations enforced on plugins don’t come into play with the GUIMark test. Browsers typically restrict the number of event loops available to a plugin which caps the framerate to around 40 - 50 fps. GUIMark doesn’t come anywhere close to hitting that limit on Mac. There are also no restrictions to the amount of cpu available to a plugin running within the browser which is why all of them peg the cpu to 100%. To illustrate the point, I created an AIR implementation of GUIMark and ran it on my Powerbook and here are the results I got. The Flash players rendering engine performs no differently outside the browser then it does inside the browser. Until plugins start bumping up against the event loop or Beam Sync restrictions, Adobe, Sun, and Microsoft don’t get a free pass for slow performance on Mac.

JavaFX Technology Overview (program) in Eclipse (Live Demo)

JavaFX Technology Overview

JavaFX is a family of products for creating rich internet applications (RIA) with immersive media and content, across all the screens of your life. Announced at Java One 2008, it includes a runtime and a tools suite that web scripters, designers and developers can use to quickly build and deliver the next generation of rich interactive applications for desktop, mobile devices, TV, and other platforms. It delivers rich client capability across a wide range of devices and screens as well as unlimited creative expression and accuracy in RIA designs.

The JavaFX family of products consists of the JavaFX Runtime, the JavaFX Tools Suite, and applications powered by JavaFX technology:

JavaFX Runtime delivers rich client capability across a wide range of devices. Examples of JavaFX Runtime are:
* JavaFX Desktop for desktop browsers and desktop applications (available fall 2008)
* JavaFX Mobile (available spring 2009) in the first rollout will deliver the JavaFX rich client runtime on the existing existing platforms that our partners are shipping today. Over time we will deliver additional products.
* JavaFX TV will be for applications that run on the TV platform (available summer 2009)
* Other platforms in the future

JavaFX Tools Suite empowers Web scripters, visual designers, and developers with the freedom to create expressive content, applications, and connected services for consumers of RIA across devices or screens
* JavaFX Development Tools include a plug-in for NetBeans and, in the future, for Eclipse and other IDEs
* JavaFX Designer Authoring Tools:
* JavaFX Media Converter (summer 2008): Tool to export rich media content directly into JavaFX
* JavaFX Designer Authoring Tool (available spring 2009): Tool for visual designers.

JavaFX Suite of Applications: The JavaFX business unit will leverage the capabilities of JavaFX to deliver a suite of content and applications starting in 2009.

JavaFX is a different technology, product and brand than the Java platform. JavaFX is not dependent on any particular JVM or runtime environment, and JavaFX is not built using the JVM specifications. JavaFX leverages the appropriate runtime for each platform - on the desktop it leverages the JRE and is co-bundled with it, while on mobile it leverages the Java ME runtime, and similarly it can run on top of other VMs.

JavaFX Tools Suite Makes Development Easier

Sun recognizes that the communities creating compelling content, applications, and services consist of a wide range of individuals with different skill sets who require specific sets of tools to fit their needs:

Visual designers need visual and graphical tools to create compelling graphics, media, prototypes and rich client applications without requiring any complex scripting or programming. They currently use Adobe Photoshop, Illustrator, and other visual tools. JavaFX designer will deliver a visual authoring tool to this community.

Web Scripters who are currently using HTML, DHTML, CSS, JavaScript, ActionScript, MXML or XAML are looking for familiar and highly productive scripting environments. JavaFX Script is designed to provide an easy-to-learn scripting language to this audience, and the JavaFX runtime is architected to allow the support of additional scripting environments that this community may already be using.

Programmers using Java programming language and other programming languages have a need to work with their scripting and designer colleagues to deliver compelling end-to-end rich interfaces for enterprise applications as well as provide the back-end for RIA content, applications and services. The JavaFX plug-in for NetBeans and JavaFX Media Converter are designed to facilitate this interaction.

Advantages of JavaFX

There are a large number of RIA requirements that remain unmet by any RIA platform, and Sun is uniquely positioned to address these challenges. JavaFX will be provide a number of unprecedented advantages:

Built on Java. JavaFX is not starting from scratch; it is built on the Java platform (Java SE and Java ME) and leverages the power and capabilities of the Java platform. It also extends the Java platform to deliver on the original promise of client-side Java. For example, Java ME has been distributed to 3 billion devices, far exceeding the distribution of Adobe Flash Lite, and JavaFX Mobile will deliver rich client capabilities on top of the Java ME platform.

Across Devices and Screens. JavaFX applications will run across multiple devices or screens - browser, mobile, TV, etc.

Reach and Distribution. Sun will leverage its unrivaled reach to distribute the JavaFX runtime across all devices and screens.

Open Source. Many components of its platform are already available in open source, Sun will announce its open source plans with the release of version 1.0.

Browser and Desktop Deployment. JavaFX will provide support for browser-based RIA applications as well as the powerful capability of deploying the same unmodified application on the desktop. JavaFX designers and developers will have the option to take full advantage of Java’s capabilities, including access to file system, security model, and caching.

Competing platforms are just beginning to provide early SDKs that provide relatively rudimentary capabilities for building browser and desktop resident applications.

Designer, Developer Workflow. Current rich client platforms have been struggling to extend beyond their animation heritage to appeal to developers. There is still a distinct need to close the gap between a designer's vision and a programmer's skills with an easy-to-use, visually accurate, high-performance suite of tools. The market is not nearly satisfied.

Java has more than 8 million developers who provide the infrastructure that powers most businesses and the backend of most large Web applications. JavaFX tools suite will empower designers to better collaborate with these developers while working within the Java platform. At JavaOne 2008, Sun will demonstrate this capability with JavaFX Media Converter.




The JavaFX Script (or JavaFX language) is a declarative scripting language. The JavaFX allows for easy creation of graphical user interfaces and enables developers to create rich media applications for deployment on Java environments. In this screencast, we use the Eclipse IDE 3.2.2 to create simple JavaFX application.

You can get your first JavaFX application up and running in Eclipse SDK easily by following these steps:
1. Extend Eclipse with JavaFX plugin (01:30):


2. Write you first JavaFX program (01:29):

3. Run JavaFX application (00:59):


Invoking Java methods from Adobe Flex

Adoption to Rich Internet Applications is increasing. What about the products which were developed earlier and are not RIAs? how will they adopt RIA? It’s very simple. If your software has a architecture where the business logic is clearly separated from other layers, then you just have to start learning Adobe Flex and develop and RIA. Because Adobe Flex allows us to invoke Java objects on the server from the client side Flex application.


How to invoke Java methods from Flex application?

  1. Add an mapping to the Java class to services-config.xml
  2. Map your RemoteObject (provided with Flex SDK) on the client side to the destination configured in services-config.xml
  3. Invoke the method in your Java class using the RemoteObject instance

What do you need to invoke a Java method from the client side application?

  1. Flex Builder
  2. Blaze DS

Isn’t that simple? Let’s get into details of implementing this.


Set up Blaze DS

Download and setup Blaze DS on your system from http://labs.adobe.com/technologies/blazeds/

You will be downloading Blaze DS with integrated Tomcat server. You just have to start the server by executing startup.bat under tomcat/bin. Please note the port number in which the Tomcat server is running. The port number mentioned below might have to be replaced with yours, if required.

Creating Java class

Create the Java class with the code below and compile it. We should deploy this class in a location, where Blaze DS can find and instantiate this class. Under the folder where the Blaze DS zip file was extracted, navigate to tomcat/webapps/blazeds/WEB-INF/classes and then copy the Java class in appropriate directory structure.

RemoteServiceHandler.java

package com.adobe.remoteobjects;

import java.util.Date;

public class RemoteServiceHandler {

public RemoteServiceHandler()

{

//This is required for the Blaze DS to instantiate the class

}

public String getResults(String name)

{

String result = null;

result = “Hi ” + name + “, this is a service and the time now is : ” + new Date();

return result;

}

}

Creating Flex application

Using the Flex Builder select File -> New -> Flex Project. Create new Flex project window will be displayed. Give your application name and other details. Select the Application Server type to J2EE. Please find the screen shot of the window I filled while developing.

SelectingServerType

Click Next and then Server Configuration window will be displayed. Modify the values in this window to reflect the paths in your system. Please find the sample values in the image below. Select the output folder properly so that the Flex application is compiled directly into the Tomcat web application directory.

ConfigureServer

Once this is done continue with the project creation setup and complete it.

Code to be included in the MXML file to invoke the Java class on the server is available below.

In the RemoteObject, the value of the destination property should be set to the ID of the destination, which will be added to the configuration file (Explained below).

MyApplication.mxml

<?xml version=”1.0″ encoding=”utf-8″?>

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical”>

<mx:Script>

<![CDATA[

import mx.controls.Alert;

]]>

</mx:Script>

<mx:RemoteObject id=”remObj”

destination=”CreatingRpc”

result=”Alert.show(event.result.toString());”

fault=”Alert.show(event.fault.faultString);”

/>

<mx:Button id=”remoteService” label=”Remote Service” click=”remObj.getResults(’Sujit’);”/>

</mx:Application>

This application has been configured to compile the output to the tomcat web application folder. Now that we have done developing the files required on both the client and the server. We need to configure Blaze DS.

Configuring Blaze DS

Navigate to tomcat/webapps/blazeds/WEB-INF/flex and open the file remote-config.xml. Replace the XML file content with the content below. The ID of the destination added below will be used by the components at the client side. Destination added will be map the destination name to the Java class, which has to be invoked.

remote-config.xml

<?xml version=”1.0″ encoding=”UTF-8″?>

<service id=”remoting-service”

class=”flex.messaging.services.RemotingService”>


<adapters>

<adapter-definition id=”java-object” class=”flex.messaging.services.remoting.adapters.JavaAdapter” default=”true”/>

</adapters>

<default-channels>

<channel ref=”my-amf”/>

</default-channels>

<destination id=”CreatingRpc”>

<properties>

<source>com.adobe.remoteobjects.RemoteServiceHandler</source>

<scope>application</scope>

</properties>

<adapter ref=”java-object”/>

</destination>

</service>

Executing the application

Start the Tomcat server. Navigate to http://localhost:8400/blazeds/MyApplication-debug/MyApplication.html in your browser. Click on the Remote Service button and then you can see the message from the Java class. Find the snapshot of the application displaying the response from the Java class below.

RemoteObjectOutput


Using the Flex 2 Tag Library for JSP

In an Adobe LiveCycle Data Services ES web application, complete the following steps to use the Flex 2 Tag Library for JSP in a JSP page:

  1. Add the following tag library declaration to your JSP page:

    <%@ taglib uri="FlexTagLib" prefix="mm" %>

  2. Use the <mxml> tag to insert a Flex application in an existing JSP page. The following example shows the <mxml> tag with the source attribute to include an external MXML file:

    <mm:mxml source="CustomerServiceChat.mxml"/>

    Alternatively, you can use the <mxml> tag with inline MXML source code, as the following example shows:


    <mm:mxml>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
    <mx:Text label="Hello World">

    </mx:Application>
    </mm:mxml>



Use the <mxml> tag carefully, as any JSP execution that results in different MXML source code causes recompilation. Each distinct instance of MXML source code is cached separately and checked for recompilation separately. Two or three distinct versions of MXML source code might be acceptable, but different MXML source code on each compilation would not be.


For example, the following JSP code results in two sets of MXML source code; one is created when request.isUserInRole("admin") is true, and another is created when request.isUserInRole("admin") is false:




<mm:mxml>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*">
<% if (request.isUserInRole("admin")) { %>
<AdminConsole/>
<% } else { %>
<UserConsole/>

<% } %>
</mx:Application>
</mm:mxml>

Use the <mxml> and <flashvar> tags to quickly create a dynamic application. Updating the <flashvar> tag does not cause a recompilation. Although the MXML code was specified inline, the source is static without JSP scriptlets.



The following example uses <mxml> and <flashvar> tags with inline MXML code to get the Java version and current date:



<%@ taglib uri="FlexTagLib" prefix="mm" %>
<mm:mxml height="300" width="600" usePlayerDetection="true" useExpressInstall="false" >
<mm:flashvar name="javaVersion" value='<%= System.getProperty("java.version") %>' />

<mm:flashvar name="currentDate" value="<%= new java.util.Date().toString() %>"/>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" >
<mx:VBox>
<mx:HBox>
<mx:Label text="Java version: "/>

<mx:Label
text="{Application.application.parameters.javaVersion}" fontWeight="bold"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="Current Time: "/>
<mx:Label text="{Application.application.parameters.currentDate}"
fontWeight="bold"/>
</mx:HBox>

</mx:VBox>
</mx:Application>
</mm:mxml>

The following example shows how to invoke an external MXML file while passing dynamic flash variables to it:



<%@ taglib uri="FlexTagLib" prefix="mm" %>
<mm:mxml source="flashvarTest.mxml" width="400" height="200">
<mm:flashvar name="javaVersion" value='<%= System.getProperty("java.version") %>' />

<mm:flashvar name="currentDate" value="<%= new java.util.Date().toString() %>"/>
</mm:mxml>

Use the <mxml> tag attributes to present a Flex application when the correct version of Flash Player is available or an alternate version of the application when the player is unavailable.


In this example, you enable Flash Player Detection but disable the Express Install. With this configuration, the JSP drops directly to the alternateContentPage instead of proceeding to upgrade Flash Player through Express Install.



<mm:mxml source="FlexApplication.mxml" usePlayerDetection="true"
useExpressInstall="false" alternateContentPage="MyLegacyApplication.html"/>


Limitations


If you use the Flex 2 Tag Library for JSP incorrectly, overall application performance can suffer because of excessive recompilation. In general, there are no performance concerns if you use the <mxml> tag and compile MXML source code by using the source attribute.


The following alternative approaches do not modify the actual MXML code that a JSP page generates and do not cause excessive recompilations. Before deciding to use the tag library with your application with inline MXML source code, consider whether one of the following options would be more appropriate:



  • Separate the presentation from the data so that you can use LiveCycle Data Services to populate the data in the application.


  • Pass in the dynamic data by using the <flashvar> tag. You can safely use different name-value pairs on the <flashvar> tag for each JSP page execution, because the differences do not cause a modification and recompilation of the MXML source code.
  • Manipulate the presentation by using ActionScript.

Flex 2 Tag Library for JSP reference

Tag

Description

Attributes

mxml

Compiles the MXML code and generates the HTML wrapper. Includes MXML source as body content, or specify an external source file with the source attribute.

source Location of the MXML code to compile.

id Name used to expose the SWF file through the id or name attribute of the HTML object or embed tag.

height Height of the MXML wrapper.

width Width of the MXML wrapper.

useHistoryManagement Include history management for the Flex application.

usePlayerDetection Include Flash Player detection for the Flex application.

useExpressInstall Install Flash Player through Express Install; ignored if Flash Player detection is disabled.

alternateContentPage Present this alternate page when the Flash Player version is unavailable; ignored if Flash Player detection is disabled.


flashvar

Specifies a variable to pass to your Flex application.

name Specifies the name of the flashvar variable.


value Specifies the value of the flashvar variable.


LiveCycle Data Services ES 2.5

Extracting content from HTML based on JSP server response in Adobe Flex

Using HTTPService component of Adobe Flex we can send a request to a page on the server. Most of pages on the server are developed using either server side scripting languages or static HTML pages that return content in form of HTML to the client. Here we show how to extract the content from HTML response returned by the server and also how to send parameters to the server scripts.

After an RPC component calls a service, the data that the service returns is placed in a lastResult object. By default, the resultFormat property value of HTTPService components and WebService component operations is object, and the data that is returned is represented as a simple tree of ActionScript objects. Flex interprets the XML data that a web service or HTTP service returns to appropriately represent base types, such as String, Number, Boolean, and Date. To work with strongly typed objects, you must populate those objects using the object tree that Flex creates. WebService and HTTPService components both return anonymous Objects and Arrays that are complex types. If makeObjectsBindable is true, which it is by default, Objects are wrapped in mx.utils.ObjectProxy instances and Arrays are wrapped in mx.collections.ArrayCollection instances.

I created a JSP and a Flex application, which will invoke the JSP on the server side and extract the content from the response in HTML format. The JSP returns HTML tags as response. We can modify the type of the lastResult object returned by the HTTPService object by modifying the resultFormat property of the HTTPService component.

In this example we will pass a parameter to the JSP and convert the response from the JSP to Object of the type XML by setting the resultFormat property of the HTTPService object to e4x and then extract the content from the <Body> element.

Create a JSP page

This JSP page takes the name as a parameter and responds a message with the input parameter.

First.jsp

<html>

<head><title>First Page</title></head>

<body>

<%

out.println(”Hi ” + request.getParameter(”name”));

%>

This is from the JSP.

</body>

</html>

Create Flex application

This application sends an HTTP service request to the JSP page. Once the JSP page responds, the response is converted into Object of the type XML by setting the resultFormat property of the HTTPService component to e4x. We parse the result object and retrieve the content in the <BODY> tag and display it. You can also observe that we are passing a parameter to the JSP in the send() method of the HTTPService component.

RPS.mxml

<?xml version=”1.0″ encoding=”utf-8″?>

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”vertical”>

<mx:Script>

<![CDATA[

import mx.rpc.events.ResultEvent;

import mx.controls.Alert;

private function handleHttpService(event:ResultEvent):void

{

Alert.show(event.result.toString(), "Complete Response");

Alert.show(event.result.body.toString(), "Content in Body element");

}

]]>

</mx:Script>

<mx:HTTPService id=”httpObj” url=”http://localhost:8400/sujit/first.jsp”

resultFormat=”e4x”

showBusyCursor=”true”

result=”handleHttpService(event)”

/>

<mx:Button id=”httpService” label=”Http Service” click=”httpObj.send({name: ‘Sujit’});” />

</mx:Application>

Snapshot of the application displaying the extracted content from server response

HTMLResponseExtracted