Title: Cairngorm krn grm Demystified
1Cairngorm (kârn gôrm ) Demystified(?)
- AFFUG March 2007
- Scott Talsma
- CTO, echoeleven
2Goals
- How to say it?
- Why should I use it?
- What is it?
- See some code
3Assumptions
- Components
- Events and event handling (click, change, etc.)
- RemoteObjects (calling, handling results)
- ltmxScript /gt, importing classes, etc.
4Pronunciation
- Cairngorm (kârn gôrm )
- n. yellowish-brown variety of quartz, especially
found in Scottish Cairngorm mountain.
5Why use it?
- if you don't get why you would need to use
something like Cairngorm, then you probably
aren't building applications that merit using it
anway
6Why use it?
- Cairngorm is not intended as something that we
expect people to pick up the same time they are
getting to grip with Flex. - Multiple developers working on the project, and
run the risk of them all solving the same problem
in multiple different ways
7Why use it?
- Unified approach to problems
- Inject complex functionality in a well understood
manner - promote, enable and encourage reuse (business
objects, business services, etc.)
8What is it?
- .swc file that gets compiled into app
- Collection of classes/interfaces against which we
can compile
9What is it?
- elegant collaboration and partitioning of design
responsibilities - "microarchitecture"
- provide structure and skeleton in a generic
fashion - A standard way of doing building a Flex app.
10Diagram
- http//www.cairngormdocs.org/cairngormDiagram/cair
ngorm2_rpc.swf
11Breaking it down
- Model
- View
- Controller ServiceLocator
- Application Tier (server-side)
12Model
- All client state data
- Anything retrieved from server
- Implements ModelLocator Cairngorm interface
- From the Cairngorm Docs
- The model locator in an application is a
singleton that the application uses to store the
client side model. - Summary Model is a Singleton containing data.
13Example
package com.echoeleven.model import
com.adobe.cairngorm.model.ModelLocator Bindab
le public class ApplicationModel implements
ModelLocator public var
useridString public var usernameString pub
lic var passwordString public var
configObject function ApplicationModel()
init() public function
init()void userid "" username
"" password "" config new
Object() config.userService
"components.UserService"
14View
- UI
- .mxml files w/controls (text fields, combobox,
datagrid, etc.) - All data is pulled from model via a binding
15Sample View
lt?xml version"1.0" encoding"utf-8"?gt ltmxVBox
xmlnsmx"http//www.adobe.com/2006/mxml"
creationComplete"updateButtonStatus( event
)"gt ltmxScriptgt lt!CDATA Bindable private
var appDataApplicationModel ApplicationModel.ge
tInstance() gt lt/mxScriptgt ltmxFormgt
ltmxFormHeading label"Login"/gt ltmxFormItem
label"User name"gt ltmxTextInput id"userName"
change"dataChange( event )" text"appData.userna
me" /gt lt/mxFormItemgt ltmxFormItem
label"Password"gt ltmxTextInput
displayAsPassword"true" id"password"
change"dataChange( event )" text"appData.passwo
rd" /gt lt/mxFormItemgt ltmxFormItemgt ltmxHB
ox width"100"gt ltmxButton id"loginBtn"
label"Login" click"login( event
)"/gt ltmxButton id"resetBtn" label"Reset"
click"reset( event )"/gt lt/mxHBoxgt lt/mxForm
Itemgt lt/mxFormgt lt/mxVBoxgt
16Controller
- Allows communication between tiers of application
via - Events
- extend class
- com.adobe.cairngorm.control.CairngormEvent
- Commands
- implement interfaces
- com.adobe.cairngorm.commands.Command
- com.adobe.cairngorm.business.Responder (optional)
- Tie both together in Controller class
17Events
- Events classes usually just a
- Collection of properties
- Constructor with params to populate those
properties - Used to pass data between layers of an application
18Event Example
- package com.echoeleven.controller.event
-
- import com.adobe.cairngorm.control.CairngormEvent
- import com.echoeleven.controller.ApplicationContr
oller - public class LoginEvent extends CairngormEvent
-
- public var usernameString
- public var passwordString
-
- public function LoginEvent(usernameString,
passwordString) - super(ApplicationController.EVENT_LOGIN)
-
- this.username username
- this.password password
-
-
19Command
- Service to Worker command pattern
- Must implement the Cairngorm Command interface
- If receiving data from server (e.g.
RemoteObject), should also implement Responder
Interface - Command class must implement execute() method
- execute() usually takes an event argument as a
parameter
20Command Example
- package com.echoeleven.controller.command
-
- import com.echoeleven.model.ApplicationModel
- import com.echoeleven.controller.event.LoginDataC
hangeEvent -
- public class LoginDataChangeCommand implements
Command -
- public function execute(eventParamCairngormEven
t)void -
- var eventLoginDataChangeEvent eventParam as
LoginDataChangeEvent -
- var appDataApplicationModel
ApplicationModel.getInstance() - appData.username event.username
- appData.password event.password
-
-
21Controller
- Tie Event and Command classes together in
Controller class constructor - addCommand( ApplicationController.EVENT_LOGIN,
LoginCommand ) - Controller listens for event
- When event is dispatched, commands execute()
method called (by controller)
22ControllerBig Picture
- View event triggered (e.g. click event)
- Caught by private method in view (mxml file)
- View method creates instance of event (extending
CairngormEvent) - View method dispatches that event via
CairngormEventDispatcher - Controller catches CairngormEvent and executes
associated Cairngorm Command - private function btnClick( eventEvent )void
- var evtLoginEvent new LoginEvent(userName.text
, password.text) - CairngormEventDispatcher.getInstance().dispatchEv
ent( evt ) -
23Example
- Create LoginDataChangeEvent class
- Create LoginDataChangeCommand class
- Connect Event to Command in controller
- Catch the TextField.change event, and call local
function dataChange() - Create instance of LoginDataChangeEvent and
dispatch it - LoginDataChangeCommand.execute() automatically
called - execute() method modifies Model
- Change to model reflected in View through binding
24Service Locator
- Singleton
- Abstracts data communication layer
- Defines which protocol (http, SOAP, AMF, etc.)
and which endpoint params (which service, which
channel, etc.)
ltcairngormServiceLocator xmlnsmx"http//ww
w.adobe.com/2006/mxml" xmlnscairngorm"com.a
dobe.cairngorm.business."gt ltmxRemoteObject i
d"userService" destination"ColdFusion" showBus
yCursor"true sourcecomponents.echoeleven.so
meCFC" result"event.token.resultHandler( event
)" fault"event.token.faultHandler( event
)"gt lt/mxRemoteObjectgt
lt/cairngormServiceLocatorgt
25Business Delegate
- Who should handle the results of a server
operation? - Avoids attaching result/error routines to data
services (e.g. RemoteObject) - Allows Command to call remote object method, and
handle the result and fault methods - Multiple instances may exist
26Business Delegate
- The Business Delegate typically fulfills its role
in collaboration with the Service Locator it
uses the Service Locator to locate and look up
remote services, such as web services, remote
Java objects, or HTTP services. Once located, the
Business Delegate invokes these services on
behalf of the class that has delegated
responsibility to it for business logic
invocation.
27Command Side of Delegate
- public class LoginCommand implements Command,
Responder -
- private var appDataApplicationModel
ApplicationModel.getInstance() - public function execute(eventParamCairngormEvent
)void -
- var eventLoginEvent eventParam as
LoginEvent - var delegateUserServiceDelegate new
UserServiceDelegate( this ) - delegate.authenticate( event.username,
event.password ) -
-
- public function onResult(eventnull)void
-
-
- public function onFault(eventnull)void
- DebugMessage.write(event.fault, "fault")
28Business Delegate
- public function UserServiceDelegate(
callingCommandcom.adobe.cairngorm.business.Respon
der ) - service ServiceLocator.getInstance().getService
("userService") - responder callingCommand
-
- public function authenticate( usernameString,
passwordString )void - var callObject service.authenticate(username,
password) - call.resultHandler responder.onResult
- call.faultHandler responder.onFault
29Hints
- Find a simple working example and use it as a
code base - Start with a small project
30References
- Labs.adobe.com
- http//cairngormdocs.org/
- Read Chapter 20 of Developing Rich Clients with
Macromedia Flex (http//www.theserverside.com/tt/
articles/content/Flex/Flex_Chapter20.pdf)