of 82 /82
Flex for Java developers: Flex for Java developers: My quest for pain-free UI development development Chris Richardson Author of POJOs in Action www.chrisrichardson.net [email protected] @crichardson Cinco de Mayo 2009

Flex For Java Developers - SDForum Java SIG

Embed Size (px)

DESCRIPTION

One day Chris Richardson, in need of a rich UI and deeply frustrated with Javascript and CSS, sat on his couch and downloaded FlexBuilder. This is what he found out.

Text of Flex For Java Developers - SDForum Java SIG

  • 1. Flex for Java developers: My quest for pain-free UIdevelopment Chris RichardsonAuthor of POJOs in Action [email protected]@crichardson Cinco de Mayo 2009

2. About Chris Grew up in England and live in Oakland Over 20+ years of software development experience including 12 years of Java Started Java architecture consulting company and sold it to BEA Speaker at JavaOne, SpringOne, etc. Java Champion Run a consulting and training company that helps organizations reduceg development costs and i dld increase effectivenesscloudtools.orgwww.cloudfoundry.com Slide 2 Copyright (c) 2009 Chris Richardson. All rights reserved. 3. AgendagThe joy and pain of UIdevelopmentOverview of FlexDeveloping Flex ApplicationsPushing data to the client gBuilding and testing Flex applications Slide 3 Copyright (c) 2009 Chris Richardson. All rights reserved. 4. Arms race: Frameworks vs. UI complexity p y 1998 1998- 2000 2000-20022002- 20052005- 20072008 19992002 20052006 Really Really MoreMore Moresimply SimpleComplex Complex complex Rich UIspagesPagesPages Pages pagesHome SpringSpringgrown MVCStrutsStrutsSpring MVC/Webframe1.0 1.0 MVC WebFlow FlowworkDojo / Slide 4 Copyright (c) 2009 Chris Richardson. All rights reserved. 5. Cloud Foundry y Slide 5 6. Cloud Foundry UI ySingle page applicationDojo toolkitUses DWR to push events to browserpEnd result is quite niceBut getting there was painfulSlide 6Copyright (c) 2009 Chris Richardson. All rights reserved. 7. Why is building RIAs so painful? y g pOpen-source JavaScript projectsVariable quality q ySome are poorly documentedBuilt on a shaky foundation of web technologiesJavaScriptpDynamic limited IDE supportPrototype-based simulated classesNo packages build your ownCSS layoutDifficult to learnRelies on hacks to accomplish basic layout tasksLack of portability across browsersEasier to use tables?Numerous bNbrowser incompatibilities itibilitiSlide 7 Copyright (c) 2009 Chris Richardson. All rights reserved. 8. Today's web = multi-layer hack y yWas a straightforward Hacks toenable offline hypertext browsing system applicationsNow an applicationdelivery platformFake classsystem Time for a Javascript changeHypertext Slide 8Copyright (c) 2009 Chris Richardson. All rights reserved. 9. GWT is an optionpTreats JavaScript as the runtimeenvironmentDevelop and debug in Javaquot;Swing-stylequot; programming modelBut my social network liked Flex Slide 9 Copyright (c) 2009 Chris Richardson. All rights reserved. 10. So I downloaded Flex Builderand wrote some Flex coded l d Slide 10 Copyright (c) 2009 Chris Richardson. All rights reserved. 11. AgendagThe joy and pain of UI developmentOverview of FlexDeveloping Flex Applications pg ppPushing data to the clientBuilding and testing Flex applications Slide 11 Copyright (c) 2009 Chris Richardson. All rights reserved. 12. What is Flex?Open-source framework for buildingRich Internet ApplicationsCurrent version is Flex 3 (Flex 4 in 4Q09)Flex apps run on the ubiquitous Flashpp qplayerIn the browserOn the desktop with Adobe AIRExcellent documentationDevelop applications inMXML declaratively define UIActionScript 3 handle events, invokebackend services, dynamically construct UI ,y ySlide 12 Copyright (c) 2009 Chris Richardson. All rights reserved. 13. ActionScript 3 the scripting language for the Flash p ygg player Class-based, object-oriented language Compile-time type checking Packages Dynamic vs. sealed classes Dynamic add properties/methods at runtimeti Method closures High Hi h performance AVM2 with JITfith compiler Dialect Di le t of ECMAS ipt (like JECMAScriptJavaScript)S ipt) Slide 13 Copyright (c) 2009 Chris Richardson. All rights reserved. 14. ActionScript XML support (ppp(E4X) )var x : XML = {title} var albums : XML = id1 {creationDate.time} t1 /xyz{notes}id2t2abc var title : String = x.title; var notes : String = x.notes;..var notes : XMLList = albums.album.notes var albums2: XMLList = ablums.album.(title = t1)Slide 14 Copyright (c) 2009 Chris Richardson. All rights reserved. 15. Comprehensive component libraryp pyComponentshave properties and methodsgenerate eventsVisual componentsControls: Button, TextField, Container: TabContainer, Form, Box, Can be styled with CSSNon-VisualData access components, e.g. HTTP, WebServicesValidatorsFormattersSlide 15 Copyright (c) 2009 Chris Richardson. All rights reserved. 16. Declaratively define UI in MXML y label= Symbol fontWeight= bold > / /l Equivalent to creatingcomponent tree inActionScriptSlide 16 Copyright (c) 2009 Chris Richardson. All rights reserved. 17. Events Components generate events Handled by ActionScript code < B tt label=quot;Get Quotequot; li k quot;h dl Cli k( t)quot;/>private function handleClick(event :Event) : void {} Slide 17 Copyright (c) 2009 Chris Richardson. All rights reserved. 18. Data Bindingg Control is updated whenever variablechanges [Bindable] private var quotes : Array = []; dataProvider= {quotes} width= 100% > Slide 18 Copyright (c) 2009 Chris Richardson. All rights reserved. 19. Custom components p Define AlbumThumbnail.mxml Use to modularizedl iapplication 3rd partydcomponents Slide 19Copyright (c) 2009 Chris Richardson. All rights reserved. 20. Flex security sandbox yUses the Flash Player security modelBy default, a Flex application can onlyaccess resources on the site that itwas downloaded fromCross-domain policy files on remoteserver grants access to Flexapplications from other domains Slide 20 Copyright (c) 2009 Chris Richardson. All rights reserved. 21. Flex Tools from AdobeFlex SDKFree, open-sourceFCompilers and command-line debuggerFlexBuilder Cheap ($249) Eclipse-based IDEFor Mac and WindowsMXML and ActionScript editors completion, renaming and validationDrag and drop UI builderGood debugging: breakpoints,Comprehensive h lChihelp Slide 21 Copyright (c) 2009 Chris Richardson. All rights reserved. 22. Flex Stock Quote DemoQSlide 22Copyright (c) 2009 Chris Richardson. All rights reserved. 23. Flex back-end integration gBlazeDSOpen-source projectO jAllows Flex clients to talk to server-sideJava applicationsRPCServer-push over HTTP pLiveCycle Data Services ESCommercialSuperset of BlazeDSMore scalableClient/Server d t synchronizationCli t/S datah i ti Slide 23 Copyright (c) 2009 Chris Richardson. All rights reserved. 24. Flex Application Architecture ppBlazeDS SOFEA = Service-Oriented Front-End Architecture Service Oriented Front EndSlide 24 Copyright (c) 2009 Chris Richardson. All rights reserved. 25. AgendagThe joy and pain of UI developmentOverview of FlexBuilding Flex ApplicationsThe Cairngorm frameworkCloud Photos Example ApplicationScenario: displaying albumsS i di l ilbScenario: creating a new albumScenario: copying photos between albumsPushing data to the clientBuilding and testing Flex applicationsSlide 25Copyright (c) 2009 Chris Richardson. All rights reserved. 26. Tangled codeg Slide 26 Copyright (c) 2009 Chris Richardson. All rights reserved. 27. Cairngorm frameworkgMVC framework for FlexModel dataView Flex components that display themodel (through binding)Controller implements quot;business logicquot; logicquot;,i.e. accessing backend services and updatethe modelEncourages:Separation of concernsSeparation of development roles: front-endand b kd back-enddAvoids big ball of mudAn alternative is PureMVCSlide 27Copyright (c) 2009 Chris Richardson. All rights reserved. 28. Cairngorm classes and rolesgViewsDisplay the model The code has a cookie-ModelLocatorcutter feel to it but IProvides access to the modellike the structureBusiness EventsGenerated by ViewsFront ControllerRoutes events to CommandsCommandsHandle eventsContain quot;business logicquot;/data access logicg/ gInvoke delegatesDelegatesProxy for remote servicesContract between front-end and back-end teamCalls b k tC ll back to command dServiceLocatorCentralized registry of (supposedly) all data access componentsUsed by delegatesSlide 28Copyright (c) 2009 Chris Richardson. All rights reserved. 29. Cairngorm flowgSlide 29Copyright (c) 2009 Chris Richardson. All rights reserved. 30. AgendagThe joy and pain of UI developmentOverview of FlexBuilding Flex ApplicationsThe Cairngorm frameworkCloud Photos Example ApplicationScenario: displaying albumsS i di l ilbScenario: creating a new albumScenario: copying photos between albumsPushing data to the clientBuilding and testing Flex applicationsSlide 30Copyright (c) 2009 Chris Richardson. All rights reserved. 31. Cloud Photos Application ppTomcatRESTful web servicesFlex Client Scala/Spring MVC/p gEvents Java/Spring/JMSManage your photos online Upload and p view photos Simple DBOrganizeS3 photos into Amazon Web Services albums Slide 31 Copyright (c) 2009 Chris Richardson. All rights reserved. 32. Cloud Photos screenshots Slide 32 Copyright (c) 2009 Chris Richardson. All rights reserved. 33. Cloud Photo web services http://localhost:8080/webapp/api/album e778769a-8432-46ca-b0f1-5c92f33a8710Pictures of kidshttps://s3.amazonaws.com//1ff7528a-65aa-4300-a5bb-c5b7e6eba985Some birdshttps://s3.amazonaws.com p /// .. Slide 33Copyright (c) 2009 Chris Richardson. All rights reserved. 34. Application structureppSlide 34Copyright (c) 2009 Chris Richardson. All rights reserved. 35. Model a Singletong package net.chrisrichardson.cloudphotos.ui.model { import com.adobe.cairngorm.model.IModelLocator; Metadata tag enables binding for all public properties [Bindable] public class CloudPhotosModelLocator implements IModelLocator {private static var modelLocator:CloudPhotosModelLocator;public var viewState : String = quot;displayAlbumsquot;;public var albums : XMLList; public var currentAlbum : XML blitAlb XML; public static function getInstance():CloudPhotosModelLocator{ if (modelLocator == null) { Singleton modelLocator = new CloudPhotosModelLocator();(); } return modelLocator; }}}Slide 35Copyright (c) 2009 Chris Richardson. All rights reserved. 36. View - Main applicationpp idth quot;100%quot; h i ht quot;100%quot; bus ess Se ces d se ces / width quot;100%quot; height quot;100%quot;>Slide 36 Copyright (c) 2009 Chris Richardson. All rights reserved. 37. View - HomePageg id= tabNavigator > CloudPhotosModelLocator.getInstance().viewState determines whether we are viewing albums or an albumSlide 37 Copyright (c) 2009 Chris Richardson. All rights reserved. 38. AgendagThe joy and pain of UI developmentOverview of FlexBuilding Flex ApplicationsThe Cairngorm frameworkCloud Photos Example ApplicationScenario: di l iSi displaying albumslbScenario: creating a new albumScenario: copying photos between albumsPushing data to the clientBuilding and testing Flex applicationsSlide 38Copyright (c) 2009 Chris Richardson. All rights reserved. 39. Display Albums Flowpy Slide 39 Copyright (c) 2009 Chris Richardson. All rights reserved. 40. View dispatches event p id quot;{Cl dPh t M d lL t tI t () lb}quot; Slide 40 Copyright (c) 2009 Chris Richardson. All rights reserved. 41. Controller executes command package net.chrisrichardson.cloudphotos.ui.control { import com.adobe.cairngorm.control.FrontController;import net.chrisrichardson.cloudphotos.ui.command.*; import net.chrisrichardson.cloudphotos.ui.event.*;public class Controller extends FrontController { public function Controller() { initializeCommands(); }public function initializeCommands() : void { addCommand( CreateAlbumEvent.CREATE_ALBUM, CreateAlbumCommand); addCommand( DisplayAlbumsEvent.DISPLAY_ALBUMS, DisplayAlbumsCommand); addCommand( DisplayAlbumEvent.DISPLAY_ALBUM, DisplayAlbumCommand); addCommand( CopyPhotoToAlbumEvent.COPY_PHOTO, CopyPhotoToAlbumCommand);} }}Slide 41Copyright (c) 2009 Chris Richardson. All rights reserved. 42. Command calls delegate g public class DisplayAlbumsCommand implements ICommand, IResponder {public function execute( event:CairngormEvent ):void {var delegate : DisplayAlbumsDelegate = new DisplayAlbumsDelegate(this);delegate.displayAlbums(); }public function result( event : Object ):void { var albums : XMLList = event.result.album; var model : Cl dPh t M d lLd l CloudPhotosModelLocator = Cl dPh t M d lLtCloudPhotosModelLocator.getInstance(); t tI t () model.albums = albums }p public function fault( event : Object ) : void {( j// handle error } } Slide 42 Copyright (c) 2009 Chris Richardson. All rights reserved. 43. Delegate invokes service g public class DisplayAlbumsDelegate { private var responder : IResponder; private var service : HTTPService;public function DisplayAlbumsDelegate( responder : IResponder ) { this.service = ServiceLocator.getInstance().getHTTPService( quot;displayAlbumsquot; );displayAlbums this.responder = responder; }public function displayAlbums() : void {var call : Obj t = service.send() ll Object id()call.addResponder(responder); } } Slide 43 Copyright (c) 2009 Chris Richardson. All rights reserved. 44. Service definition xmlns:cairngorm=quot;http://www adobe com/2006/cairngormquot;> / Slide 44Copyright (c) 2009 Chris Richardson. All rights reserved. 45. Command updates model p public class DisplayAlbumsCommand implements ICommand, IResponder {public function execute( event:CairngormEvent ):void {var delegate : DisplayAlbumsDelegate = new DisplayAlbumsDelegate(this);delegate.displayAlbums();}public function result( event : Object ):void {var albums : XMLList = event.result.album;var model : Cl dPh t M d lLd l CloudPhotosModelLocator = Cl dPh t M d lLt CloudPhotosModelLocator.getInstance();t tI t ()model.albums = albums }p public function fault( event : Object ) : void {( j// handle error } } Slide 45 Copyright (c) 2009 Chris Richardson. All rights reserved. 46. View displays model py id quot;{Cl dPh t M d lL t tI t () lb}quot;>Slide 46Copyright (c) 2009 Chris Richardson. All rights reserved. 47. View component pe778769a-8432-46ca-b0f1-5c92f33a8710 /S itwidth= 100 height=quot;25quot; text=quot;{album title}quot;/> Slide 47 Copyright (c) 2009 Chris Richardson. All rights reserved. 48. AgendagThe joy and pain of UI developmentOverview of FlexBuilding Flex ApplicationsThe Cairngorm frameworkCloud Photos Example ApplicationScenario: displaying albumsS i di l ilbScenario: creating a new albumScenario: copying photos between albumsPushing data to the clientBuilding and testing Flex applicationsSlide 48Copyright (c) 2009 Chris Richardson. All rights reserved. 49. Points of interest Uses a popup window Uploads files Command publishes a Cairngormpg event to notify view that upload is completeSlide 49Copyright (c) 2009 Chris Richardson. All rights reserved. 50. Displaying a popup windowp y g ppp id quot;{Cl dPh t M d lL t tI t () lb}quot;Slide 50Copyright (c) 2009 Chris Richardson. All rights reserved. 51. CreateAlbum popup window ppp Ti l quot; hquot; bl Di bl CB()quot;/ provides / an easy way to layout the form fields id= createButton label= Create Albumquot; click=quot;createAlbum(event)quot; enabled=quot;falsequot;/> Slide 51 Copyright (c) 2009 Chris Richardson. All rights reserved. 52. Selecting files to upload g pprivate var myFileReference:FileReferenceList = new FileReferenceList();[Bindable]private var photosToUpload : Array; private function selectFiles():void { myFileReference.addEventListener(quot;selectquot;, selectHandler); myFileReference.browse();} private function selectHandler(event:Event):void {photosToUpload = myFileReference.fileList.slice();enableDisableCreateButton();} private function enableDisableCreateButton() : void {createButton.enabled = titl V lid tt B tt bl d titleValidator.validate().type ! quot;invalidquot; lid t () t!= quot;ilidquot; && dateValidator.validate().type != quot;invalidquot; && filesSupplied()} pprivate function filesSupplied() : Boolean {pp()return photosToUpload != null && photosToUpload.length > 0} Slide 52Copyright (c) 2009 Chris Richardson. All rights reserved. 53. Displaying progress and dispatching Cairngorm eventpgg / pSlide 56Copyright (c) 2009 Chris Richardson. All rights reserved. 57. AgendagThe joy and pain of UI developmentOverview of FlexO i f FlBuilding Flex ApplicationsThe Cairngorm frameworkCloud Photos Example ApplicationScenario: displaying albums pygScenario: creating a new albumScenario: copying photos betweenalbumsPushing data to the clientBuilding and testing Flex applications Slide 57Copyright (c) 2009 Chris Richardson. All rights reserved. 58. Points of interest Uses drag and drop to copy a photo to an album Slide 58 Copyright (c) 2009 Chris Richardson. All rights reserved. 59. Initiating a draggg Slide 59 Copyright (c) 2009 Chris Richardson. All rights reserved. 60. Handling a dropgp Slide 60 Copyright (c) 2009 Chris Richardson. All rights reserved. 61. AgendagThe joy and pain of UI developmentOverview of FlexDeveloping Flex Applications pg ppPushing data to the clientBuilding and testing Flex applications Slide 61 Copyright (c) 2009 Chris Richardson. All rights reserved. 62. Why events? yCloud Photos server asynchronouslyuploads photos to S3Client might display photo before it isavailable Notify client when a photo is availableClient can reload the imageSlide 62 Copyright (c) 2009 Chris Richardson. All rights reserved. 63. BlazeDSOpen-source projectConnects Flex and AIR clients to Javabackend servicesClient-side Flex componentsServer-side components, E.g. ServletRPC servicesProxying for remote (web) servicesInvoke server-side Java objectPublish-Subscribe messagingSupports integration with JMSSpring BlazeDS project for simplifieddevelopment Slide 63Copyright (c) 2009 Chris Richardson. All rights reserved. 64. BlazeDS messaging componentsggp ClientServerreceivesmessages from JMS Queue/Consumer Destination AdapterTopic usingChannelEndpoint corresponds to http://localhost:8080/webapp/messagebroker/amfpolling Slide 64 Copyright (c) 2009 Chris Richardson. All rights reserved. 65. Channel/Endpoint options/ ppHTTP Options:Simple polling with piggybackLong polling message/connectionStreaming many messages/connectionFormats:AMF efficient binary formatAMFX XML formatSlide 65Copyright (c) 2009 Chris Richardson. All rights reserved. 66. Example client-side consumer p to S3. Client subscribes and reloads Slide 66Copyright (c) 2009 Chris Richardson. All rights reserved. 67. Spring beans for messagingpg gg public class SpringProducer {private JmsTemplate template;private Destination destination;public void send(String message) { template.convertAndSend(destination, message); }}Slide 67Copyright (c) 2009 Chris Richardson. All rights reserved. 68. BlazeDS MessageBrokerServletg MessageBrokerServletflex.messaging.MessageBrokerServletl l fl i kS l/ ll services.configuration.file/WEB-INF/flex/services-config.xml /i i 1lt iMessageBrokerServlet/messagebroker/*Slide 68Copyright (c) 2009 Chris Richardson. All rights reserved. 69. services-config.xml gShared by client and serverMessaging ServiceOne or more adaptersOne or more destinationsOne or more channelsDestinationsReferenced by clientSource/sink of messages gHas an adapter, e.g. JMSAdapterChannelsUsed by a Flex component to communicate with theBlazeDS serverBl DSCommunicate with server-side endpointsEndpointsURLs thatURL th t are mapped t Md to MessageBroker servletBk ltSlide 69 Copyright (c) 2009 Chris Richardson. All rights reserved. 70. Channels and endpoints p l quot;fli di AMFE d i quot;/ true4/ti /i fiSlide 70Copyright (c) 2009 Chris Richardson. All rights reserved. 71. Messaging servicegg ref my polling amfjtopicjndiname /p p Slide 71 Copyright (c) 2009 Chris Richardson. All rights reserved. 72. AgendagThe joy and pain of UI developmentOverview of FlexDeveloping Flex ApplicationspgppPushing data to the clientBuilding and testing FlexapplicationsSlide 72Copyright (c) 2009 Chris Richardson. All rights reserved. 73. Using Flex Mojos gjOpen source projectMaven Mojos for building and testingflex applicationshttp://code.google.com/p/flex-mojos/Badly documented but they work yySlide 73Copyright (c) 2009 Chris Richardson. All rights reserved. 74. Building a Flex client p jg project l iR i pia-repositoryhttp://repository.sonatype.org/content/groups/flexgroup/cairngorm mvn install builds SWFcairngorm2_2_1swc/p y srcinfo.flex mojosinfo.flex-mojosflex-compiler-mojo . Slide 74 Copyright (c) 2009 Chris Richardson. All rights reserved. 75. Adding the SWF to ygyour WAR war ddi net.chrisrichardsonkickstart-webappInput = SWF + Existing WAR file1.0-SNAPSHOTwarOutput = new WAR file containing SWF net.chrisrichardsonphotoflexui1.0-SNAPSHOTswfyp/ yp org.sonatype.flexmojosflexmojos-maven-plugincopy-flex-resources Slide 75 Copyright (c) 2009 Chris Richardson. All rights reserved. 76. Automated testing g$$: HP QTP, RIATestFlexUnitFocused on unit testsRecord UI tests with FlexMonkeyEncountered a licensing error duringcompilation!FluintSupposedly better than FlexUnitNot supported by Flex MojosSlide 76Copyright (c) 2009 Chris Richardson. All rights reserved. 77. Selenium-FlexLooks the most familiar/promisingselenium.flexClick()selenium flexClick()selenium.flexWaitForElement()Selenium extensions invoke ActionScriptfunctions via External interfaceInclude SeleniumFlexAPI.swc in yourapplicationExternal interface seems not to work in IE6Tricky to get working in FireFox yg gLaunching SeleniumServer via Java API didntwork extensions not loadedmaven-selenium-plugin workedpgSlide 77 Copyright (c) 2009 Chris Richardson. All rights reserved. 78. Example Selenium-Flex test p public class WebIntegrationTest extends TestCase {@Override protected void setUp() throws Exception { selenium = new DefaultSeleniumFlex(quot;localhostquot;, 4444, browserType,quot;http://localhost:8080quot;); selenium.start(); } public void test() throws Exception {selenium.open(quot;http://localhost:8080/webapp/photoflexui.htmlquot;);waitForFlexApplicationToLoad(quot;createAlbumButtonquot;);selenium.flexWaitForElement(quot;albumThumbnail[1]quot;); selenium.flexClick(quot;albumThumbnail[1]quot;);selenium.flexWaitForElementVisible(quot;backToAlbumsButtonquot;); selenium.flexClick( backToAlbumsButtons ); selenium flexClick(quot;backToAlbumsButtonsquot;);selenium.flexWaitForElementVisible(quot;createAlbumButtonquot;); selenium.flexClick(quot;createAlbumButtonquot;); }}Slide 78 Copyright (c) 2009 Chris Richardson. All rights reserved. 79. My next stepsy pWrite some automated testsInvestigate Spring ActionScriptDependency injection frameworkPromotes loose couplingInject stubs for servicesInvestigate ExternalInterfaceActionScriptJavaScriptSlide 79Copyright (c) 2009 Chris Richardson. All rights reserved. 80. SummaryFlex HTML/Javascript/CSS pBetter paradigm (Open-source) testingtools are moreEasier to developmatureSlide 80Copyright (c) 2009 Chris Richardson. All rights reserved. 81. Final thoughts g Download or contribute to Cloud Tools today : ywww.cloudtools.org Checkout Cloud Foundry:www.cloudfoundry.comwww cloudfoundry com Buy my book Send email:[email protected] Visit my website:www.chrisrichardson.net Talk to me about consulting and trainingPhone: 510 904 9832 Slide 81 Copyright (c) 2009 Chris Richardson. All rights reserved. 82. Resourceshttp://www.actionscript.org/http://www.adobe.com/devnet/actionscript/articles/actionscript3_overview.htmlhttp://www.adobe.com/devnet/flex/http://www.adobe.com/devnet/flash/http://www.infoq.com/articles/java-flex-blazedsIntro link:http://www.adobe.com/devnet/flex/articles/introducing_cairngorm.htmlhttp://dispatchevent.org/roger/as3-e4x-rundown//http://myflex.org/presentations/ComparingFlexFrameworks.pdfhttp://code.google.com/p/flexlib/ p // gg /p//Slide 82 Copyright (c) 2009 Chris Richardson. All rights reserved.