0
Flex for Java developers:
My quest for pain-free UI
       development
        Chris Richardson
   Author of POJOs in Acti...
About Chris
                                    Grew up in England and live in Oakland
                          •
       ...
Agenda
 g
 The joy and pain of UI
 development
 Overview of Flex
 Developing Flex Applications
 Pushing data to the client...
Arms race: Frameworks vs. UI complexity
                                p     y


1998
1998-     2000
          2000-     ...
Cloud Foundry
            y




    Slide 5
Cloud Foundry UI
            y
 Single page application
 Dojo toolkit
 Uses DWR to push events to browser
               p...
Why is building RIAs so painful?
  y           g         p
 Open-source JavaScript projects
   Variable quality
          ...
Today's web = multi-layer hack
    y                 y
 Was – a straightforward                                           ...
GWT is an option
           p
 Treats JavaScript as the runtime
 environment
 Develop and debug in Java
 quot;Swing-styleq...
So I downloaded Flex Builder




     and wrote some Flex code…
       d             l     d
                             ...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Developing Flex Applications
        pg         pp
 Pushi...
What is Flex?
 Open-source framework for building
 Rich Internet Applications
 Current version is Flex 3 (Flex 4 in 4Q09)
...
ActionScript 3 – the scripting
language for the Flash p y
   gg                   player
  Class-based, object-oriented la...
ActionScript XML support (
             p        pp    (E4X)
                                )

var x : XML = <createAlbum...
Comprehensive component library
   p             p            y
 Components
   have properties and methods
   generate eve...
Declaratively define UI in MXML
              y
<mx:Application >
  <mx:Form>
   <mx:FormItem label=quot;Symbolquot; fontW...
Events
      Components generate events
      Handled by ActionScript code
<mx:Button l b l quot;G t Q t quot; click=quot;...
Data Binding
           g

 Control is updated whenever variable
 changes
                [Bindable]
                priva...
Custom components
          p

                                                                                       Defi...
Flex security sandbox
            y
 Uses the Flash Player security model
 By default, a Flex application can only
 access...
Flex Tools from Adobe
 Flex SDK
   Free, open-source
   F
   Compilers and command-line debugger
 FlexBuilder –
   Cheap (...
Flex Stock Quote Demo
           Q




                                                                     Slide 22
     ...
Flex back-end integration
                  g
 BlazeDS
   Open-source project
   O                 j
   Allows Flex client...
Flex Application Architecture
      pp



                                                                  Blaze
        ...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Building Flex Applications
   The Cairngorm framework
   ...
Tangled code
   g
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Application xmlns:mx=quot;http://www.adobe.co...
Cairngorm framework
     g
 MVC framework for Flex
   Model – data
   View – Flex components that display the
   model (th...
Cairngorm classes and roles
     g
 Views
     Display the model                                                       The...
Cairngorm flow
     g




                                                                     Slide 29
         Copyright...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Building Flex Applications
   The Cairngorm framework
   ...
Cloud Photos Application
              pp
                                                         Tomcat
               R...
Cloud Photos – screenshots




                                                                      Slide 32
          Co...
Cloud Photo – web services
        http://localhost:8080/webapp/api/album




<albums>
 <album>
  <id>e778769a-8432-46ca-b...
Application structure
 pp




                                                                       Slide 34
           C...
Model – a Singleton
             g
package net.chrisrichardson.cloudphotos.ui.model {
  import com.adobe.cairngorm.model.I...
View - Main application
             pp
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Application layout=quot...
View - HomePage
             g
<mx:Vbox …>

 <mx:Binding destination=quot;currentStatequot;
             destination curre...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Building Flex Applications
   The Cairngorm framework
   ...
Display Albums Flow
   py




                                                                      Slide 39
          Cop...
View dispatches event
        p
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Vbox … creationComplete=quot;di...
Controller executes command
package net.chrisrichardson.cloudphotos.ui.control
{
  import com.adobe.cairngorm.control.Fron...
Command calls delegate
                  g
public class DisplayAlbumsCommand implements ICommand, IResponder
{

public fun...
Delegate invokes service
    g
public class DisplayAlbumsDelegate
{
  private var responder : IResponder;
  private var se...
Service definition
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>

<cairngorm:ServiceLocator
 xmlns:mx=quot;http:/...
Command updates model
              p
public class DisplayAlbumsCommand implements ICommand, IResponder
{

public function...
View displays model
        py
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Vbox … creationComplete=quot;dis...
View component
        p
                                   <album>
<mx:GridItem >
                                     <i...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Building Flex Applications
   The Cairngorm framework
   ...
Points of interest
  Uses a popup window
  Uploads files
  Command publishes a Cairngorm
             p                g
 ...
Displaying a popup window
   p y g ppp
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Vbox … creationComplete=...
CreateAlbum popup window
            ppp
<mx:TitleWindow>
<mx:Form width=quot;100%quot;>
  <mx:FormItem label=quot;Album T...
Selecting files to upload
        g           p
 private var myFileReference:FileReferenceList = new FileReferenceList();
...
Displaying progress and
dispatching Cairngorm event
   p      g      g
<?xml version=quot;1.0quot; encoding=quot;utf-8quot...
Uploading a file
 p      g
public class CreateAlbumDelegate
 {
   var photo : FileReference;

    public function notePhot...
CreateAlbumCommand
package net.chrisrichardson.cloudphotos.ui.command {

public class CreateAlbumCommand implements IComma...
CreateAlbumPopup
             pp
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
                                  ...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 O     i     f Fl
 Building Flex Applications
   The Cairn...
Points of interest
  Uses drag and drop to copy a photo
  to an album




                                                ...
Initiating a drag
         g      g
<mx:VBox width=quot;100quot; height=quot;175quot;>
  <mx:Script>
                     ...
Handling a drop
       g      p
<mx:VBox width=quot;100quot; height=quot;175quot;>
  <mx:Script>
                         ...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Developing Flex Applications
        pg         pp
 Pushi...
Why events?
  y
 Cloud Photos server asynchronously
 uploads photos to S3
 Client might display photo before it is
 availa...
BlazeDS
 Open-source project
 Connects Flex and AIR clients to Java
 backend services
   Client-side Flex components
   Se...
BlazeDS messaging components
             gg      p


Client                                  Server


                   ...
Channel/Endpoint options
       /   p      p
 HTTP Options:
   Simple polling with piggyback
   Long polling – message/con...
Example client-side consumer
    p
<?xml version=quot;1.0quot; encoding=quot;utf-8quot;?>
<mx:Canvas creationComplete=quot...
Spring beans for messaging
     pg                   gg
<amq:topic id=quot;destinationquot;
 physicalName=quot;org.apache....
BlazeDS MessageBrokerServlet
             g
<servlet>
  <servlet-name>MessageBrokerServlet</servlet-name>
  <servlet-class...
services-config.xml
              g
 Shared by client and server
 Messaging Service
   One or more adapters
   One or more...
Channels and endpoints
                p
<services-config>

<channel-definition id quot;
  h      l d fi i i  id=quot;my-p...
Messaging service
     gg
<service id=quot;message-servicequot; class=quot;flex.messaging.services.MessageServicequot;>

 ...
Agenda
 g
 The joy and pain of UI development
 Overview of Flex
 Developing Flex Applications
       pg          pp
 Pushi...
Using Flex Mojos
    g        j
 Open source project
 Maven Mojos for building and testing
 flex applications
 http://code...
Building a Flex client p j
       g               project
<project>
…
<pluginRepositories>
     <pluginRepository>
       ...
Adding the SWF to y
     g            your WAR
<project>
<packaging>war</packaging>
…
<dependencies>
  d    d    i
  <depe...
Automated testing
                g
 $$: HP QTP, RIATest
 FlexUnit
   Focused on unit tests
   Record UI tests with FlexMo...
Selenium-Flex
 Looks the most familiar/promising
   selenium.flexClick()
   selenium flexClick()
   selenium.flexWaitForEl...
Example Selenium-Flex test
    p
public class WebIntegrationTest extends TestCase {

@Override
protected void setUp() thro...
My next steps
 y         p
 Write some automated tests
 Investigate Spring ActionScript
   Dependency injection framework
...
Summary

Flex                                             HTML/Javascript/CSS
                                            ...
Final thoughts
          g
                                        Download or contribute to Cloud
                       ...
Resources
 http://www.actionscript.org/
 http://www.adobe.com/devnet/actionscript/articl
 es/actionscript3_overview.html
 ...
Upcoming SlideShare
Loading in...5
×

Flex For Java Developers - SDForum Java SIG

5,841

Published on

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.

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,841
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
114
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "Flex For Java Developers - SDForum Java SIG"

  1. 1. Flex for Java developers: My quest for pain-free UI development Chris Richardson Author of POJOs in Action www.chrisrichardson.net chris@chrisrichardson.net @crichardson Cinco de Mayo 2009
  2. 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 reduce g development costs and i d l d increase effectiveness cloudtools.org www.cloudfoundry.com Slide 2 Copyright (c) 2009 Chris Richardson. All rights reserved.
  3. 3. Agenda g The joy and pain of UI development Overview of Flex Developing Flex Applications Pushing data to the client g Building and testing Flex applications Slide 3 Copyright (c) 2009 Chris Richardson. All rights reserved.
  4. 4. Arms race: Frameworks vs. UI complexity p y 1998 1998- 2000 2000- 2002 2002- 2005 2005- 2007 2008 1999 2002 2005 2006 Really Really More More More simply Simple Complex Complex complex Rich UIs pages Pages Pages Pages pages Home Spring Spring grown MVC Struts Struts Spring MVC/Web frame 1.0 1.0 MVC WebFlow Flow work Dojo /☺ ☺ Slide 4 Copyright (c) 2009 Chris Richardson. All rights reserved.
  5. 5. Cloud Foundry y Slide 5
  6. 6. Cloud Foundry UI y Single page application Dojo toolkit Uses DWR to push events to browser p End result is quite nice But getting there was painful Slide 6 Copyright (c) 2009 Chris Richardson. All rights reserved.
  7. 7. Why is building RIAs so painful? y g p Open-source JavaScript projects Variable quality q y Some are poorly documented Built on a shaky foundation of web technologies JavaScript p Dynamic ⇒ limited IDE support Prototype-based ⇒ simulated classes No packages ⇒ build your own … CSS layout Difficult to learn Relies on “hacks” to accomplish basic layout tasks Lack of portability across browsers Easier to use tables? Numerous b N browser incompatibilities i tibiliti Slide 7 Copyright (c) 2009 Chris Richardson. All rights reserved.
  8. 8. Today's web = multi-layer hack y y Was – a straightforward Hacks to enable offline hypertext browsing system applications Now – an application … delivery platform Fake class system ⇒Time for a Javascript change Hypertext Slide 8 Copyright (c) 2009 Chris Richardson. All rights reserved.
  9. 9. GWT is an option p Treats JavaScript as the runtime environment Develop and debug in Java quot;Swing-stylequot; programming model But my social network liked Flex … Slide 9 Copyright (c) 2009 Chris Richardson. All rights reserved.
  10. 10. So I downloaded Flex Builder and wrote some Flex code… d l d Slide 10 Copyright (c) 2009 Chris Richardson. All rights reserved.
  11. 11. Agenda g The joy and pain of UI development Overview of Flex Developing Flex Applications pg pp Pushing data to the client Building and testing Flex applications Slide 11 Copyright (c) 2009 Chris Richardson. All rights reserved.
  12. 12. What is Flex? Open-source framework for building Rich Internet Applications Current version is Flex 3 (Flex 4 in 4Q09) Flex apps run on the ubiquitous Flash pp q player In the browser On the desktop with Adobe AIR Excellent documentation Develop applications in MXML – declaratively define UI ActionScript 3 – handle events, invoke backend services, dynamically construct UI ,y y Slide 12 Copyright (c) 2009 Chris Richardson. All rights reserved.
  13. 13. ActionScript 3 – the scripting language for the Flash p y gg player Class-based, object-oriented language Compile-time type checking Packages Dynamic vs. sealed classes Dynamic – add properties/methods at runtime ti Method closures High Hi h performance AVM2 with JIT f ith compiler Dialect Di le t of ECMAS ipt (like J ECMAScript JavaScript) S ipt) Slide 13 Copyright (c) 2009 Chris Richardson. All rights reserved.
  14. 14. ActionScript XML support ( p pp (E4X) ) var x : XML = <createAlbumRequest> <title>{title}</title> var albums : XML = <albums> <album> <creationDate> <id>id1</id> {creationDate.time} <title>t1</title> / </creationDate> <thumbnail>xyz<thumbnail> <notes>{notes}</notes> </album> <album> </createAlbumRequest> <id>id2</id> <title>t2</title> <thumbnail>abc</thumbnail> var title : String = x.title; </album> var notes : String = x.notes; ….. </albums> var notes : XMLList = albums.album.notes var albums2: XMLList = ablums.album.(title = “t1”) Slide 14 Copyright (c) 2009 Chris Richardson. All rights reserved.
  15. 15. Comprehensive component library p p y Components have properties and methods generate events Visual components Controls: Button, TextField, … Container: TabContainer, Form, Box, … Can be styled with CSS Non-Visual Data access components, e.g. HTTP, Web Services Validators Formatters Slide 15 Copyright (c) 2009 Chris Richardson. All rights reserved.
  16. 16. Declaratively define UI in MXML y <mx:Application > <mx:Form> <mx:FormItem label=quot;Symbolquot; fontWeight=quot;boldquot;> label= Symbol fontWeight= bold > <mx:TextInput id=quot;symbolquot; text=quot;AAPLquot; fontWeight=quot;normalquot;/> </mx:FormItem> <mx:FormItem label=quot;quot;> <mx:Button label=quot;Get Quotequot; click=quot;handleClick(event)quot;/> </mx:FormItem> / </mx:Form> <mx:DataGrid dataProvider=quot;{quotes}quot; width=quot;100%quot;> <mx:columns> <mx:DataGridColumn headerText=quot;Symbolquot; dataField=quot;symbolquot;/> <mx:DataGridColumn headerText=quot;Pricequot; dataField=quot;pricequot;/> </mx:columns> / l </mx:DataGrid> </mx:Application> Equivalent to creating component tree in ActionScript Slide 16 Copyright (c) 2009 Chris Richardson. All rights reserved.
  17. 17. Events Components generate events Handled by ActionScript code <mx:Button l b l quot;G t Q t quot; click=quot;handleClick(event)quot;/> < 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. 18. Data Binding g Control is updated whenever variable changes [Bindable] private var quotes : Array = []; <mx:DataGrid dataProvider=quot;{quotes}quot; width=quot;100%quot;> dataProvider= {quotes} width= 100% > <mx:columns> <mx:DataGridColumn headerText=quot;Symbolquot; dataField=quot;symbolquot;/> <mx:DataGridColumn headerText=quot;Pricequot; dataField=quot;pricequot;/> </mx:columns> </mx:DataGrid> Slide 18 Copyright (c) 2009 Chris Richardson. All rights reserved.
  19. 19. Custom components p Define <mx:GridItem > AlbumThumbnail.mxml <mx:Script> subclasses in <![CDATA[ [Bindable] MXML or public var album : XML; p public function viewAlbum() : void { ….} () } ActionScript A ti S i t ]]> </mx:Script> Use to <mx:VBox width=quot;100quot; height=quot;125quot;> modularize dl i <mx:Image id quot;i I id=quot;imgquot; click=quot;viewAlbum()quot; quot; li k quot; i Alb ()quot; source=quot;{album.thumbnail}quot; /> </mx:Box> application <mx:Text width=quot;100quot; height=quot;25quot; text=quot;{album.title}quot;/> 3rd party d </mx:VBox> components </mx:GridItem> <components:AlbumThumbnail album=quot;{rp.currentItem}quot;/> Slide 19 Copyright (c) 2009 Chris Richardson. All rights reserved.
  20. 20. Flex security sandbox y Uses the Flash Player security model By default, a Flex application can only access resources on the site that it was downloaded from Cross-domain policy files on remote server grants access to Flex applications from other domains Slide 20 Copyright (c) 2009 Chris Richardson. All rights reserved.
  21. 21. Flex Tools from Adobe Flex SDK Free, open-source F Compilers and command-line debugger FlexBuilder – Cheap ($249) Eclipse-based IDE For Mac and Windows MXML and ActionScript editors – completion, renaming and validation Drag and drop UI builder Good debugging: breakpoints, Comprehensive h l C h i help Slide 21 Copyright (c) 2009 Chris Richardson. All rights reserved.
  22. 22. Flex Stock Quote Demo Q Slide 22 Copyright (c) 2009 Chris Richardson. All rights reserved.
  23. 23. Flex back-end integration g BlazeDS Open-source project O j Allows Flex clients to talk to server-side Java applications RPC Server-push over HTTP p LiveCycle Data Services ES Commercial Superset of BlazeDS More scalable Client/Server d t synchronization Cli t/S data h i ti Slide 23 Copyright (c) 2009 Chris Richardson. All rights reserved.
  24. 24. Flex Application Architecture pp Blaze DS SOFEA = Service-Oriented Front-End Architecture Service Oriented Front End Slide 24 Copyright (c) 2009 Chris Richardson. All rights reserved.
  25. 25. Agenda g The joy and pain of UI development Overview of Flex Building Flex Applications The Cairngorm framework Cloud Photos Example Application Scenario: displaying albums S i di l i lb Scenario: creating a new album Scenario: copying photos between albums Pushing data to the client Building and testing Flex applications Slide 25 Copyright (c) 2009 Chris Richardson. All rights reserved.
  26. 26. Tangled code g <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Application xmlns:mx=quot;http://www.adobe.com/2006/mxmlquot; layout=quot;absolutequot; implements=quot;mx.rpc.IResponderquot; backgroundColor=quot;#ffffffquot;> <mx:Script> Data [Bindable] private var quote : String; private function handleClick(event :Event) : void { var service : HTTPService = new HTTPService(); Data … Access } Logic public function result(data:Object):void { …. } p public function fault(info:Object):void { } ( j ) ]]> </mx:Script> <mx:VDividedBox width=quot;414quot; height=quot;217quot; Presentation logic …. </mx:VDividedBox> </mx:Application> Slide 26 Copyright (c) 2009 Chris Richardson. All rights reserved.
  27. 27. Cairngorm framework g MVC framework for Flex Model – data View – Flex components that display the model (through binding) Controller – implements quot;business logicquot; logicquot;, i.e. accessing backend services and update the model Encourages: Separation of concerns Separation of development roles: front-end and b k d back-endd Avoids big ball of mud An alternative is PureMVC Slide 27 Copyright (c) 2009 Chris Richardson. All rights reserved.
  28. 28. Cairngorm classes and roles g Views Display the model The code has a cookie- ModelLocator cutter feel to it but I Provides access to the model like the structure “Business” Events Generated by Views Front Controller Routes events to Commands Commands Handle events Contain quot;business logicquot;/data access logic g/ g Invoke delegates Delegates Proxy for remote services Contract between front-end and back-end team Calls b k t C ll back to command d ServiceLocator Centralized registry of (supposedly) all data access components Used by delegates Slide 28 Copyright (c) 2009 Chris Richardson. All rights reserved.
  29. 29. Cairngorm flow g Slide 29 Copyright (c) 2009 Chris Richardson. All rights reserved.
  30. 30. Agenda g The joy and pain of UI development Overview of Flex Building Flex Applications The Cairngorm framework Cloud Photos Example Application Scenario: displaying albums S i di l i lb Scenario: creating a new album Scenario: copying photos between albums Pushing data to the client Building and testing Flex applications Slide 30 Copyright (c) 2009 Chris Richardson. All rights reserved.
  31. 31. Cloud Photos Application pp Tomcat RESTful web services Flex Client Scala/Spring MVC /p g Events Java/Spring/JMS Manage your photos online Upload and p view photos Simple DB Organize S3 photos into Amazon Web Services albums … Slide 31 Copyright (c) 2009 Chris Richardson. All rights reserved.
  32. 32. Cloud Photos – screenshots Slide 32 Copyright (c) 2009 Chris Richardson. All rights reserved.
  33. 33. Cloud Photo – web services http://localhost:8080/webapp/api/album <albums> <album> <id>e778769a-8432-46ca-b0f1-5c92f33a8710</id> <title>Pictures of kids</title> <thumbnail>https://s3.amazonaws.com/…</thumbnail> </album> / <album> <id>1ff7528a-65aa-4300-a5bb-c5b7e6eba985</id> <title>Some birds</title> <thumbnail>https://s3.amazonaws.com…</thumbnail> p // / </album> ….. </albums> Slide 33 Copyright (c) 2009 Chris Richardson. All rights reserved.
  34. 34. Application structure pp Slide 34 Copyright (c) 2009 Chris Richardson. All rights reserved.
  35. 35. Model – a Singleton g 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 bli tAlb XML; public static function getInstance():CloudPhotosModelLocator{ if (modelLocator == null) { Singleton modelLocator = new CloudPhotosModelLocator();(); } return modelLocator; } } } Slide 35 Copyright (c) 2009 Chris Richardson. All rights reserved.
  36. 36. View - Main application pp <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Application layout=quot;verticalquot; layout vertical xmlns:ns1=quot;net.chrisrichardson.cloudphotos.ui.components.*quot; xmlns:control=quot;net.chrisrichardson.cloudphotos.ui.control.*quot; xmlns:business=quot;net.chrisrichardson.cloudphotos.ui.business.*quot; width=quot;100%quot; height=quot;100%quot;> idth quot;100%quot; h i ht quot;100%quot; <business:Services id=quot;servicesquot; /> bus ess Se ces d se ces / <control:Controller id=quot;controllerquot; /> <mx:Label text=quot;Cloud Photosquot; fontSize=quot;33quot;/> <ns1:HomePage width=quot;100%quot; height=quot;100%quot;> width quot;100%quot; height quot;100%quot;> </ns1:HomePage> </mx:Application> Slide 36 Copyright (c) 2009 Chris Richardson. All rights reserved.
  37. 37. View - HomePage g <mx:Vbox …> <mx:Binding destination=quot;currentStatequot; destination currentState source=quot;{CloudPhotosModelLocator.getInstance().viewState}quot;/> <mx:states> <mx:State name=quot;displayAlbumsquot;> <mx:SetProperty name=quot;selectedIndexquot; target=quot;{viewStack}quot; value=quot;{0}quot;/> </mx:State> <mx:State name=quot;displayAlbumquot;> <mx:SetProperty name=quot;selectedIndexquot; target=quot;{viewStack}quot; value=quot;{1}quot;/> </mx:State> </mx:states> <mx:TabNavigator id=quot;tabNavigatorquot; …> id= tabNavigator > <mx:ViewStack id=quot;viewStackquot; width=quot;100%quot; height=quot;100%quot; label=quot;My Albumsquot; > <components:AlbumList id=quot;albumListquot; width=quot;100%quot; height=quot;100%“/> <components:AlbumView id=quot;albumViewquot; width=quot;100%quot; height=quot;100%“/> </mx:ViewStack> … </mx:TabNavigator> CloudPhotosModelLocator.getInstance().viewState </mx:VBox> determines whether we are viewing albums or an album Slide 37 Copyright (c) 2009 Chris Richardson. All rights reserved.
  38. 38. Agenda g The joy and pain of UI development Overview of Flex Building Flex Applications The Cairngorm framework Cloud Photos Example Application Scenario: di l i S i displaying albums lb Scenario: creating a new album Scenario: copying photos between albums Pushing data to the client Building and testing Flex applications Slide 38 Copyright (c) 2009 Chris Richardson. All rights reserved.
  39. 39. Display Albums Flow py Slide 39 Copyright (c) 2009 Chris Richardson. All rights reserved.
  40. 40. View dispatches event p <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Vbox … creationComplete=quot;displayAlbums()quot;> <mx:Script> <![CDATA[ private function displayAlbums():void { var event : DisplayAlbumsEvent = new DisplayAlbumsEvent(); event.dispatch(); } private function createAlbum() : void { PopUpManager.centerPopUp(PopUpManager.createPopUp(this, CreateAlbumPopup, true)); } ]]> </mx:Script> <mx:HBox width=quot;100%quot; height=quot;10%quot;> <mx:Button label=quot;Create Newquot; click=quot;createAlbum()quot;/> </mx:HBox> <mx:Tile id=quot;albumGridquot; width=quot;100%quot; height=quot;90%quot;> <mx:Repeater id quot; quot; d t P R t id=quot;rpquot; dataProvider=quot;{CloudPhotosModelLocator.getInstance().albums}quot;> id quot;{Cl dPh t M d lL t tI t () lb }quot; <components:AlbumThumbnail album=quot;{rp.currentItem}quot;/> </mx:Repeater> </mx:Tile> </mx:VBox> Slide 40 Copyright (c) 2009 Chris Richardson. All rights reserved.
  41. 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 41 Copyright (c) 2009 Chris Richardson. All rights reserved.
  42. 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 lL d l CloudPhotosModelLocator = Cl dPh t M d lL t CloudPhotosModelLocator.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. 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 i d() call.addResponder(responder); } } Slide 43 Copyright (c) 2009 Chris Richardson. All rights reserved.
  44. 44. Service definition <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <cairngorm:ServiceLocator xmlns:mx=quot;http://www.adobe.com/2006/mxmlquot; xmlns:cairngorm http://www.adobe.com/2006/cairngorm > xmlns:cairngorm=quot;http://www adobe com/2006/cairngormquot;> <mx:HTTPService id=quot;displayAlbumsquot; url=quot;http://.../api/albumquot; resultFormat=quot;e4xquot; ltF t quot;4quot; useProxy=quot;falsequot; method=quot;GETquot; > </mx:HTTPService> / </cairngorm:ServiceLocator> Slide 44 Copyright (c) 2009 Chris Richardson. All rights reserved.
  45. 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 lL d l CloudPhotosModelLocator = Cl dPh t M d lL t CloudPhotosModelLocator.getInstance(); t tI t () model.albums = albums } p public function fault( event : Object ) : void { ( j <albums> // handle error <album>…</album> } <album>…</album> } … </albums> Slide 45 Copyright (c) 2009 Chris Richardson. All rights reserved.
  46. 46. View displays model py <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Vbox … creationComplete=quot;displayAlbums()quot;> <mx:Script> <![CDATA[ private function displayAlbums():void { var event : DisplayAlbumsEvent = new DisplayAlbumsEvent(); event.dispatch(); } private function createAlbum() : void { PopUpManager.centerPopUp(PopUpManager.createPopUp(this, CreateAlbumPopup, true)); } ]]> </mx:Script> <mx:HBox width=quot;100%quot; height=quot;10%quot;> <mx:Button label=quot;Create Newquot; click=quot;createAlbum()quot;/> </mx:HBox> <mx:Tile id=quot;albumGridquot; width=quot;100%quot; height=quot;90%quot;> <mx:Repeater id quot; quot; d t P < R t id=quot;rpquot; dataProvider=quot;{CloudPhotosModelLocator.getInstance().albums}quot;> id quot;{Cl dPh t M d lL t tI t () lb }quot;> <components:AlbumThumbnail album=quot;{rp.currentItem}quot;/> </mx:Repeater> </mx:Tile> </mx:VBox> Slide 46 Copyright (c) 2009 Chris Richardson. All rights reserved.
  47. 47. View component p <album> <mx:GridItem > <id>e778769a-8432-46ca-b0f1-5c92f33a8710</id> <mx:Script> <title>Pictures of kids</title> / <thumbnail>https://s3.amazonaws.com/…</thumbnail> <![CDATA[ </album> [Bindable] public var album : XML; p public function viewAlbum() : void { () new DisplayAlbumEvent(album.id).dispatch(); CloudPhotosModelLocator.getInstance().viewState = quot;displayAlbumquot;; } ]]> </mx:Script> / S it <mx:Box width=quot;100quot; height=quot;125quot;> <mx:Image id=quot;imgquot; click=quot;viewAlbum()quot; source=quot;{album.thumbnail}quot; /> </mx:Box> <mx:Text width=quot;100quot; height= 25 text= {album.title} /> width= 100 height=quot;25quot; text=quot;{album title}quot;/> </mx:VBox> </mx:GridItem> Slide 47 Copyright (c) 2009 Chris Richardson. All rights reserved.
  48. 48. Agenda g The joy and pain of UI development Overview of Flex Building Flex Applications The Cairngorm framework Cloud Photos Example Application Scenario: displaying albums S i di l i lb Scenario: creating a new album Scenario: copying photos between albums Pushing data to the client Building and testing Flex applications Slide 48 Copyright (c) 2009 Chris Richardson. All rights reserved.
  49. 49. Points of interest Uses a popup window Uploads files Command publishes a Cairngorm p g event to notify view that upload is complete Slide 49 Copyright (c) 2009 Chris Richardson. All rights reserved.
  50. 50. Displaying a popup window p y g ppp <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Vbox … creationComplete=quot;displayAlbums()quot;> <mx:Script> <![CDATA[ private function displayAlbums():void { var event : DisplayAlbumsEvent = new DisplayAlbumsEvent(); event.dispatch(); } private function createAlbum() : void { PopUpManager.centerPopUp(PopUpManager.createPopUp(this, CreateAlbumPopup, true)); } ]]> </mx:Script> <mx:HBox width=quot;100%quot; height=quot;10%quot;> <mx:Button label=quot;Create Newquot; click=quot;createAlbum()quot;/> </mx:HBox> <mx:Tile id=quot;albumGridquot; width=quot;100%quot; height=quot;90%quot;> <mx:Repeater id quot; quot; d t P R t id=quot;rpquot; dataProvider=quot;{CloudPhotosModelLocator.getInstance().albums}quot;> id quot;{Cl dPh t M d lL t tI t () lb }quot; <components:AlbumThumbnail album=quot;{rp.currentItem}quot;/> </mx:Repeater> </mx:Tile> </mx:VBox> Slide 50 Copyright (c) 2009 Chris Richardson. All rights reserved.
  51. 51. CreateAlbum popup window ppp <mx:TitleWindow> <mx:Form width=quot;100%quot;> <mx:FormItem label=quot;Album Titlequot;> <mx:TextInput id quot; lb T I id=quot;albumTitlequot; change=quot;enableDisableCreateButton()quot;/> Ti l quot; h quot; bl Di bl C B ()quot;/ </mx:FormItem> <mx:FormItem label=quot;Album Datequot;> <mx:DateChooser id=quot;datequot; change=quot;enableDisableCreateButton()quot;/> </mx:FormItem> <mx:FormItem label=quot;Notesquot;> <mx:TextArea id=quot;notesquot;/> </mx:FormItem> <mx:FormItem label=quot;quot;> <mx:Button label=quot;Select Images...quot; click=quot;selectFiles()quot;/> </mx:FormItem> <mx:FormItem label=quot;quot;> <Form> provides <mx:Label text=quot;{photosToUpload.length} imagesquot;/> </mx:FormItem> / an easy way to <mx:FormItem label=quot;Selected Filesquot; width=quot;100%quot;> layout the form <mx:DataGrid dataProvider=quot;{photosToUpload}quot; width=quot;100%quot;> <mx:columns> fields <mx:DataGridColumn headerText=quot;Namequot; dataField=quot;namequot;/> <mx:DataGridColumn headerText=quot;Datequot; dataField=quot;creationDatequot;/> </mx:columns> </mx:DataGrid> </mx:FormItem> </mx:Form> <mx:ControlBar> <mx:Button id=quot;createButtonquot; label=quot;Create Album click= createAlbum(event) enabled= false /> id= createButton label= Create Albumquot; click=quot;createAlbum(event)quot; enabled=quot;falsequot;/> <mx:Button label=quot;Cancelquot; click=quot;cancelCreateAlbum()quot;/> </mx:ControlBar> </mx:TitleWindow> Slide 51 Copyright (c) 2009 Chris Richardson. All rights reserved.
  52. 52. Selecting files to upload g p private 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 t t B tt bl d titleValidator.validate().type ! quot;invalidquot; lid t () t != quot;i lidquot; && dateValidator.validate().type != quot;invalidquot; && filesSupplied() } p private function filesSupplied() : Boolean { pp () return photosToUpload != null && photosToUpload.length > 0 } Slide 52 Copyright (c) 2009 Chris Richardson. All rights reserved.
  53. 53. Displaying progress and dispatching Cairngorm event p g g <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:TitleWindow> <mx:Script> <![CDATA[ private var uploadProgressWindow : PhotoUploadProgressWindow; private function createAlbum(event:Event) : void { uploadProgressWindow = PhotoUploadProgressWindow(PopUpManager.createPopUp(this, PhotoUploadProgressWindow, true)); PopUpManager.centerPopUp(uploadProgressWindow); var ev : C CreateAlbumEvent = new C t Alb E t CreateAlbumEvent() t Alb E t() ev.album = new Album(albumTitle.text, notes.text, date.selectedDate) ev.photosToUpload = photosToUpload ev.dispatch() } </mx:Script> </mx:TitleWindow> Slide 53 Copyright (c) 2009 Chris Richardson. All rights reserved.
  54. 54. Uploading a file p g public class CreateAlbumDelegate { var photo : FileReference; public function notePhotoAdded(photoId : String) : void { … photoIndex = photoIndex + 1; var ur : URLRequest = new URLRequest(); ur.url = Env.getRootUrl() + quot;api/album/quot; + album.id + quot;/photo/quot; + p photoId; ; this.photo.addEventListener(Event.COMPLETE, completeHandler); this.photo.upload(ur, quot;photoquot;); } public function completeHandler(event: Event) : void { … } } Slide 54 Copyright (c) 2009 Chris Richardson. All rights reserved.
  55. 55. CreateAlbumCommand package net.chrisrichardson.cloudphotos.ui.command { public class CreateAlbumCommand implements ICommand, IResponder { public function CreateAlbumCommand() {} public function execute( event:CairngormEvent ):void { var delegate : CreateAlbumDelegate = new CreateAlbumDelegate(this); var album : Album = (event as CreateAlbumEvent).album var photosToUpload : Array = (event as CreateAlbumEvent).photosToUpload delegate.createAlbum(album, photosToUpload); } Long running public function result( event : Object ):void { new AlbumCreatedEvent((event as Album).id).dispatch(); - publishes a } Cairngorm public function fault( event : Object ) : void { … } event when finished } Slide 55 Copyright (c) 2009 Chris Richardson. All rights reserved.
  56. 56. CreateAlbumPopup pp <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> View subscribes to <mx:TitleWindow creationComplete=quot;creationComplete()quot;> AlbumCreatedEvent – <mx:Script> easier than binding to <![CDATA[ model private function creationComplete() : void { CairngormEventDispatcher.getInstance() .addEventListener(quot;albumCreatedquot;, albumCreated); } public function albumCreated(event : CairngormEvent) : void { PopUpManager.removePopUp(uploadProgressWindow); CloudPhotosModelLocator.getInstance().viewState = quot;displayAlbumquot;; new DisplayAlbumsEvent().dispatch(); new DisplayAlbumEvent((event as AlbumCreatedEvent).albumId).dispatch(); PopUpManager.removePopUp(this); } } ]]> </mx:Script> / p </mx:TitleWindow> Slide 56 Copyright (c) 2009 Chris Richardson. All rights reserved.
  57. 57. Agenda g The joy and pain of UI development Overview of Flex O i f Fl Building Flex Applications The Cairngorm framework Cloud Photos Example Application Scenario: displaying albums pyg Scenario: creating a new album Scenario: copying photos between albums Pushing data to the client Building and testing Flex applications Slide 57 Copyright (c) 2009 Chris Richardson. All rights reserved.
  58. 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. 59. Initiating a drag g g <mx:VBox width=quot;100quot; height=quot;175quot;> <mx:Script> PhotoThumbnail.mxml <![CDATA[ [Bindable] var photo : XML; private function mouseMoveHandler(event:MouseEvent):void { var dragInitiator:Image=Image(event.currentTarget); var ds:DragSource = new DragSource(); ds.addData(photo.id, 'photoId'); DragManager.doDrag(dragInitiator, ds, event); } … ]]> </mx:Script> <mx:Image id=quot;imgquot; width=quot;100%quot; height=quot;100%quot; mouseMove=quot;mouseMoveHandler(event)quot; source=quot;{photo.thumbnail}quot;/> </mx:VBox> Slide 59 Copyright (c) 2009 Chris Richardson. All rights reserved.
  60. 60. Handling a drop g p <mx:VBox width=quot;100quot; height=quot;175quot;> <mx:Script> AlbumSummaryThumbnail.mxml y <![CDATA[ [Bindable] [Bi d bl ] public var album : XML ; private function dragEnterHandler(event:DragEvent):void { if (event.dragSource.hasFormat('photoId')) { var dropTarget:Image=Image(event.currentTarget); DragManager.acceptDragDrop(dropTarget); } } private function dragDropHandler(event:DragEvent):void { var photoId : Object = event.dragSource.dataForFormat('photoId'); p j g (p ); new CopyPhotoToAlbumEvent(album.id, String(photoId)).dispatch(); } ]]> </mx:Script> <mx:Box width=quot;100quot; height=quot;125quot; verticalScrollPolicy=quot;offquot; horizontalScrollPolicy=quot;offquot;> <mx:Image dragEnter=quot;dragEnterHandler(event);quot; dragDrop=quot;dragDropHandler(event);quot; source=quot;{album.thumbnail}quot;/> </mx:Box> <mx:Text id=quot;titlequot; width=quot;100quot; height=quot;25quot; text=quot;{album.title}quot;/> </mx:VBox> Slide 60 Copyright (c) 2009 Chris Richardson. All rights reserved.
  61. 61. Agenda g The joy and pain of UI development Overview of Flex Developing Flex Applications pg pp Pushing data to the client Building and testing Flex applications Slide 61 Copyright (c) 2009 Chris Richardson. All rights reserved.
  62. 62. Why events? y Cloud Photos server asynchronously uploads photos to S3 Client might display photo before it is available ⇒ Notify client when a photo is available Client can reload the image Slide 62 Copyright (c) 2009 Chris Richardson. All rights reserved.
  63. 63. BlazeDS Open-source project Connects Flex and AIR clients to Java backend services Client-side Flex components Server-side components, E.g. Servlet RPC services Proxying for remote (web) services Invoke server-side Java object Publish-Subscribe messaging Supports integration with JMS Spring BlazeDS project for simplified development Slide 63 Copyright (c) 2009 Chris Richardson. All rights reserved.
  64. 64. BlazeDS messaging components gg p Client Server receives messages from JMS Queue/ Consumer Destination Adapter Topic using Channel Endpoint corresponds to http://localhost:8080/webapp/messagebroker/amfpolling Slide 64 Copyright (c) 2009 Chris Richardson. All rights reserved.
  65. 65. Channel/Endpoint options / p p HTTP Options: Simple polling with piggyback Long polling – message/connection Streaming – many messages/connection Formats: AMF – efficient binary format AMFX – XML format Slide 65 Copyright (c) 2009 Chris Richardson. All rights reserved.
  66. 66. Example client-side consumer p <?xml version=quot;1.0quot; encoding=quot;utf-8quot;?> <mx:Canvas creationComplete=quot;creationComplete()quot;> <mx:Script> <![CDATA[ ![CDATA[ public function creationComplete() : void { consumer.subscribe();} private function messageHandler(event:MessageEvent):void { for each (var photoThumbnail : PhotoThumbnail in thumbnailContainer.getChildren()) { photoThumbnail.reloadIfNecessary(event.message.body.toString()); } } Server publishes a JMS event when it has uploaded an image ]]> </mx:Script> to S3. Client subscribes and reloads <mx:Consumer id=quot;consumerquot; destination=quot;message-destinationquot; images if required message=quot;messageHandler(event)quot; …/> <mx:Tile id=quot;thumbnailContainerquot; width=quot;100%quot; height=quot;90%quot;> <mx:Repeater id=quot;rpquot; id rp dataProvider=quot;{CloudPhotosModelLocator.getInstance().currentAlbum.photos.photo}quot;> <components:PhotoThumbnail photo=quot;{rp.currentItem}quot;/> </mx:Repeater> </mx:Tile> </mx:Canvas> Slide 66 Copyright (c) 2009 Chris Richardson. All rights reserved.
  67. 67. Spring beans for messaging pg gg <amq:topic id=quot;destinationquot; physicalName=quot;org.apache.activemq.spring.Test.spring.embeddedquot;/> <bean id=quot;consumerJmsTemplatequot; class=quot;org.springframework.jms.core.JmsTemplatequot;> <property name=quot;connectionFactoryquot; ref=quot;jmsFactoryquot;/> </bean> <bean id=quot;producerquot; class=quot;net.chrisrichardson.kickstart.backend.services.SpringProducerquot;> <property name=quot;templatequot; ref=quot;myJmsTemplatequot;/> <property name=quot;destinationquot; ref=quot;destinationquot; /> </bean> public class SpringProducer { private JmsTemplate template; private Destination destination; public void send(String message) { template.convertAndSend(destination, message); } } Slide 67 Copyright (c) 2009 Chris Richardson. All rights reserved.
  68. 68. BlazeDS MessageBrokerServlet g <servlet> <servlet-name>MessageBrokerServlet</servlet-name> <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class> l l fl i kS l / l l <init-param> <param-name>services.configuration.file</param-name> <param-value>/WEB-INF/flex/services-config.xml</param-value> </init-param> /i i <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> lt i <servlet-name>MessageBrokerServlet</servlet-name> <url-pattern>/messagebroker/*</url-pattern> </servlet-mapping> Slide 68 Copyright (c) 2009 Chris Richardson. All rights reserved.
  69. 69. services-config.xml g Shared by client and server Messaging Service One or more adapters One or more destinations One or more channels Destinations Referenced by client Source/sink of messages g Has an adapter, e.g. JMSAdapter Channels Used by a Flex component to communicate with the BlazeDS server Bl DS Communicate with server-side endpoints Endpoints URLs that URL th t are mapped t M d to MessageBroker servlet Bk lt Slide 69 Copyright (c) 2009 Chris Richardson. All rights reserved.
  70. 70. Channels and endpoints p <services-config> <channel-definition id quot; h l d fi i i id=quot;my-polling-amfquot; lli fquot; class=quot;mx.messaging.channels.AMFChannelquot;> <endpoint url=quot;http://localhost:8080/webapp/messagebroker/amfpollingquot; class=quot;flex.messaging.endpoints.AMFEndpointquot;/> l quot;fl i di AMFE d i quot;/ <properties> <polling-enabled>true</polling-enabled> <polling-interval-seconds>4</polling-interval-seconds> </properties> / ti </channel-definition> </services-config> / i fi Slide 70 Copyright (c) 2009 Chris Richardson. All rights reserved.
  71. 71. Messaging service gg <service id=quot;message-servicequot; class=quot;flex.messaging.services.MessageServicequot;> <adapters> <adapter-definition id=quot;actionscriptquot; class=quot;flex.messaging.services.messaging.adapters.ActionScriptAdapterquot; default=quot;truequot; /> <adapter-definition id=quot;jmsquot; class=quot;flex.messaging.services.messaging.adapters.JMSAdapterquot; /> </adapters> <default-channels> <channel ref=quot;my-polling-amfquot; /> ref my polling amf </default-channels> <destination id=quot;message-destinationquot;> <properties> <jms> j <destination-jndi-name>topicjndiname</destination-jndi-name> … </jms> </properties> /p p <adapter ref=quot;jmsquot; /> </destination> </service> Slide 71 Copyright (c) 2009 Chris Richardson. All rights reserved.
  72. 72. Agenda g The joy and pain of UI development Overview of Flex Developing Flex Applications pg pp Pushing data to the client Building and testing Flex applications Slide 72 Copyright (c) 2009 Chris Richardson. All rights reserved.
  73. 73. Using Flex Mojos g j Open source project Maven Mojos for building and testing flex applications http://code.google.com/p/flex-mojos/ Badly documented but they work y y Slide 73 Copyright (c) 2009 Chris Richardson. All rights reserved.
  74. 74. Building a Flex client p j g project <project> … <pluginRepositories> <pluginRepository> l iR i <id>pia-repository</id> <url>http://repository.sonatype.org/content/groups/flexgroup/</url> </pluginRepository> </pluginRepositories> <dependencies> <dependency> <groupId>cairngorm</groupId> “mvn install” builds SWF <artifactId>cairngorm</artifactId> <version>2_2_1</version> <type>swc</type> </dependency> /p y </dependencies> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <groupId>info.flex mojos</groupId> <groupId>info.flex-mojos</groupId> <artifactId>flex-compiler-mojo</artifactId> </plugin> …. </plugins> </build> </project> Slide 74 Copyright (c) 2009 Chris Richardson. All rights reserved.
  75. 75. Adding the SWF to y g your WAR <project> <packaging>war</packaging> … <dependencies> d d i <dependency> <groupId>net.chrisrichardson</groupId> <artifactId>kickstart-webapp</artifactId> Input = SWF + Existing WAR file <version>1.0-SNAPSHOT</version> <type>war</type> Output = new WAR file containing SWF </dependency> <dependency> <groupId>net.chrisrichardson</groupId> <artifactId>photoflexui</artifactId> <version>1.0-SNAPSHOT</version> <type>swf</type> yp / yp </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-maven-plugin</artifactId> <executions> <execution> <goals><goal>copy-flex-resources</goal></goals> </execution> </executions> </plugin> … Slide 75 Copyright (c) 2009 Chris Richardson. All rights reserved.
  76. 76. Automated testing g $$: HP QTP, RIATest FlexUnit Focused on unit tests Record UI tests with FlexMonkey Encountered a licensing error during compilation! Fluint Supposedly better than FlexUnit Not supported by Flex Mojos Slide 76 Copyright (c) 2009 Chris Richardson. All rights reserved.
  77. 77. Selenium-Flex Looks the most familiar/promising selenium.flexClick() selenium flexClick() selenium.flexWaitForElement() … Selenium extensions invoke ActionScript functions via External interface Include SeleniumFlexAPI.swc in your application External interface seems not to work in IE6 Tricky to get working in FireFox y g g Launching SeleniumServer via Java API didn’t work – extensions not loaded maven-selenium-plugin worked pg Slide 77 Copyright (c) 2009 Chris Richardson. All rights reserved.
  78. 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. 79. My next steps y p Write some automated tests Investigate Spring ActionScript Dependency injection framework Promotes loose coupling “Inject stubs for services” Investigate ExternalInterface ActionScript JavaScript Slide 79 Copyright (c) 2009 Chris Richardson. All rights reserved.
  80. 80. Summary Flex HTML/Javascript/CSS p Better paradigm (Open-source) testing tools are more Easier to develop mature Slide 80 Copyright (c) 2009 Chris Richardson. All rights reserved.
  81. 81. Final thoughts g Download or contribute to Cloud Tools today : y www.cloudtools.org Checkout Cloud Foundry: www.cloudfoundry.com www cloudfoundry com Buy my book ☺ Send email: chris@chrisrichardson.net Visit my website: www.chrisrichardson.net Talk to me about consulting and training Phone: 510 904 9832 Slide 81 Copyright (c) 2009 Chris Richardson. All rights reserved.
  82. 82. Resources http://www.actionscript.org/ http://www.adobe.com/devnet/actionscript/articl es/actionscript3_overview.html http://www.adobe.com/devnet/flex/ http://www.adobe.com/devnet/flash/ http://www.infoq.com/articles/java-flex-blazeds Intro link: http://www.adobe.com/devnet/flex/articles/intro ducing_cairngorm.html http://dispatchevent.org/roger/as3-e4x- rundown/ / http://myflex.org/presentations/ComparingFlexFr ameworks.pdf http://code.google.com/p/flexlib/ p // gg /p/ / Slide 82 Copyright (c) 2009 Chris Richardson. All rights reserved.
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×