Introduction
I’ve been playing around with a stack of Flex/ActionScript and Java frameworks and finally came up with one that I’m really pleased with — since I’m reusing these terms throughout the series, please review the acronyms after each, as that’s how I’ll be referring to them in the tutorial:
- Flex
- Cairngorm (”CG”)
- Spring ActionScript (”SAS”), formerly Prana
- Tomcat (”TC”)
- WebORB (”WORB”) / BlazeDS (”BDS”)
- Spring, Server-side Java version
- Hibernate (”HB”)
- MySQL
To that, I’m planing on writing a series of tutorials where each one builds on the previous one. The final tutorial will cover: Flex + Cairngorm + Spring ActionScript + Tomcat + WebORB/BlazeDS + Spring Java + Spring Security + Hibernate + MySQL
- Part 1: Basic Flex + CG Application
- Part 2: Flex + CG + SAS
- Part 3: Flex + CG + SAS + Injecting Services into Business Delegates
- Part 4: Integrated Flex Project + Java Project with Tomcat
Tutorial Goal: Flex + Cairngorm
Build a foundational Flex + Cairngorm application that provides a solid application architecture so that we can easily add new functionality in later iterations and tutorials — this will probably be a bit slow for most experienced Flex developers, so feel free to jump to Part 2 that introduces the Spring ActionScript framework (”SAS”).
Assets:
Prerequisites & Assumptions
- Ability to create Flex and ActionScript classes with Flex Builder (”FB”). NOTE: I’m actually using Eclipse WTP with the Flex Builder Plugin so I can develop in both Java/J2EE and Flex projects in one IDE.
- Used or understand Cairngorm’s basic flow and how it all fits together. If you haven’t, I recommend looking at the Cairngorm Diagram for some reference.
- Understanding of OOP and basic Design Patterns.
What This Tutorial is Not
This particular tutorial is not focused on why I chose CG over one of the myriad other frameworks like Mate, PureMVC, Swiz, Bob’s New AS3 MVC-based Framework with some other obscure name, etc…I could have just as easily chosen PureMVC (”PMVC”), but since CG is more widely used and I want to keep things simple, we’re going with CG. Remember, this simply sets up the plumbing for later fun, so please leave the frameworks debate and why I chose CG for another time, or at least until another post where I actually want to argue the architectural issues that both frameworks possess.
Furthermore, I won’t go into great detail about CG’s complete ins and outs and/or best practices and extensions that my team at WASI currently uses in this first post…let’s just get a CG app up and running and then come back to that in a later, cleanup/best-practices post.
NOTE: Most of the code snippets are truncated to be concise and only highlight the lines of code that truly deserve the readers attention, so it’s highly recommended that readers download the accompanying project source files in order to follow along.
So without any further delay, let’s get at it.
Create a Flex Builder Project
NOTE: If you don’t feel like writing all this from scratch, just download my project.
Since this is part one in a n+ series of tuts, let’s create a new Flex project called “EmployeeManagementConsole1″. I originally created an address book application, but since I’ll be referencing Marcel Boucher’s Blog later in the series for his Flex + Hibernate (”HIB”) Employee Management Console, I’d like to be consistent…and why reinvent the wheel…thanks for the starting point bud.
Add Libraries and Dependencies
Next we’ll need to add the necessary libraries and dependencies to the project as SWCs and AS files; for now, we’ll just need:
Cairngorm 2.2.1 (non-enterprise edition) — Download the ZIP, extract it, and import the Cairngorm.swc into the libs folder of your Flex Builder project.
Create the Flex View
Again, since we want to keep this simple, we’re going to reuse the application UI from Marcel Boucher’s Blog, so we won’t spend any great amount of detail reviewing it. Create 2 Panels and put a DataGrid (”DG”) in the left one with 3 columns in with header names : Employee ID, First Name, Last Name. In the second Panel, create a Form with 2 FormItems corresponding with the First and Last Name fields we just added to the DG. Finally, below the DG put a Button with the label “Refresh List.” It should look something like this:

Employee Management Console UI
Hook Up Cairngorm & Get Some Data
First, create a ModelLocator and give it a public property of employeeList of type ArrayCollection for our DG view to bind to: CairngormModelLocator.as
/**
* The CairngormModelLocator provides singleton access to all the
* model/business objects in the application.
*/
[Bindable] public class CairngormModelLocator implements ModelLocator
{
public var employeeList:ArrayCollection = new ArrayCollection();
...
}
Go ahead and create the necessary CG Event (”EVT”), Command (”CMD”), and Business Delegate (”BD”) to actually get us some data by implementing the get list of employees functionality — just make one small change to the BD — instead of calling it EmployeeDelegate, let’s call it EmployeeASDelegate, signifying that it’s returning hard-coded AS mock objects to your CMD; this will set us up to create different BDs for different data sets with SAS in the next couple tutorials. Notice the use of trace() statements as a primitive form of logging for this first iteration; again, we’ll add in real logging in a later tutorial. Your EVT, CMD, and BD should all look something like the following:
EmployeeEvent.as
package com.wasi.employeeconsole.events
{
import com.adobe.cairngorm.control.CairngormEvent;
public class EmployeeEvent extends CairngormEvent
{
/**
* The event type for getting all the employees.
*/
public static const GET_LIST:String = "getList";
/**
* Constructor.
*
* @param type The event type for the event.
*/
public function EmployeeEvent(type:String)
{
super(type, false, false);
trace("EmployeeEvent Constructor");
}
}
}
EmployeeCommand.as
package com.wasi.employeeconsole.commands
{
import com.adobe.cairngorm.commands.ICommand;
import com.adobe.cairngorm.control.CairngormEvent;
import com.wasi.employeeconsole.business.delegates.EmployeeASDelegate;
import mx.rpc.IResponder;
public class GetEmployeeListCommand implements ICommand, IResponder
{
private var delegate:EmployeeASDelegate;
public function GetEmployeeListCommand()
{
trace("GetEmployeeListCommand Consturctor");
this.delegate = new EmployeeASDelegate(this);
}
public function execute(event:CairngormEvent):void
{
trace("GetEmployeeListCommand execute");
this.delegate.getList();
}
public function result(data:Object):void
{
trace("GetEmployeeListCommand result");
}
public function fault(info:Object):void
{
trace("GetEmployeeListCommand fault");
}
}
}
EmployeeASDelegate.as
package com.wasi.employeeconsole.business.delegates
{
import flash.utils.setTimeout;
import mx.collections.ArrayCollection;
import mx.rpc.IResponder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
/**
* A hard-coded delegate that creates mock objects and sends them back
* to the correspnding command as if it had actually called a real asynchronous
* service.
*/
public class EmployeeASDelegate
{
/**
* RPC Responder, used as a reference back to the command that made the request.
*/
private var responder:IResponder;
/**
* Constructor.
*/
public function EmployeeASDelegate(responder:IResponder=null)
{
trace("EmployeeASDelegate Consturctor");
this.responder = responder;
}
/**
* Get the list of employees.
*/
public function getList():void
{
trace("EmployeeASDelegate getList");
// we'll fake an asynchronous service call with a slight delay
setTimeout(result, 1000, new ResultEvent(ResultEvent.RESULT));
}
/**
* Handles the successful service request.
*
* @param response Object The success event coming back from the asynchronous
* service call containing the data payload.
*/
public function result(resultEvent:ResultEvent):void
{
trace("EmployeeASDelegate result");
var response:ArrayCollection;
response = new ArrayCollection();
// pass the command the response object to do whatever it wants with it
this.responder.result(response);
}
/**
* Handle the failed request. Pass it on
* to the command that originally requested it.
*
* @param faultEvent The fault event coming back from the asynchronous
* service call containing the error message, etc.
*/
public function fault(faultEvent:FaultEvent):void
{
trace("EmployeeASDelegate fault");
this.responder.fault(faultEvent);
}
}
}
Don’t forget to add the EVT to CMD mapping in the FrontController (”FC”):
CairngormFrontController.as
/**
* Map all the events to commands.
*/
protected function addCommands():void
{
trace("CairngormFrontController addCommands");
this.addCommand(EmployeeEvent.GET_LIST, GetEmployeeListCommand);
}
After creating the plumbing with our CG classes, let’s add in a click handler method for the “Refresh List” button called “getList()” and implement it by calling the CG EmployeeEvent:
EmployeeManagementConsole1.MXML
private function getList(event:MouseEvent):void
{
trace("Application getList");
new EmployeeEvent(EmployeeEvent.GET_LIST).dispatch();
}
...
<mx:Button label="Refresh List" click="getList(event)"/>
Flex Builder Console
Test the application in Debug Mode and you should see something like the following in the Flex Builder console:
[SWF] Users:brianmriley:projects:spring-hibernate:workspaces:flex3:EmployeeManagementConsole1:bin-debug:EmployeeManagementConsole1.swf - 1,073,390 bytes after decompression
CairngormFrontController Constructor
CairngormFrontController addCommands
Application getList
EmployeeEvent Constructor
GetEmployeeListCommand Constructor
EmployeeASDelegate Constructor
GetEmployeeListCommand execute
EmployeeASDelegate getList
EmployeeASDelegate result
GetEmployeeListCommand result
Now that we know our CG application flow hooked up, let’s add some data and populate our list of employees DG in the view. We’ll start by creating a simple client-side representation of an Employee object, sometimes referred to as a model, domain, business, or value object. Since we’ll ultimately map this Employee AS object to a Java object, we’ll place it in the client-side model package. Give it three public properties: id, firstName, lastName:
EmployeeModel.as
package com.wasi.employeeconsole.models
{
public class EmployeeModel
{
public var id:int;
public var firstName:String;
public var lastName:String;
}
}
EmployeeASDelegate#result(resultEvent:ResultEvent)
Next we’ll use this object to create a list of employees in our mock-object AS BD — open up EmployeeASDelegate and create an ArrayCollection (”AC”) of Employee objects in it’s result() method like so:
public function result(resultEvent:ResultEvent):void
{
trace("EmployeeASDelegate result");
var response:ArrayCollection;
var employee:EmployeeModel;
response = new ArrayCollection();
employee = new EmployeeModel();
employee.id = 0;
employee.firstName = "Brian";
employee.lastName = "Riley";
response.addItem(employee);
employee = new EmployeeModel();
employee.id = 1;
employee.firstName = "Tim";
employee.lastName = "McGee";
response.addItem(employee);
employee = new EmployeeModel();
employee.id = 2;
employee.firstName = "Joe";
employee.lastName = "Seiter";
response.addItem(employee);
// pass the command the response object to do whatever it wants with it
this.responder.result(response);
}
GetEmployeeListCommand#result(data:Object)
Once our BD creates the data, it’ll pass it back to the CMD to actually set the data on the model, so we’ll need to make some modifications to the result() method in GetEmployeeListCommand:
public function result(data:Object):void
{
trace("GetEmployeeListCommand result");
var employeeList:ArrayCollection;
employeeList = data as ArrayCollection;
CairngormModelLocator.getInstance().employeeList = employeeList;
}
Bind Employee DG View to Model
Finally, let’s bind the DG to the list of employees in the model by means of MXML data binding:
<mx:DataGrid
id="dgrid"
dataProvider="{CairngormModelLocator.getInstance().employeeList}"
width="100%" height="411"
bottom="0" right="0">
<mx:columns>
<mx:DataGridColumn headerText="Employee ID" dataField="id"/>
<mx:DataGridColumn headerText="First Name" dataField="firstName"/>
<mx:DataGridColumn headerText="Last Name" dataField="lastName"/>
</mx:columns>
</mx:DataGrid>
When you test your application, you should see something like:

Employee Mgmt Console Populated with AS Mock Objects
At this point we have a basic Flex + CG app up and running…exciting, nah, not really. But we do have the bare-bones code base we’ll need to start having some real fun. Next, learn what SAS is and how to integrate it into this basic CG application.
References:
- My First Hibernate Enabled Flex Application - Marcel Boucher
#1 by Ryan - May 2nd, 2009 at 01:06
Awesome tutorial, Thanks!
I look forward to the next one.
#2 by jay - May 22nd, 2009 at 11:37
This is exactly what I needed. I have been trying to pick this up for a long time… The work you’ve done is SPOT ON for what I need. Thanks for sharing.
#3 by Venkat - February 8th, 2010 at 09:12
Grate effort..! Excellent hard work..! Keep posting on integrating RIA with J2EE and Open source technologies.. Thanks for helping to.. those who are struggling on server side..by this blog..
#4 by Naveen Bijalwan - June 23rd, 2010 at 07:40
excellent and simple post to to learn how , what and why of flex and java