<<

Adobe Flex Master Class Our upcoming book contains a lot more materials than you are about to learn during this training.

This master class is presented by three chickens who actually prepared it.

(c) Farata Systems Flex and Flash Player Write Once Flash Anywhere Architecture . .abc

.abc parser

JIT Compiler AOT Compiler LLVM Code Generator Verifier MIR Code Generator

MD Code Generator Interpreter iPhone Applicaon (x86, PPC, ARM, etc.) Packager

ARM LLVM Interpreter Runme System (Type System, Object Model) .ipa Memory Manager / Garbage Collector AS3‐Bytecode‐MIR‐Nave

iPhone Hello, World Demo Interpret or JIT Interpret or JIT‐Compile

• Inializaon funcons ($init) and constructors ($cinit) are interpreted • Everything else is JIT • DO NOT put performance‐intensive code in constructors or in class inializaon i.e.:

class Sieve { var n:int, sieve:Array=[], c:int, i:int, inc:int; set_bit(0, 0, sieve); set_bit(1, 0, sieve); set_bit(2, 1, sieve); for (i = 3; i <= n; i++) set_bit(i, i & 1, sieve); c = 3; do { i = c * c, inc = c + c; while (i <= n) { set_bit(i, 0, sieve); i += inc; } c += 2; while (!get_bit(c, sieve)) c++; } while (c * c <= n); } AconScript: Class and Instance

package farata.web { [Event(name="seleconChanged", type="flash.events.Event")] public class AssetBrowser extends mx.core.UIComponent { public var displayMode:String; [Bindable] public var selectedAsset:String; } }

Are You A Short Film Fan? • A regular Flex applicaon is a Flash movie of just two frames • Only few classes get linked to the first frame, all applicaon logic classes get linked to the second frame, which is connuously replayed What Makes Two Frames in Flex? • [Frame] metadata links annotated class to the next frame relave (aer) to factoryClass.

‐keep compiler switch Demo Flash Mentality Thinking In “Flash” 1/2 • Ted Patrick introduced “Elasc Racetrack” as the mental model of the single Flash Player thread that is processing user’s code

• Sean Christmann further redefined the frame as set of ‘Marshal’ slices, approx 20 ms each on Firefox/Mac (depends on the browser/OS): Possible Acons inside a Marshal Slice

1. Player events are dispatched Timer Mouse enterFrame URLLoader

2. User listeners for above events get executed stage.invalidate() gets invoked

3. Player dispatches Render event

4. User listeners (oponal) for Render event get executed

5. Player renders the changes How Many Timer Events Per Frame?

mer, mouse, UrlLoader render enterFrame

• Frame rate limit: can not exceed 1/sliceTime • Possibility of mulple player event invocaons per frame • callLater() is med to the “render” event

Elasc Racetrack Demo Flex Binding

• Binding engages Flex compiler to – generate code that dispatches events – generate code that watches for events – generate code that re‐computes expressions on events • You can take on yourself event‐dispatching • You can bind funcons and properes alike Binding Code Generaon

• Observe what mxmlc does with the simple variable: [Bindable] public var firstName:String;

Binding Examples Demo Advanced Visual Components

UIComponent Methods to Override

createChildren()

commitProperes()

measure()

layoutChrome()

updateDisplayList()

• Component lifecycle is based around callLater() • commitProperes() is used to avoid race condions • layoutChrome() is obsolete in light of Flex 4 skinning

CustomComponents Demo Flex 4: What’s changed?

Watch video lessons at hp://www.adobe.com/devnet/flex/videotraining/ flex4beta/ Read hp://www.adobe.com/devnet/flex/arcles/flex3and4_differences_03.html

• Separaon of component’s “look and feel” from its funconality. In Halo, skin is a part of the component; in Gumbo, skin is a separate class: spark.components.Buon and spark.skins.defaultBuonSkin

• Separaon of containment from layout. Containers can use pre‐built layouts ‐ BasicLayout, TileLayout, HorizontalLayout, VercalLayout ‐ or any custom layouts. BasicLayout (absolute posioning) supports constraints.

• New View States syntax. No more AddChild(), RemoveChild(). No more SetProperty(), SetEventHandler():

Flex 4: What’s changed?(cont.)

• There are two types of Spark containers: skinnable and non‐ skinnable

• Lighter non‐skinnable containers: Group, HGroup, VGroup, DataGroup To assign a specific layout to a selected group of components, place them inside

• Skinnable: SkinnableContainer, SkinnableDataContainer, Panel , Applicaon • By default, skins do not include scrolling. Example: to make your panel scrollable assign it a new skin in which contentGroup element of the (ancestor’s) PanelSkin is wrapped into Flex 4: What’s changed (cont.) • ItemRenderers extend s:ItemRenderer • Namespaces: fx ‐ language, s – Spark (new) components, mx Halo (old) components Flex Component LifeCycle

parent.addChild(new ComboBox ())

cbx.parent = cbx.createChildren() [ validateSkinState(), cbx.invalidateProperes(), invalidateSize(), invalidateDisplayList(), etc.] cbx.Event:inialize

invalidate cbx.parent.Event:inialize “later”

cbx.commitProperes() [ cbx.aachSkin() ] // LifeCycle of the skin is spawned ! cbx Event:partAdded cbx.measure() “later”

validate cbx.updateDisplayList() cbx.Event:updateComplete

cbx.visible=true cbx.Event:creaonComplete

render obj.Event:updateComplete Skin Inheritance Demo Selected Design Paerns What are Design Paerns?

Design paerns suggest an approach to common problems that arise during soware development regardless of what programming language you use.

But the goal of this presentaon is to highlight selected paerns as you may implement them taking advantage of the Flex framework. We’ll talk about the following paerns:

• Singleton • Proxy • Mediator • Data Transfer Object • Asynchronous Token • Class Factory Singleton

You can create only one instance of such a class.

There’s no private constructors in AconScript package somePackage{ public class MySingleton {

private stac const _instance: MySingleton = new MySingleton (Lock ); public stac funcon get instance():MySingleton { return _instance; } public funcon MySingleton( lock:Class ) { if ( lock != Lock ) { throw new Error( "Illegal instanaon." ); } } } // End of package class Lock { } Have you ever seen this?

var model: AppModelLocator = AppModelLocator.getInstance();

and this? service = ServiceLocator.getInstance().getHTTPService( 'loadEmployeesService'); Enhancing the Applicaon object public dynamic class DynamicApplicaon extends Applicaon implements IApplicaonFacade{ public funcon DynamicApplicaon(){ super(); } public stac var services:Diconary = new Diconary();

public funcon getService(name:String) : Object { return services[name]; } public funcon addService(name:String,value: Object): void { services[name] = value; } public funcon removeService(name:String) : void { delete services[name]; } public funcon getServices() : Diconary { The IApplicaonFacade just declares these return services; four methods to enable Flex Builder’s } intellisense help when casng. } var myApp:IApplicationFacade = … Adding any properes to myModel

Watch the video: hp://flexblog.faratasystems.com/?p=432 Sample dynamic applicaon

// Add required services to the Applicaon object, i.e. myModel and myServices private funcon addAllServices() :void {

DynamicApplicaon.services["myModel"]= new Object(); DynamicApplicaon.services["myServices"] = new Object(); } private funcon getData(serviceName:String, key:Object):Object{

return DynamicApplicaon.services[serviceName][key]; } private funcon setData(serviceName:String, key:Object, value:String):void{ DynamicApplicaon.services[serviceName][key]= new String(value); }

]]>

Sample dynamic applicaon (cont.)

Add one or more key/value pairs to the object MyModel

Retrieve and display the value from MyModel bykey

(c) Farata Systems Proxy A proxy is an object that represents another object and controls and/or emulates access to it’s properes and methods Think of a secretary who processes mail for her boss.

Major methods of flash.uls.Proxy

flash_proxy callProperty(name:*, ... rest):*

flash_proxy getProperty(name:*):*

flash_proxy setProperty(name:*, value:*):void

flash_proxy hasProperty(name:*):Boolean

Subclasses: RemoteObject, mx.uls.ObjectProxy ObjectProxy = flash.uls.Proxy + IExternalizable + IEventDispatcher + IUUID var myProxy = new ObjectProxy(object); Wrapping Person in ObjectProxy

funcon changeHandler(event:PropertyChangeEvent):void { log.text+="event.kind: "+ event.kind + " property :" + event.property + " old value:" + event.oldValue + " new value: " + event.newValue +"\n"; } ]]> Property Emulaon With ObjectProxy Use case: When the salary of a person increases over $55K, she becomes entled for the pension in the amount of 2% of the salary. You want to add this funconality without touching the code of the class Person. In a subclass of ObjectProxy, you can override package com.farata{ getProperty()and setProperty() to emulate properes that import mx.uls.ObjectProxy original object does not have import flash.uls.*; use namespace flash_proxy; public dynamic class MyPersonProxy extends ObjectProxy { private var person:Person; public funcon MyPersonProxy(item:Person){ super(item); person=item; } flash_proxy override funcon setProperty(name:*, value:*):void { if ( name == 'salary' && value>55000) { // add a new property to the instance of the dynamic class Person // to be used in computaon of the total compensaon setProperty("pension", 0.02); } super.setProperty(name, value); } }} Method Emulaon With Proxy

Use case: we want to simplify LocalConnecon API that allows a SWF( aka client) to call a public method on the another friendly SWF (aka server) on the same computer:

var outConnecon = new LocalConnecon(); outConnecon.send( "_myConn”, "sampleFuncon", param1 );

private var inConn:LocalConnecon; public funcon onCreaonComplete():void{ inConn = new LocalConnecon();inConn.client = this; connecon.allowDomain; connecon.allowInsecureDomain("*"); connecon.connect( "myConn" ); } public funcon sampleFuncon(parm:String):void{ trace(" " + parm); } Method Emulaon With Proxy (cont.) • Compare the client call with and without custom proxy ‐ LocalObject:

var outConnecon = new LocalConnecon(); WITHOUT outConnecon.send( PROXY "_myConn”, "sampleFuncon", param1 );

WITH PROXY server.sampleFuncon(param1); . . . . Meet “LocalObject” Proxy

• LocalObject (abbreviated) interprets any obj.methodName() calls:

LocalConnecon Demo Mediator

Any complex screen, more or less, of a business applicaon consists of a number of containers and components.

We want to create loosely‐coupled custom components that are self contained, do not know about existence of each other and can communicate with the “outside world” by sending and receiving events. Mediators and components

(c) Farata Systems Wall Street: Stock Trading Applicaon Before the trader clicked on the Price Panel PricePanel component has three variables: symbol, bid and ask

PricePanel dispatches the OrderEvent dispatchEvent(new OrderEvent( OrderEvent.PREPARE_ORDER_EVENT , symbol, bid,ask,buy));

OrderPanel listens to OrderEvent Aer the trader clicked on the Price Panel addEventListener( OrderEvent.PLACE_ORDER_EVENT, orderEventHandler)

funcon orderEventHandler(evt:OrderEvent){ sym.text=evt.symbol; operaon.text=evt.buy?"Buy":"Sell"; price.text=(oper.text=="Buy"? evt.bid:evt.ask); } PricePanel Component. Take 1

public funcon OrderEvent(eventType:String, symbol:String, bid:String, ask:String, buy:Boolean=false ){ super(eventType,true, true); // let it bubble this.symbol=symbol; this.bid=bid; this.ask=ask; this.buy=buy; this.eventType=eventType; } override public funcon clone():Event{ return new OrderEvent(eventType,symbol, bid, ask,buy); } } } The Mediator receives this event from PricePanel and dispatches it to OrderPanel The Mediator applicaon Listen to the OrderEvent from PricingPanel

private funcon orderEventHandler(evt:OrderEvent):void{ // The mediator decides what to do with the received event // In our case it forwards the order received // from PricePanel to OrderPanel var orderEvt: OrderEvent= new OrderEvent(OrderEvent.PLACE_ORDER_EVENT,evt.symbol, evt.bid, evt.ask, evt.buy); ordPanel.dispatchEvent(orderEvt); } ]]> …and send it to OrderPanel Introducing DTO in Stock Trading App.

Instead of passing several variables between pricing and order panels, we’ll encapsulate order details in the OrderDTO class and put it inside the event object to the mediator. package com.farata.dto{ [Bindable] public class OrderDTO{ public var symbol:String; public var bid:String; public var ask:String; public var buy:Boolean; //a buy/sell flag

public funcon OrderDTO(symbol:String, bid:String, ask:String, buy:Boolean=false){ this.symbol=symbol; this.bid=bid; this.ask=ask; this.buy=buy; } } } Trading sample, take 2

1. PricePanel2 dispatched an event with packaged DTO inside 2. Mediator receives the event object and extracts from it the DTO 3. Mediator dispatches an event to OrderPanel2 with packaged DTO inside 4. OrderPanel2 receives the event, extracts the DTO and processes it A DTO fragment with bid property

[Bindable(event="propertyChange")] public dynamic class OrderDTO extends EventDispatcher{

private var _bid:Number; private var _lastPrice:Number;

public funcon set bid(value: Number):void { var oldValue:Object = _bid; if (oldValue != value) { _lastPrice = value; dispatchUpdateEvent("bid", oldValue, value); } }

public funcon get bid(): String{ return _bid; }

private funcon dispatchUpdateEvent(propertyName: String, oldValue:Object, value: Object): void{

dispatchEvent( PropertyChangeEvent.createUpdateEvent(this, propertyName, oldValue, value)); } ... }

Farata Systems has created Dto2Fx generator that creates AconScript DTOs from their Java counterparts. It’s part of the open source Clear Toolkit project (c) Farata Systems AsyncToken

The goal of the Asynchronous Token paern is to properly route the processing on the client in response to the data arriving in an arbitrary order from the server

AsyncToken is a dynamic class, you can add any properes to this class during runme.

With AsyncToken you can add mulple event handlers (responders) to a remote call.

… private funcon sendOrder(/*arguments go here*/):void{

var token: AsyncToken = ord.placeOrder({item:”Sony TV”}); token.orderNumber=”12345”;

token.responder = new Responder(processOrderPlaced, processOrderFault); token.addResponder(new Responder(createShipment,processOrderFault)); } When the result comes back

AsyncToken is a local object. It is idenfied by a messageId that is passed with the request to server.

When the server responds, it includes a correlationId property in the message header, and Flex automacally calls the appropriate AsyncToken responders in the order they were defined. private function processOrderPlaced(event:ResultEvent):void {

myOrderNumber:Object = event.token.orderNumber;

// if myOrderNumber is 12345, process it accordingly } Class Factory Creang an instance of an object: var order:MyObject = new MyObject(); order.description=”Sony TV”;

What if someme you need to create an instance of MyObject, and somemes HisObject?

Implement a class factory design paern to to build various instances. A simple implementaon is to write a switch statement that, based on the argument, returns an appropriate instance mx.core.ClassFactory as ItemRenderer var productRenderer:ClassFactory = new ClassFactory(ProductRenderer); productRenderer.properties = { showProductImage: true }; //productRenderer.newInstance();not needed for List myList.itemRenderer = productRenderer;

1.create an instance of the class ProductRenderer – it’s stored in the generator property of this class.

2.Inializes the property showProductImage of the newly created ProductRenderer. Can inialize more than one key/value pairs

3. Use newly created object as an item renderer of a List component (they know how to instanate objects that implement iFactory)

A renderer without properes: Limitaons of Flex 3 mx.core.ClassFactory

• The class mx.core.ClassFactory can create a factory only for a class. It can’t build instances of objects based on a return of a funcon – a class is required.

• Building UI objects on the fly may require applying dynamic data‐driven styles. Styles are not properes and mx.core.ClassFactory would not know what to do with them if you’d used them in the properties var.

• Renderers of UI components may need to process events. It would be nice if event listeners could be aached by a class factory and created object would dispatch events when properes are changing. In Flex 3, the class mx.core.ClassFactory doesn’t know how to do it. com.farata.core.UIStacClassFactory

Clear Toolkit includes com.farata.core.UIStaClassFactory and com.farata.core.UIClassFactory described in Chapter 2 of the book “Enterprise Development with Flex”

// Data provider for the grid … public class ColumnRecord { private funcon switcher(data:Object = null) :*{ public var columnLabel:String; if (data == null) return new Label(); public var columnType:String; switch(data.columnType) { public var columnValue:*; case "ssn": var mi:MaskedTextInput = public funcon ColumnRecord( new MaskedTextInput(); l:String, t:String, v:*) { mi.inputMask = "###‐##‐####"; columnLabel=l; return mi; columnType=t; } columnValue=v; return new TextInput(); } } UIStacClassFactory feeds a form Styling with com.farata.core.UIClassFactory Delcarave styles with UIClassFactory {MaskedTextInput} {MaskedTextInput} Delcarave styles with UIClassFactory (cont.)

Dynamically change the styles fontWeight and background column depending on the value of the Salary in each row: UIClassFactory: editors with listeners {CheckBox}

Class Factory in Flex 4 Flex 4 allows you to dynamically assign item renderers to List based components based on the name of the class provided in a String variable:

… private funcon myRenderedFunc (item:Object): ClassFactory{ var myRenderer:Class;

switch (item.membershipType){ case “Trial”: myRenderer=TrialMemberRenderer; break; case “Basic”: myRenderer=BasicMemberRenderer; break; case “Premium”: myRenderer=TrialMemberRenderer; break; } return new ClassFactory(myRenderer); } Integraon with the server Integraon With Server: LCDS vs. BlazeDS

LiveCycle DS vs. BlazeDS Data Management Service Adapters Data Synchronization • LCDS advantages: Fiber • Scalability (10000 users /CPU) Data Paging • Reliability Lazy loading SQL • Developers’ Producvity RPC Services

Hibernate Web Service • BlazeDS advantage:

HTTP Service ColdFusion Development • Service Free and open source

Remote Object Service Java Proxy

Messaging XDP-PDF Generation WSRP Portal Integration WSRP JMS Model-driven Pub/Sub via Servlet Threads

Pub/Sub via Java NIO Custom… Real-time Data Push

Reliable Communications James Ward “Census” Benchmark MessageBroker Endpoints

RTMP Endpoints rtmp://server:port1 RTMP

rtmp:// Server server:port2 Socket

NIO Endpoints http://server:port3/nioamf

http://server:port4/nioamf‐2

https://server:port5/nioamf‐top‐secret Server NIO Socket

AMF Endpoints http://server:port/context/messagebroker/amf

http://server:port/context/messagebroker/amf‐123

https://server:port/context/messagebroker/amfsecret Flex Message Broker

HTTP Endpoints Servlet

http://server:port/context/messagebroker/hp Message Broker https://server:port/context/messagebroker/hpsecure Flex Messaging Configuraon

• MessageBroker configuraon files – Design‐me and run‐me purpose – Using ‐ services is Flex vs. Air – Injecon of channels and desnaons into compiled SWF – dynamic channel configuraon:

var channelSet:ChannelSet = new ChannelSet(); var channel:AMFChannel = new AMFChannel("my‐amf", amfEndpoint); channelSet.addChannel(channel); remoteObj.channelSet = channelSet; remoteObj.getEmployees=();

• Compiling portal SWF against mulple MessageBrokers with remote=true to absolve portal’s MB from running a portlet’s MB endpoint:

ParallelRemong Demo Porolio RPC Demo RPC demo with Porolio Applicaon

PorolioRPCDemo (walkthrough) Data Synchronizaon in LCDS LCDS Data Synchronizaon • Many clients “live share” data, poinng to the same desnaon in the data‐ management‐config.xml • Changes in the locally managed array collecons are tracked and published to the desnaon; each client acts as a consumer and a producer at the same me • Applicaon may call commit() method to ship all changes in one shot. • Default – autocommit. • Custom Java objects backing DMS usually provide . a method returning the collecon, aka fill method . a method processing the list of changes sent from the client, aka sync method

fill() Custom sync() DMS Assembler Data Management Service DMS Example DMS Demo DMS Demo Flex LCDS/Blaze DS Protocols

• BlazeDS documentaon hp://livedocs.adobe.com/blazeds/1/blazeds_devguide/ blazeds_devguide.

hp://opensource.adobe.com/wiki/display/blazeds/BlazeDS/

• LCDS Capacity planning hp://www.adobe.com/products/livecycle/pdfs/ 95011594_lcds_planguide_wp_ue.pdf Polling

Polling interval – me delay before the next polling

true 3 Long Polling

Property Meaning

wait‐interval‐millis 60000 (how long the server should wait before returning a polling request) client‐wait‐ 1 (how long the client should wait to reissue) interval‐millis max‐waing‐poll‐ number of allowed server threads before falling back to requests simple polling

true 3 60000 1 100 Streaming

Property Meaning idle‐meout‐minutes how long the server should wait before returning a polling request server‐to‐client‐ 3000 heartbeat‐millis max‐streaming‐ 100 (number of allowed server threads ) clients

0 100 3000 Client‐2‐Client Messaging Use Case Client‐to‐client Messaging Producer and Consumer Apps Producer and Consumer Applicaons

public funcon send():void { var message:AsyncMessage = new AsyncMessage(); message.body = "SomeText"; // could be a complex object message.headers.arbitraryHeaderName = "value“; producer.send(message); }

public funcon onMessage (event:MessageEvent):void { // process event.message.headers and // event.message.body trace(event.message.body); // “SomeText” } Client‐to‐Client‐2‐Client Messaging Use Case Client(s) Messaging

Chat Demo Server Push (BlazeDS or LCDS)

• Server may produce messages too • In parcularly, server may produce these messages as mediator between clients and external JMS Provider ( JMS Adapter) Server Push (BlazeDS or LCDS)

MessageBroker msgBroker = MessageBroker.getMessageBroker(null); AsyncMessage msg = new AsyncMessage(); msg.setDesnaon("feed"); // target desnaon msg.setClientId(UUIDUls.createUUID(false)); msg.setMessageId(UUIDUls.createUUID(false)); msg.setTimestamp(System.currentTimeMillis()); msg.setBody(“Pushed Message" ); // arbitrary message msgBroker.routeMessageToService(msg, null);

hp://localhost:8080/BlazeMessagingDemo/stareed.jsp hp://localhost:8080/BlazeMessagingDemo/stopfeed.jsp

ServerPush Demo Flex Remong: Classes And Channels

(your) Object (your) Factory Adapter Service Service Message Agent Channel EndPoint Channel Definion

com.farata.test. HelloWorld (oponal) Factory flex.messaging.servic mx.rpc.remong. es.remong.adapters. RemoteObject JavaAdapter flex.messaging.servic mx.messaging.Producer es.RemongService mx.messaging.channels. flex.messaging.endpo AMFChannel ints.AMFEndpoint

my‐amf Custom RemoteObject: You want to avoid “session” on the server? With or you can use message headers to pass the context informaon on each call. However, the does not have access to message headers Here we will make custom RemoteObject to support remoteObject.headers:

private funcon onClick():void { // Custom remote object allows passing "session" informaon via headers var headers:Diconary = new Diconary(); | headers["region"] = "NorthEast"; AconScript remoteObject.headers = headers; remoteObject.test('Victor'); }

public class HelloWorld { public String test (String arg) { Java return "Hello, " + arg + "(" + LastMessage.getMessage().getHeader("region") + ")"; } } Custom Java Adapter 1,2 and … public class JavaAdapter extends flex.messaging.services.remong.adapters.JavaAdapter { public Object invoke(Message msg) { try { LastMessage.setMessage(msg); //LastMessage persists msg in the thread‐local variable return super.invoke(msg); } finally { LastMessage.setMessage(null); } }}

remong‐config.xml:

class="flex.messaging.services.remong.adapters.JavaAdapte r" id="java‐object"/> Custom Java Adapter … 3 public class LastMessage {

public final stac String AUTOSYNC_SUBTOPIC_HEADER_NAME="autoSyncSubtopic";

private stac ThreadLocal s_tlsMsg = new ThreadLocal();

public stac Message getMessage() { return (Message)s_tlsMsg.get(); }

public stac void setMessage(Message msg ) { s_tlsMsg.set(msg); } }

Custom Remong Adapter Demo Modules, Libraries, Applicaons Loading as CornerStone of Paroning

• SWF of the main applicaon can load other classes located in other packaged as: – modules – libraries – applicaons • Class: flash.display.Loader – Libraries – Modules – Applicaon • Paroning = Dynamic class loading Nucleus of Loading‐ Image

• Dynamic Loading:

• Embedding

• Explicit Reference: Embedding with reuse

Embedding: Generated Image Class

package { import mx.core.BitmapAsset; [ExcludeClass] [Embed(_resolvedSource=“c:/workspace/ModuleLoaders/src/assets/ faratalogo_header.png", _column="3", source="assets/faratalogo_header.png", exportSymbol="StacImageDemo_logoClass", _line="147", _pathsep="true", _file=“c:/ workspace/ModuleLoaders/src/generated/StacImageDemo‐generated.as")]

public class StacImageDemo_logoClass extends mx.core.BitmapAsset { public funcon StacImageDemo_logoClass() { super(); } }} Dynamic Image Loading: Close‐Up [Bindable] private var imageByteArray:ByteArray; private funcon loadImage():void { var urlRequest:URLRequest = new URLRequest(IMAGE_URL); var urlLoader:URLLoader = new URLLoader(); urlLoader.dataFormat = “binary”; urlLoader.addEventListener(“complete”,onComplete); urlLoader.load(urlRequest); } private funcon onComplete(event:Event):void{ var urlLoader:URLLoader = event.target as URLLoader; imageByteArray = urlLoader.data as ByteArray; loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, getBitmapData); loader.loadBytes(imageByteArray); } [Bindable] private var bitmap:Bitmap; private funcon getBitmapData(e:Event):void { bitmap= loader.content as Bitmap; } . . . ByteCode vs. Class Definions • Ulmate subjects of the dynamic loading are class definions, be that definions of assets or components • Transfer of the byte code and actual creaon of class definions are two separate acons – Transfer: URLLoader – Creaon of class definion & adding to stage: Loader (mx:Image contains Loader)

Image Demo (Module Loaders) Dynamic Styles

/* styles.css */

@namespace s "library://ns.adobe.com/flex/spark"; @namespace mx "library://ns.adobe.com/flex/halo"; s|Applicaon { skin‐class:ClassReference("skins.ApplicaonSkin"); } s|Buon.leArrow { skin‐class:ClassReference("skins.LeArrowBuonSkin"); } .controlBarPanelStyle { skin‐class: ClassReference("skins.GradientRectSkin"); } Dynamic Styles: Meet the Managers private const STYLE_MODULE_URL:String = '/Modules/styles.swf'; private funcon toggleStyles():void { var localStyleManager:IStyleManager2 = StyleManager.getStyleManager( this.systemManager ); try { var moduleInfo:IModuleInfo = ModuleManager.getModule(STYLE_MODULE_URL); } catch (e:Error) {trace("Check that " + STYLE_MODULE_URL + " exists");}

if (moduleInfo.loaded) { localStyleManager.unloadStyleDeclaraons(STYLE_MODULE_URL); } else { localStyleManager.loadStyleDeclaraons(STYLE_MODULE_URL); } } RunmeStylesDemo All Roads Lead To … Loader

SWFLoader ModuleManager

flash.display.Loader flash.display.Loader

flash.net.URLLoader Image

• All work is done by Loader oponally assisted by URLLoader Modules: ModuleLoader

• In case of ModuleLoader, all heavy liing is done by flash.display.Loader as well:

Module Manager: Preloading • Provides singleton registry of modules • Separates loading from instanaon • Pre‐loading:

private var moduleInfoRef:Object = {}; //keep‐alive trick for moduleInfo private funcon loadModule():void { var info:IModuleInfo = ModuleManager.getModule(moduleUrl); info.addEventListener(ModuleEvent.READY, onModuleReady ) ; moduleInfoRef[moduleUrl] = info; info.load(); private funcon onModuleReady(event:ModuleEvent):void { moduleInfoRef[event.module.url]=null; } Module Manager: Instanaon private funcon createModuleInstance(moduleUrl:String, parent:UIComponent=null):Module { var module:Module; var info:IModuleInfo = ModuleManager.getModule(moduleUrl); var flexModuleFactory:IFlexModuleFactory = info.factory; if (flexModuleFactory != null) { module = flexModuleFactory.create() as Module; if (parent) { parent.addChild(module); } } return module; }

ModuleManager Demo Shared Event Dispatcher

loaderInfo.sharedEvents Applicaon SWF

Shared Event Dispatcher

Module SWF systemManager.loaderInfo.sharedEvents Communicang With the Modules

• Bad: Direct name reference • Slightly beer: Interfaces • Any referencing opens a possibility of a memory leak • Best: exchange events via loaderInfo.sharedEvents

ReferenceCommunicaon and EventCommunicaon Demos A Tree of Applicaon Domains

Flash Player System Classes Domain

Flex Framework Domain of Domain of and Business Flex Flex Applicaon Classes Applicaon 1 Applicaon 2

Classes Specific for Domain of Domain of Domain of Business Module 1.1 Module 1.2 Module 2.1 Subsystem

• Classes get loaded into Applicaon Domains • Child domain classes “see” parent’s classes; re‐load of the same class is not possible (unless via unload) Loading Modules into Child Domain (Default)

Module Classes that are not linked by Applicaon

Flex Framework and Applicaon Classes

Flash Player Classes

Loading Modules into Same Domain (Default)

Flex Framework Applicaon and delta Module Classes

Flash Player Classes

ModuleDomainDemo

• Applicaon will have access to the module classes when module is explicitly loaded in the applicaon’s domain • Dynamic class instanaon:

try { var clazz:Class = loaderInfo.applicaonDomain.getDefinion ("CustomGrid") as Class; } catch (error:ReferenceError) { Alert.show ("Definion of 'CustomGrid' class can not be found in the current domain of the applicaon ","Class Not Found Error"); return; }

dg = DataGrid(new clazz()); How to Use Modules

• Use Modules to package – Subsystems of the enterprise applicaons that you would be able to recompile from sources for every release • Modules are explicitly loaded by the applicaon. Choices: child applicaon domain (default), same applicaon domain • Load modules into the same domain to achieve the seamless possible integraon • For beer class isolaon – load applicaons (later in the presentaon • Modules are notorious for rewring the global applicaon sengs. Compile module without –services to avoid rewrite of the channels and desnaons • Manage memory by focusing on unloading arrays and images that take real space, rather then on unloading modules. • Beware: [RemoteObject] make modules unloadable • Provide a test bed for local debugging and unit test of the module in the isolaon from the main Flex project) Flex Libraries

• Flex Library Projects are used for design‐me packaging of the reusable components into SWC files • The run‐me use depends on the link‐type: how you link the SWC to the applicaon (or module) The Purpose of Link Types

• Merge‐in (inject main SWF with ‘required’ classes): – to speed up download of the Internet applicaons that do not share classes with other applicaons and are not subject to frequent changes

• RSL (download enre SWF): – to speed up combined download of the related applicaons and subsequent versions of these applicaons; – to allow dynamic class instanaon via getDefinionByName()

• External (delegate responsibility): – to avoid packaging classes that are to be loaded by other SWFs before ‘out’ SWF gets loaded itself. RSL Metamorphosis

Thesaurus: 1egg : Flex Library Project 2 RSL! caterpillar : SWC file 3pupae: build process (FB, Ant) 4adult : SWF file of RSL

SWC will fly only if link type is RSL SWC Anatomy

• A SWC file is an archive with dormant library.swf inside it:

• During the build process library.swf gets by default extracted as (example) ComponentLibrary.swf • During the run‐me applicaon or module will look for a ComponentLibrary.swf according to link url How much of an applicaon code must arrive from the server if you have the following swf and swc?

MyFlexApplicaon 500Kb+n, where n<=100Kb .swf weighs 500Kb Case 1: Merged Into Code: Only those library classes that are menoned in the app get merged in

MyFlexLibrary.swc 500Kb+100Kb=600Kb weighs 100Kb Case 2: RSL: Do you think I’m stupid or something to use RSL?

Quiz: How many SWFs get deployed in each case? RSL SWF vs. Applicaon SWF

• Applicaon’s or module’s SWF: “main” class – descendant of SystemManager (SM) – is located in the first frame of the SWF movie, all other classes and assets SM loads into the second frame • Library’s SWF has only one frame – the bag of classes, without its own SM • Library classes get preloaded by the applicaon’s or module’s SM prior to the rest classes Peeking inside Applicaon & Module • Applicaons and Modules are two‐frame SWFs • Frame 1 is occupied by the neighborhood of the SystemManager class – the entry point to your applicaon. Peeking inside a Custom Library SWF • Custom Library SWFs don’t have the inializaon frame (but Flex framework libraries DO!) RSL: “A Bug By Design”

• Library project yields library.swf inside the SWC file • Compilaon of the library against a parcular applicaon or module generates Styles and FlexInit mixins specific to the applicaon or module • These mixins supplement only those library classes that are stacally referenced by the applicaon or module code. And they fail to do so for classes that you want to reference dynamically

• The design problem is that mixins are not arfacts of the library.

UsingLibrary Demo An Illustraon of RSL BBD – Flex 2/3 This will be MISSING from Styles mixin, if no Panel is referenced stacally: spark.components.Panel selector = new CSSSelector( "spark.components.Panel", condions, selector); mergedStyle = styleManager.getMergedStyleDeclaraon( "spark.components.Panel"); style = new CSSStyleDeclaraon(selector, styleManager, mergedStyle == null);

This will be MISSING from FlexInit mixin, if class used in remong is not referenced stacally in the applicaon:

try { if (flash.net.getClassByAlias("foo.Bar") == null){ flash.net.registerClassAlias("foo.Bar", flex.class.with.RemoteClassAnnotaon);} } catch (e:Error) { flash.net.registerClassAlias("foo.Bar", flex.class.with.RemoteClassAnnotaon); } How to Build Healthy RSLs

• Replace SWF produced by compc compiler (or build of the Flex Library Project) with your own:

1. Turn off “AutoExtract” linking opon. Library SWF will not be produced on each build of the applicaon SWF

2. Add to the project a descendant of the mx.core.SimpleApplicaon that stacally references all library classes. Wrap it with MXML to force compiler into generang mix‐ins. Compile the project with the Ant, but compile it with mxmlc compiler, i.e. – as applicaon. Now you have library that takes care of itself.

3. Drop this autonomous library SWF at the deployment locaon instead of the autoExtracted one. Bootstrapping the RSL package { import mx.core.SimpleApplicaon; public class LibraryHead extends SimpleApplicaon { import com.farata.samples.CustomPanel; CustomPanel; //forced link public funcon LibraryHead () { trace(“Library inialized"); // Place you custom init code here }}}

Build Self‐Safe RSL with ANT Libraries Bootstrapped as Applicaons

• Build these libraries with ANT / mxmlc • Place the SWF into bin of the expecng applicaons • Do NOT use AutoExtract on SWC!

• Results: – Libraries that are self‐sufficient; – Libraries that are reusable across applicaons; – Libraries that are safe for dynamic linking • (Oponal) Automaon of the enre process: – Farata Fx2Ant Plugin

How to Use RSLs ‐ Summary

1. Use RSLs to package reusable components 2. RSL means pre‐load into the same applicaon domain 3. For link‐type of the library(SWC or project) in the main project of the modular applicaon choose RSL (FB4 default) 4. For link‐type for the same library in the module of the modular applicaon choose external 5. When you build the very library, consider external for the libraries it depends on (FB4 default); apply #3 to these libraries 6. Consider packaging Flex SDK libraries, especially framework.swc and datavisualizaon.swc as RSLs (FB4 default) (plus you can benefit from signed versions) Loading Applicaon as Siblings

Flash Player Classes System Domain

Flex Framework Sibling (sub) and Business Flex Applicaon 1 Applicaon 2 (SDK 3.2+) Applicaon Classes (SDK 3.2+)

Non‐overlapping Child (sub) Flex Framework Applicaon 1.1 and Business (SDK must match Applicaon Classes parent’s)

or swfLoader.loaderContext= new LoaderContext( false, new ApplicationDomain(null) ); Loading Scenarios Inside the Same Web Domain

Loader Context Syntax SWFLoader Syntax Scenarios swfLoader.loaderContext=new Multiversioning swfLoader.loaderContext=new D_omain

ApplicationDomain.currentDomain ) The default one ); swfLoader.loaderContext=new Not applicable SS* LoaderContext( false, S_same D_omain ApplicationDomain.currentDomain ); Possible, dubious

SameSandboxChildDomainDemo ‐ default portlet loading Loading Applicaon Across Web Domains

System System Flash Player Domain Flash Player Domain Classes Classes localhost 127.0.0.1

Flex and Flex Flex and Flex Business Business Applicaon Applicaon 1 Applicaon Applicaon 3 (SDK 3.2+) Classes Classes (SDK 3.2+)

or swfLoader.loaderContext= new LoaderContext( false, new ApplicationDomain(null), SecurityDomain.currentDomain ); Sandboxes a.k.a. Security Domains

• A sandbox hosts a tree of applicaon domains • Types of Sandboxes – Local with networking – Local with filesystem – Local with trust – Remote ‐ one per web (sub)domain; can not “create” a sandbox programmacally – A sandbox hosts a tree of applicaon domains • Visual differences: sub‐applicaon running in a separate sandbox will center/clip popups to it’s own size; drag/drop will not be supported What You Can Do With Different Net Domains Loader Context Syntax SWFLoader Syntax Scenario swfLoader.loaderContext=new null ); DSDD: Multiversioning swfLoader.loaderContext=new swfLoader.loaderContext=new ), SecurityDomain.currentDomain SSCD ); swfLoader.loaderContext=new N/A S_ame_S_andBox – LoaderContext( false, S_ame_D_omain ApplicationDomain.applicationDomain, SecurityDomain.currentDomain ); SSSD Mulversioning and Class Sharing

Flash Player System Domain Classes

Flex Messaging Custom and Common for all Domains Bootstrap Loader Business Classes Applicaon

Flex and Business Flex Applicaon Flex Applicaon Applicaon 1 2 Classes

• Mul‐versioning: interoperaon between Flex 3.2 + applicaon • Requires use of sibling (or from another sandbox) applicaon domains • There is no class casng between siblings or across sandboxes Bootstrap Loader

• If you use Flex Messaging you need an arficial domain to parent your “siblings”, or the first sibling to inialize a messaging channel with the Flash Player will monopolize messaging on behalf of the enre sandbox. No one else will see messages coming back from the server. • If you exchange structured data across siblings you need to define the common classes in a common parent applicaon domain

• SameSandboxDifferentDomainDemo with & w/out BSLoader • SampleFlexPortalDemo How to Use Applicaons

• Use Applicaons to package – Subsystems of the enterprise applicaons that you will not be able or might not want to recompile from sources for every release: different versions of the base libraries, different versions of the Flex framework, etc. • Loading of the (sub) applicaons is explicit task of the applicaon code • Applicaons from the different net domain are automacally loaded into the sibling applicaon domain • Applicaons from the same net domain are by default loaded into the child applicaon domain. You may want to load them into the sibling domain for complete version separaon Example Projects for Libraries/Modules

The sample projects used in the Modules and Libraries units are:

ApplicaonLoaders.zip, Charts.zip, Feeds.zip, ModuleLoaders.zip, Modules.zip Portal.zip, PortalBootstrap.zip, PortalLib.zip, RemoteSite.zip, UsingLibraries.zip Data Synchronizaon with BlazeDS/ LCDS using DataCollecon Cornerstone of Data Management – ChangeObject – The Cornerstone of Data Management ChangeObject Interface

•hp://livedocs.adobe.com/livecycle/es/sdkHelp/programmer/lcdsjavadoc/ flex/data/ChangeObject.html: • getNewVersion(), getPrevVersion() • isUpdate(), isCreate(), isDelete() • getChangedPropertyNames() • setNewVersion()

• All changes are communicated as list of ChangeObjects: • Changes from client to server • Changes from server to client • Response to changes sent by this client (echo) • Proliferaon of changes sent by other clients (push)

• Only original data set is sent as complete list of records – once! Java Backing of Adobe Data Management The Java side of Adobe Data Management Service Service • Applicaon may call commit() method to ship all changes in one shot. • Default – autocommit. • Custom Java objects backing DMS usually provide . a method returning the collecon, aka fill method . a method processing the list of changes sent from the client, aka sync method

fill()

sync() Custom DMS Assembler Farata’s Data Management

• Clear Toolkit hps://sourceforge.net/projects/cleartoolkit/ supports data synchronizaon over RemoteObject and Consumer (BlazeDS is ENOUGH) • Supports data pull and server push (changes) • Support of paginaon: roadmap • Enables client‐side managed transacons: – transaconal commit from several array collecons – transaconal batching of any number of remong operaons – supports hierarchical nesng of collecons • Major objects: – DataCollecon – BatchService Farata’s DataCollecon Soluon

What’s DataCollection?

• com.farata.collecons.DataCollecon – part of Farata Clear component library.

• Extension of standard ArrayCollecon

• Features: – “desnaon aware”, knows where to fill itself from (on the Java Remong side) – “change tracking”, records all interacve and programmac changes – “sync‐able” – knows the Java Remong method to submit all accumulated changes to the server – “push‐ready” – has internal Consumer for server‐pushed changed DataCollection Satellites

• com.farata.remong.BatchService – allows batching of changes to mulple DataCollecons to be sent to the server for atomic processing • CDB plugin: CRUD code generaon for Java and Flex with two starng points: a) SQL – all Java will be code generated for you or b) Java DAO and DTO. DataCollection Demo Use Case How to Program a Client Managed Transaction

• Have a fill method (getEmployee) returning DTO list • Have _sync() method for simple synchronizaon; • Have _deleteItems()/_updateItems()/_insertItems() for smart batching of changes in “master‐detail” scenario

getEmployee()

getEmployee_sync()

getEmployee_deleteItems()

getEmployee_insertItems() EmployeeDao

getEmployee_updateItems() BatchService / Batch Gateway Tandem

• com.farata.remong.BatchService is a part of Farata clear.swc – Allows to group together changes accumulated by mulple DataCollecons: batchService.registerCollecon(orders, 0); //level 0 ‐ master batchService.registerCollecon(orderItems,1); //level 1 ‐ details – Allows to send the batch of changes to be executed as single JTA transacon by the server: var batch:Array = batchService.batchRegisteredCollecons(); batchService.sendBatch(batch) • com.farata.remong.BatchGateway is a part of Farata daoflex‐runme.jar, pre‐installed upon configuring a CDB project – Serves preconfigured desnaon that BatchService sends his batches to. Executes the batch sequenally (by default – as signle JTA transacon) Preparing a Batch on the Client

public class OrderController { public funcon OrderController(){ orders = new DataCollecon(); orders.desnaon="Order"; orders.method="getOrders"; orderItems = new DataCollecon(); orderItems.desnaon="Order"; orderItems.method="getOrderItems"; . . . . } public funcon fillOrders():void { orders.fill(); } public funcon fillOrderItems(orderId:String):void { orderItems.fill(orderId); } } Sending a Batch to the Server

public class OrderController { public funcon OrderController(){ . . . . batchService = new BatchService(); batchService.registerCollecon(orders, 0); //master batchService.registerCollecon(orderItems,1); //level 1 details, orders } public funcon commit():void { var batch:Array = batchService.batchRegisteredCollecons(); batchService.sendBatch(batch); // transacon, by default } } Executing a Batch on the Server

• Pre‐built class com.farata.remong.BatchGateway • Allows to call mulple remote Java methods in sequence according to the list of BatchMember’s prepared in AconScript. • Allows to wraps JTA transacon around this sequence • BatchMember: (“desnaon”, “method”, [ arguments]) • Use cases: batch updates, batch retrieves

BatchService BatchGateway Methods: send(batch) Methods: Events: executeBatch() RESULT FAULT

ActionScript /MXML Flex Remoting Unraveling AutoSyncUnravelling AutoSync

Java Server Push to a Flex messaging desnaon: hp://localhost:8080/BlazeMessagingDemo/stareed.jsp hp://localhost:8080/BlazeMessagingDemo/stopfeed.jsp

MessageBroker msgBroker = MessageBroker.getMessageBroker(null); AsyncMessage msg = new AsyncMessage(); msg.setDestination("feed"); // target destination msg.setClientId(UUIDUtils.createUUID(false)); msg.setMessageId(UUIDUtils.createUUID(false)); msg.setTimestamp(System.currentTimeMillis()); msg.setBody(“Pushed Message" ); // arbitrary message msgBroker.routeMessageToService(msg, null); Clear Toolkit includes CDB

• Clear Data Builder ‐ formerly DaoFlex: hp://sourceforge.net/projects/cleartoolkit (Downloads, documentaon, license)

• CVS – Host: cleartoolkit.cvs.sourceforge.net – Repository: /cvsroot/cleartoolkit – Protocol: pserver – User: anonymous CDB SQL Branch: Complete Automation

Written Abstract Java class: method by developer signatures annotated with SQL

CDB Pre-built + custom DAO Java DTO CDB Assembler Config files Templates Test MXML

Java MXML, Generated Implementaon AconScript by CDB classes classes

Deployed by CDB JAR with JAR with abstract implementaon classes classes CDB SQL Mode package com.theriabook.datasource; /** * @daoflex:webservice * pool=jdbc/theriabook */ public abstract class Employee { /** * @daoflex:sql * sql= select * from employee where • start_date < :startDate > * transferType=EmployeeDTO[] * keyColumns=emp_id */ public abstract List getEmployees(Date startDate); }

• Code generaon soluon that completely automates manual Java coding for CRUD (create, retrieve, update, delete) tasks • Integrates with Eclipse or works standalone as Ant task • Goes all the way from simple annotated Java class to deployed JARs in the WEB‐INF/lib • Generates all required Java, AconScript, MXML, XML CDB Java Mode: Partial Automation

Written Annotated Java DTO + Java DAO by developer implemenng fill() and sync() methods

CDB Pre-built + custom CDB Assembler Test MXML Config files Templates

MXML, Generated AconScript by CDB classes

Deployed by CDB JAR with JAR with abstract implementaon classes classes Farata DTO2Fx Plugin http://sourceforge.net/projects/cleartoolkit/files/ browse for DTO2Fx.pdf package com.farata.test; package com.farata.test { import com.farata.dto2fx.annotaons.FXClass; public class _EmployeeDTO extends flash.events.EventDispatcher import com.farata.dto2fx.annotaons.FXIgnore; implements mx.core.IPropertyChangeNofier, mx.core.IUID { @FXClass public class EmployeeDTO { @FXClass public firstName; public class EmployeeDTO { private String sex; private var _firstName:String; . . . private var _sex:String; private String uid; . . .

public long getSex() { private var uid:String; [Bindable(event="propertyChange")] return sex; public funcon get firstName():String { } return _firstName; public void setSex(String sex) { } this.sex = sex; • > public funcon set firstName(value:String):void { } const oldValue:String = this._firstName; if (oldValue != value) {

this._firstName= value; @FXIgnore dispatchUpdateEvent(“firstName", oldValue, value); public String getUid() { } return uid; } } [Bindable(event="propertyChange")] public funcon get sex():String { @FXIgnore return _sex; public void setUid(String uid) { } this.uid = uid; public funcon set sex(value:String):void { } const oldValue:String = this._sex; } if (oldValue != value) { this._sex = value; dispatchUpdateEvent("sex", oldValue, value); } } Staffing Flex Projects Roles in Flex Projects

• Web Designers • Flex GUI developers • Flex Component developers • Flex architect Convince me that I need to hire all those specialists Flex Architect’s Responsibilies • Design the enre applicaon structure by deciding on how many modules and libraries should be used. • Select frameworks, component libraries and ulies • Decide on communicaon protocols to be used for communicaon with the server er • Enhance the applicaon protocols if need be • Arrange for the performance and stress tests to ensure that the applicaon is loaded as fast as possible even if the users are sing at the slower Internet connecon • Deal with on applicaon security issues, authencaon/authorizaon • Act as a technical lead providing guidance to developers. • Communicate with the server side developers, decide on protocols and data formats. • Acvely work with managers on project plans • Promote use of coding best pracces and perform code reviews • Conduct technical job interviews Comparing Flex Frameworks Selected MVC Frameworks • Cairngorm by Adobe Consulng • Mate by ASFusion • PureMVC by Cliff Hall • Parsley by Spicefactory

import mx.rpc.events.ResultEvent;

import mx.collecons.ArrayCollecon; 1

Sue //data provider for the list is an ArrayCollecon a.k.a. model Hove [Bindable] [email protected] private var employees: ArrayCollecon=new ArrayCollecon; 01/07/2006

… private funcon employeeDataHandler(event:ResultEvent):void{ employees=event.result.employees.employee; } // format the names to display last and first names in the List public funcon fullName( empItem : Object ) : String { return empItem.lastname + ", " + empItem.firstname; } ]]> Displaying a list of Employees with Flex ( no other frameworks) Cairngorm Sample dataflow Cairngorm: Pros and Cons.

Pros: ‐ It’s a popular framework‐ many Flex developers know it ‐ Allows to separate responsibilies of developers ‐ Lowers the requirements to the skill‐set of developers

Cons: ‐ Requires developers write lots of addional classes, which adds to project meline ‐ Built on global singletons, which complicates modularizaon ‐ Forces you to use only binding for updang views ‐ Allows only one‐to‐one mapping between events and commands ‐ Having several singletones leads to ght object coupling Mate Sample dataflow Mate: Pros and Cons.

Pros: ‐ Mate is non‐intrusive – Mate‐specific code can be encapsulated in a handful of objects. ‐ It’s MXML based and allows you to keep using Flex event model ‐ promotes lose coupling between components by implemenng Dependency Injecon ‐ Well documented

Cons: ‐ It hasn’t been released yet (currently in Alpha) ‐ Doesn’t support working with Data Management Services offered by LCDS PureMVC Sample dataflow PureMVC: Pros and Cons.

Pros: ‐ It’s well documented ‐ It’s available for developers that want to use AconScript only (i.e. Flash )

Cons: ‐ It’s not a framework wrien for Flex hence does use features offered by MXML ‐ Doesn’t use standard Flex events ‐ Has too many layers, which are ghtly coupled ‐ Requires staffing projects with more senior developers ‐ Developers have to write lots of addional classes, which adds to project meline ‐ It’s built on several singletons, and applicaon code becomes cluered by making mulple calls to them. Parsley Diet: Metadata Instead of Diagrams To wire component to Parsley: To promote event to Parsley‐handling: [ManagedEvents("companySeleconChange")]

To declare a method as message‐handler: [MessageHandler(selector="companySeleconChange")] public funcon onCompanySeleconChange(event:CompanyEvent):void { . . .}

To inject property (by type) from all available Contexts: [Inject] [Bindable] public var companies:DataCollecon;

To register a “Contex”:

To declare a Context:

This message will be sent to the specified desnaon selected with the Logging Manager. If a user calls producon support complaining about some unexpected behavior, ask her to press Ctrl+Shi+Backspace – the logging manager will pop‐up: Logging with Log4Fx – sample output

You can set the output desnaon as RemoteLogging to watch the log info from any computer connected to the Internet Occasionally Connected AIR applicaons and PDF Generaon on the Client Adobe Integrated Runme (AIR)

AIR is a step toward providing a full plaorm for desktop applicaon development.

AIR offers development and predictable runme environment for AJAX and Flex developers.

To run AIR applicaons, the user’s computer must have AIR runme installed (about 15MB): hp://get.adobe.com/air . AIR is cool because 1. AIR supports I/O operaons with user’s file system 2. AIR allows you to sign and version applicaons 3. Updater controls proper upgrades of the apps 4. AIR comes with a local database SQLite to keep the data (in clear or encrypted mode) on the user’s PC 5. AIR applicaons can monitor network connecons 6. You can run AIR applicaons when disconnected 7. AIR has beer than Flex support of HTML AIR 1.5 is so cool because not

1. AIR can’t make calls to user’s OS 2. AIR can’t launch non‐AIR applicaons 3. AIR can’t directly access ports on user’s PC 4. Adobe doesn’t offer data synchronizaon support for apps that use BlazeDS 5. AIR doesn’t allow PDF Generaon on the client

Farata Systems fixed the items 4 and 5 AIR 2.0 is cool because • AIR 2.0 introduced significant improvements that received a warm welcome in the developers community, and some of them are listed here: • It can launch and communicate with a nave (non‐AIR) applicaons • It lowers CPU and memory consumpon • Support for the detecon of mass storage devices • It knows how to open files with default programs • Microso access API gives you access to uncompressed microphone data • It introduces mul‐touch funconality • Introducon UDP sockets is a great improvement for such real me applicaons as online games or voice over IP. • Global error handling guarantees to catch all unhandled errors • The sizes of the run‐me installers are smaller that in AIR 1.5. PharmaSales Applicaon

Every day a dispatcher of Acme Pharma Inc. schedules visits for salesman stored in the corporate database. PharmaSales Applicaon

Every morning a salesman starts PharmaSales AIR applicaon, which connects to the corporate database (MySQL) and automacally into a local database (SQLite) that exists on salesman’s laptop. Architecture of Pharma Sales

Client Server

Adobe Air Java Servlet Container Applicaon

Clear.swc

Adobe BlazeDS Corporate DBMS

SQLite DBMS Uses of local SQLite cache

• Create an independent desktop applicaon with its own local database.

• Allow the AIR applicaon to remain operaonal even when there is no network connecon. Sync the data with the central database when connecon is available. • Offload large chunks of intermediate applicaon data to lower memory ulizaon. Liz can see her visits for today

Liz doesn’t know that her visits were saved in the local database SQLite.

Liz doesn’t give a damn! She just knows it’s safe to disconnect and hit the road. Liz visits a medical office

She enters the comments about this visit… Liz saves the visit notes locally

Please note, we are disconnected. SQLite Manager’s data view

Local DB is not a copy of the central DB. Only the query results (DTOs) are stored in the local cache. Liz came home late…

She inserted the network cable in her notebook and started the PharmaSales applicaon

Liz is a lile drunk .She can barely see the buon Sync. Liz clicks on it and falls asleep… Clear Toolkit is cool because

It supports the data sync between the local SQLite database with BlazeDS and LCDS. If the local data has been changed in a disconnected mode, the changes can be sent to the central DBMS when connected.

This is done by the class OfflineDataCollecon that comes with clear.swc, a library of Flex components from open source Clear Toolkit hps://sourceforge.net/projects/cleartoolkit/. It’s nice to have a map handy… …Even if you are disconnected Why prinng into PDF?

Flash Player prinng: start a single‐threaded print job and add to it dynamically created pages

Flash Player and AIR runme require that the interval between the following commands shouldn’t be more than 15 seconds:

PrintJob.start() and the first PrintJob.addPage() PrintJob.addPage() and the next PrintJob.addPage() PrintJob.addPage() and PrintJob.send()

Otherwise – runme excepons. PDF and XDP

PDF stands for Portable Document Format. It was originally created by Adobe but in July of 2008 became an open standard

XDP (XML Data Package) enables storage of PDF content, forms, and data inside the forms and, of course, processes it as XML.

XDP is not supported by older versions of Acrobat Reader. PDF Generaon

1. Use LiveCycle Designer and create

2. Use Flex for UI integrated with LiveCycle forms on the server

3. Send bitmaps from Flex to LCDS

4. Perform PDF generaon on the client with Clear Toolkit components or ClearBI PDF Generaon from bitmaps 1. A client may send a Bytearray (a bitmap) object to the server private funcon generatePDF():void { var snapshot:ImageSnapshot = ImageSnapshot.captureImage(balanceSheet); balanceSheetImage = ImageSnapshot.encodeImageAsBase64(snapshot);

snapshot = ImageSnapshot.captureImage(earnings); earningsImage = ImageSnapshot.encodeImageAsBase64(snapshot); }

2. On the server, you create a Java class that merges the bitmap with an XFA form

// define a string with a link to the XFA template String source = FlexContext.getServletContext().getRealPath(”/pdfgen/company.xfa”); XFAHelper helper = new XFAHelper(); helper.open(source);

// Import XFA dataset : dataset is the XML constructed in your Flex applicaon. // dataset is a org.w3c.dom.Document helper.importDataset(dataset);

// Save new PDF as a byte array in the current session byte[] bytes = helper.saveToByteArray(); PDF Generaon on the client 1. Open source library AlivePDF (hp://alivepdf.org/)

2. Flex UI components from Clear Toolkit library (hp:// sourceforge.net/projects/cleartoolkit ), which can expose their state in an XDP format to be used for generaon PDF.

3. Open Source library purePDF is a port to AconScript of popular Java tool iText: hp://bit.ly/bQw5x6

Starng from Flash Player 10, the AS class FileReference allows you to save files locally. Its funcon save() opens the popup window allowing the user to specify the file name to save the data in. In our example, this allows to eliminate the need of a roundtrip to the server that does nothing but bouncing this array of bytes. Keep in mind though, that aer saving the PDF this way, the user will need to do an extra step to open the file with Acrobat Reader or any other program. Prinng with AlivePDF var p:PDF = new PDF(Orientaon.PORTRAIT, Unit.MM, Size.A4); p.addPage(); p.setFont(FontFamily.ARIAL, Style.NORMAL, 12); p.addText("10x10", 10, 10); p.addText("100x100", 100, 100); p.addMulCell(50, 8, "Hello World2");

savePdf(p, "hw.pdf"); }

private funcon savePdf(p:PDF, fileName:String):void{

var ba:ByteArray = p.save(Method.LOCAL); var fs:FileStream = new FileStream(); var f:File = File.desktopDirectory.resolvePath(fileName); fs.open(f, FileMode.WRITE); try{ fs.writeBytes(ba); } catch (e:*){} //… AlivePDF does a good job creang objects and assembling them into pages, which are then converted into a PDF format.

But it sll requires you to prepare (in addion to the screen version) a second copy of the UI to be printed. It’s not what‐you‐ see‐is‐what‐you‐get (WYSIWYG) programming.

This process is a manual allocaon and measurements of each object’s in the PDF to be.

We don’t like to manually write the code specifying styles and measurements.

We prefer components and containers that can present themselves as XDP objects. Prinng into a local pdf file Generated PDF with header and footer ClearBI Reference Applicaon ClearBI Report Designer Troubleshoong

Tracking your applicaon’s HTTP traffic real‐me is important. for Firefox is a handy tool: hp://geirebug.com

For tracing AMF calls use either Charles: hp://www.charlesproxy.com or Service Capture: hp://www.kevinlangdon.com/serviceCapture

Charles is an HTTP proxy and monitor that allows a developer to view the HTTP traffic between a and the Internet.

Charles’ ability to simulate modem speeds by throling your bandwidth and introducing latency is invaluable.

Web Developer Add‐on to Firefox: hps://addons.mozilla.org/en‐US/firefox/addon/60 Tesng Flex RIA The sooner you start tesng your applicaon, the shorter the development cycle will be.

Because of dynamic nature of AconScript, Flex applicaons have to be tested more thoroughly than Java ones.

Types of tesng:

•Unit and Integraon Tesng

•Funconal Tesng

•Load Tesng Unit Tesng Unit tesng is performed by a developer and is targeted at small pieces of code, for example, to ensure that if you call a funcon with parcular arguments, it’ll return the expected result.

Test‐driven development (TDD): write test code first, and then the applicaon code, for example,

Create a class MortgageCalculator and the class TestMortgageCalculator that will test its funconality. Write a test that funcon that will assert that the monthly payment on a mortgage is properly calculated.

FlexUnit 4 is a unit tesng framework for Flex. Flash Builder 4 allows automac creaon of test cases (see menu New | TestCase Class ). Just enter the name of the class to test and Flash Builder will generate a test applicaon and a test case class in a separate package. For each method of your class, i.e. calculateMonthlyPayment(), it’ll generate a test method, i.e. testCalculateMonthlyPayment(). You just need to implement it. public funcon testCalculateMonthlyPayment(){ //A $200K mortgage at 7% for 30 years should have a monthly payment of $1199.10 Assert.assertEquals(MortgageCalculator.calculateMonthlyPayment (200000, 7,30 ),1199.1 ); } Unit and Integraon Tesng (Cont.) FlexMonkey is an open source tool from Gorilla Logic. hp://code.google.com/p/ flexmonkey/

It’s a unit and funconal tesng framework for Flex applicaons, which also and AIR automates tesng of Flex UI funconality.

FlexMonkey can record and play back UI interacons. This screenshots was taken aer entering the name of the manager and selecng a date.

It also generates test script in AconScript. Funconal Tesng

Funconal tesng (a.k.a. black‐box, QA, or acceptance tesng) is aimed to find out if the applicaon properly implemented business logic.

For example, if the user clicks on a row in the customers data grid, the program should display a form view with specific details about the selected customer.

QuickTest Professional (QTP) by HP (formerly Mercury). During the recording phase, QTP creates a script in VBScript language. The checkpoints included in the script are used for comparison of the current with expected values.

FlexMonkey 1.0 supports funconal tesng for Flex and AIR applicaons Load Tesng

Response me of your applicaon should be well defined in the Service Level Agreement (SLA), which should state what’s acceptable from the users perspecve.

For example, the SLA can include a clause stang that the inial download of your applicaon shouldn’t take longer than 30 seconds for the users with DSL connecon (500kbps).

Neoload is a commercial stress tesng tool: hp://neotys.com/

WebLoad 8.3 is a commercial stress tesng soware: hp://www.radview.com/. It includes reporng and allows to enter SLA into the tests. Load Tests with NeoLoad Connuous Integraon

The term connuous integraon has been introduced by Marn Fowler and Mahew Foemmel. It recommends creang scripts and running automated builds of the applicaon at least once a day.

We are using an open source framework called CruiseControl for establishing a connuous build process: hp://cruisecontrol.sourceforge.net/.

Report on the results of each build are being automacally emailed to producon support group.

Hudson is yet another popular open source CI server: hp://hudson‐ci.org/ Selected Performance Topics

Flex app can be slow, fast or perceived as fast.

Flex preloaders can quickly display a light‐weight page.

Design any app as if it’s a portal with a light shell applicaon and a number of modules loaded on as needed basis Preparing for performance challenges

1. Review all resources (namely images, sound, and movies ) and decide what to embed and what to load. Keep embedded images in a separate FB project and load it as RSL

2. Separate skins and style sheets into modules. Precompile CSS into a SWF and load it with StyleManager

3.Make the first page light. If a Web designer proposes a dashboard to be the first page ‐ fight. Preparing for performance challenges, cont. 4. Request a wrien SLA on the download speed 5. Monitor the performance using soware (Charles) or hardware (a portable Appliance Mini Maxwell) 6. Preloader should bring a small (up to 50Kb) SWF wrien in Flash. This can be a logon, copyright, or a simple menu page, i.e. hps://connectnow.acrobat.com/ Before the Applicaon is ready

• The Applicaon object instanates. • Its property Applicaon.systemManager inializes. Preloader is created. • The Applicaon dispatches the FlexEvent.PREINITIALIZE event at the beginning of the inializaon process. • Flash Player calls the method createChildren() on the Applicaon. At this point each of the applicaon’s components is constructed, and each component’s createChildren() is also called. • The Applicaon dispatches the FlexEvent.INITIALIZE event, which indicates that all applicaon’s components have been inialized. • Flash Player dispatches FlexEvent.CREATION_COMPLETE • Flash Player adds the Applicaon object to the display list and the Preloader object gets removed. • Flash Player dispatches the FlexEvent.APPLICATION_COMPLETE event. Dealing with Memory Leaks

• Help GC (reference count and mark and sweep) • Use FB Profiler • Each addChild() must have removeChild() • addListener(),weak references, removeListener() • Closures myBuon.addEventListener(“click”, funcon (evt:MouseEvent){//do something}); • LocalConnecon trick:

var conn1:LocalConnecon = new localConnecon(); var conn2:LocalConnecon = new localConnecon(); conn1.connect(“MyConnecon”); conn2.connect(“MyConnecon”); Performance consideraons

• Startup me • To reduce startup me: • Use preloaders to quickly display either funconal elements (logon, etc) or some business‐related news. • Design with modularizaon and opmizaon of .swf files (remove debug and metadata informaon). • Use RSLs, signed framework libraries. • Minimize inially displayed UI. • Externalize (don’t embed) large images and unnecessary resources. • Process large images to make them smaller for the Web. Performance consideraons (cont.) • UI performance • Minimize usage of containers within containers (especially inside datagrids). Most of the UI performance issues are derived from containers measurement and layouts code. • Defer object creaon and inializaon (don’t do it in constructors). If you postpone creaon of UI controls up to the moment they become visible, you’ll have beer performance. If you do not update UI every me one of the properes changes but process them together (commitProperes()) you most likely to execute common code secons responsible for rendering once instead of mulple mes. • For some containers, use creaonPolicy in queued for perceived inializaon performance. • Provide adapve user controlled duraon of effects. Although nice cinematographic effects are fine during applicaon introducon, their ming and enablement should be controlled by users. • Minimize update of CSS in the run‐me. If you need to set style based on data, do it early, preferably in inializaon stage of the control and not in the creaonComplete event as it minimizes number of lookups. • Validate performance of data bound controls (such as List based controls) for scrolling and manipulaon (sorng, filtering, etc.) early in development and with maximum data sets. Do not use the Flex Repeater component with sizable data sets. Performance consideraons (cont.) • I/O Performance • Use AMF rather than WebServices and XML based protocols, especially for large (over 1KB) result sets. • Use strong data types with AMF on both sides for the best performance and memory usage. • Use streaming for real‐me informaon. If you have choice, select them in the following order: RTMP, AMF streaming, long polling. • Use lazy‐loading of data, especially with hierarchical data sets. • Try to opmize a legacy data feed; compress it on proxy server at least, provide an AMF wrapper at best. Performance consideraons (cont.) • Memory ulizaon

• Use strongly typed variables whenever possible, especially when you have large number of instances. • Avoid using XML format. • Provide usage‐based classes for non‐embedded resources. For example, when you build a photo album applicaon, you do want to cache more then screen full of images so scrolling becomes faster without reloading already scrolled images. The amount of ulized memory and common sense, however, should prevent from keeping all images loaded. • Avoid unnecessary bindings (like binding used for inializaon) as they produce tons of generated code and live objects. Provide inializaon through your code when it is needed and has minimal performance impact. • Idenfy and minimize memory leaks using Flash Builder profiler. Performance consideraons (cont.) • Code execuon performance

• For beer performance you can make your code JIT compliant by • Using strong data types • Using local variables to opmize data access • Keeping code out of inializaon rounes and constructors • For applicaons working with large amount of data consider using Vector data type (Flash Player 10 and above) over Array. • Binding slows startup as they require inializaon of supporng classes; keep it minimal. Contact info and useful links Email: [email protected]

Web site: hp://www.faratasystems.com

Flex Blog: hp://flexblog.faratasystems.com

Clear Toolkit Framework: hp://sourceforge.net/projects/cleartoolkit/

O’Reilly Book “Enterprise Development with Flex” (rough cuts): hp://my.safaribooksonline.com/9780596801465

Code samples: can be downloaded at hp://www.myflex.org/presentaons/fms/part1.zip hp://www.myflex.org/presentaons/fms/part2.zip

This presentaon’s slide deck is available at hp://www.myflex.org/presentaons/fms/slides.pdf