Archive for May, 2009
Convert Plain-Old Flex Project to Java Server Based Project
Posted by brianr in eclipse, flex builder, java on May 28th, 2009
Ever start a project as a plain-old Flex project that doesn’t use a Java server and then later want to convert it? You’d think you could do this simply by examing the project’s server properties (Project -> Properties -> Flex Server) and adding a server…but no…you can’t…ehhh…not to fret, there’s still hope…don’t create a new project from scratch just yet and copy all your old projects files into your new project. We just need to modify a couple of the project’s .files and we’re good to go.
Modify the Project Property Files
Since we started our Flex project as a non-server based project, we’ll need to make some modifications to our .project, .actionScriptProperties, and .flexProperties files in order to convert the project to a server-based application. These files all exist under the root of the Flex Project’s directory — if you can’t see them, make sure you’re in either the Flex or Flex Debugging Perspective.
As a side note, under the covers we’re modifying the Flex Project’s Properties as if we right-clicked on the project and selected Properties.
NOTE: The following examples use a @@key@@ to indicate where you should substitute your own project, workspace, and server settings.
NOTE: This also assumes that you’re building your flex project to a directory in your Java project called flex — you don’t need to create it in WebContent on the Java side, as it’s generated by Flex Builder when you do a build or clean.
.actionScriptProperties
Open up .actionScriptProperties and locate the <compiler> node and add or change the following attributes to look like this:
- outputFolderLocation=”DOCUMENTS/@@JavaProjectName@@/WebContent/flex”
- rootURL=”http://@@Host@@:@@Port@@/@@JavaAppContext@@/flex”
Your .actionScriptProperties should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<actionScriptProperties
mainApplicationPath="@@MyFlexApp@@.mxml"
version="3">
<compiler
additionalCompilerArguments="-locale en_US
-use-network=false"
copyDependentFiles="true"
enableModuleDebug="true"
generateAccessible="false"
htmlExpressInstall="true"
htmlGenerate="true"
htmlHistoryManagement="true"
htmlPlayerVersion="9.0.124"
htmlPlayerVersionCheck="true"
outputFolderLocation=
"DOCUMENTS/@@JavaProjectName@@/WebContent/flex"
outputFolderPath="bin-debug"
rootURL="http://@@Host@@:@@Port@@/@@JavaAppContext@@/flex"
sourceFolderPath="src"
strict="true"
useApolloConfig="false"
verifyDigests="true"
warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="1">
<libraryPathEntry kind="4" path=""/>
<libraryPathEntry kind="1" linkType="1" path="libs"/>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="@@MyFlexApp@@.mxml"/>
</applications>
<modules/>
<buildCSSFiles/>
</actionScriptProperties>
.flexProperties
Open up .flexProperties and locate the <flexProperties> node and add or change the following attributes to look like this:
- flexServerType=”2″
- serverContextRoot=”/@@JavaAppContext@@”
- serverRoot=”${DOCUMENTS}/@@JavaProjectName@@/WebContent”
- serverRootURL=”http://@@Host@@:@@Port@@/@@JavaAppContext@@/”
Your .flexProperties should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<flexProperties
flexServerType="2"
serverContextRoot="/@@JavaAppContext@@"
serverRoot="${DOCUMENTS}/@@JavaProjectName@@/WebContent"
serverRootURL="http://@@Host@@:@@Port@@/@@JavaAppContext@@/"
toolCompile="true"
useServerFlexSDK="false"
version="1"/>
.project
Open up .project and locate the <projectDescription> node and add the node <linkedResources> after the <natures> node inside <projectDescription> — simply copy and paste the <linkedResources> node from my code snippet below; your .project file should look like this:
NOTE: You need to put the full, absolute path on your machine to your Java Web Project in place of the @@FULL_PATH@@ key I subsituted down below for the path on my machine.
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>EmployeeManagementConsole4</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.flexnature</nature>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
<linkedResources>
<link>
<name>bin-debug</name>
<type>2</type>
<location>
@@FULL_PATH@@/@@JavaProjectName@@/WebContent/flex
</location>
</link>
</linkedResources>
</projectDescription>
Check Flex Project Properties
Just to make sure we did everything correctly, let’s check the project properties by right-click on our Flex Project and selecting Properties -> Flex Build Path. It should look like this:
NOTE: The screen shots have my actual project, workspace, and server settings — these should help solidify the entire tutorial. They are from Part 4 of my Stack Tutorial Series.
- Main source folder: src
- Output folder: ${DOCUMENTS}/@@JavaProjectName@@/WebContent/flex
- Output folder URL: http://@@Host@@:@@Port@@/@@JavaAppContext@@/flex

Build Path Properties
Next let’s check the Flex Server Settings: Project Properties -> Flex Server:
- Root folder: ${DOCUMENTS}/@@JavaProjectName@@/WebContent
- Root URL: http://@@Host@@:@@Port@@/@@JavaAppContext@@/
- Context root: /@@JavaAppContext@@

Server Properties
Finished!
Flex + Cairngorm + Spring ActionScript + Tomcat + WebORB/BlazeDS + Spring Java + Hibernate + MySQL Tutorial Part 3
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
Part 3 in our series will build on our working knowledge of Spring ActionScript framework (”SAS”) and use Dependency Injection (”DI”) to add the services to our Business Delegates (”BD”) from Part 2.
Tutorial Goal: Inject Service Definitions into Business Delegates using Spring AS
Build upon the existing, foundational Flex + Cairngorm (”CG”) + SAS application and inject the desired services into our Business Delegate (”BD”) at runtime; we’ll continue working with the EmployeeXMLDelegate and inject the necessary HTTPservice and it’s properties as opposed to hardcoding them directly in the BD. After this tutorial you should know why and how to inject complex objects with 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 Part 1 of this tutorial and the Cairngorm Diagram for some reference.
- Basic understanding of Spring ActionScript and Dependency Injection. If you haven’t, I recommend looking at Part 2.
- Understanding of OOP and basic Design Patterns.
What This Tutorial is Not
There’s actually a set of extensions for SAS for both CG and PureMVC (”PMVC”), but since CG is more widely used and I want to keep things simple, this tutorial will focus on SAS + CG…so leave the frameworks debate and why I chose CG for this example for another time, or at least until another post where I actually want to argue the architectural issues that both frameworks possess. I’m also not going to focus on CG best-practices and extensions that WASI currently uses in this first post…let’s just get a SAS + 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.
Create a Flex Builder Project
If you don’t already have the project from Part 2 of this series, please download it and import it into Flex Builder (”FB”). Once in FB, copy and paste it into the same workspace as “EmployeeManagementConsole2″.
NOTE: If you don’t feel like writing all this from scratch, just download my project for Part 3.
Remove Hardcoded Service From EmployeeXMLDelegate
Open up EmployeeXMLDelegate and remove the class property httpService and it’s instantiation from the constructor. You’re BD’s constructor should now look like this:
public class EmployeeXMLDelegate extends AbstractDelegate implements IEmployeeDelegate
{
/**
* Constructor.
*/
public function EmployeeXMLDelegate(responder:IResponder=null)
{
trace("EmployeeXMLDelegate Constructor");
this.responder = responder;
}
...
}
Add HTTPService Service to AbstractDelegate
Open up AbstractDelegate and add the class property httpService. You’re BD’s constructor should now look like this:
public class AbstractDelegate
{
/**
* Reference to the XML / HTTP service the concrete delegate's will will use.
*/
public var httpService:HTTPService;
/**
* Constructor.
*/
public function AbstractDelegate()
{
trace("AbstractDelegate Constructor");
}
...
Notice that the httpService property was given the public modifier so that we can actually perform the DI — if it’s private or protected we can’t inject the HTTPService.
Modify the Spring ApplicationContext & Inject Services
Open the SAS Application Context (”SASAC”) file and locate the definition of the EmployeeXMLDelegate in the node <property name=”employeeDelegate”>; here’s where we’re looking to inject our HTTPService as a property of our BD. Notice the <property name=”httpService”> – it matches the exact property name of the httpService that we created in our AbstractDelegate and is where we’ll perform the DI. Just like the previously hardcoded version of our EmployeeXMLDelegate, we’ll set the following properties on our HTTPService:
- url = ../assets/xml/employee_list.xml
- resultFormat = e4x
- method = GET
You’re SASAC file should now look somewhat like the following snippet. Note: I removed extraneous nodes (ie the DelegateLocator, etc) from this snippet to be concise; please review the accompanying files available for download or see the the project from Part 2 for more details.
ApplicationContext.xml
<?xml version="1.0"?>
<objects>
...
<property name="employeeDelegate">
<object
class="com.wasi.employeeconsole.business.delegates.EmployeeXMLDelegate">
<property name="httpService">
<object class="mx.rpc.http.HTTPService">
<property
name="url"
value="../assets/xml/employee_list.xml" />
<property
name="resultFormat"
value="e4x" />
<property
name="method"
value="GET" />
</object>
</property>
</object>
</property>
...
</objects>
If you run the application now you’ll receive an error — this is because we haven’t included the HTTPService anywhere in the application and yet we’re trying to instantiate it at runtime. Since we ran into this issue in Part 2, I won’t go into details and you can read about it here — it refers to an issue when trying to inject a BD, but the issue is the same here with the HTTPService. What we need to do to fix the issue is to add a reference to the HTTPService in the ClassReferences.properties file like we did for the Delegates we injected.
ClassReferences.properties
Add the following to the ClassReferences file:
HTTPService = ClassReference("mx.rpc.http.HTTPService")
Compile & Run the Application
When you test your application you should see something like:

Employee Management Console with XML Business Delegate with HTTPService Injected
So now we’re back to a working application, but we’ve injected the HTTPService into our BD making it even more flexible from a configuration standpoint. If you’d like to explore this further try one of the following or both:
- Move the employee_list.xml file to somewhere else in the project or file system and simply change the url property of the httpService in the Spring AS ApplicationContext file — notice that you don’t have to recompile your Flex app either, as the SASAC file is loaded at runtime.
- Create a Java servlet (or .NET or PHP script) that generates the same XML structure as the employee_list.xml and change the url property of the httpService in the Spring AS ApplicationContext file to point to that dynamic XML service provider.
References:
- Dependency Injection in Flex Applications - Part 1 - Spring ActionScript and Cairngorm - Allen Manning
- IoC and the Dependency Injection Pattern in Flex - Eric Feminella
- Christophe Herreman’s Blog - Christophe Herreman
Content-Disposition Header May Prevent SWF Files From Playing
A Little Background Information for Context
I’m working with Xcelsius (”XC”) and Flex and I had to create a custom SWFLoader component to fix some issues with the out of the box (”OOTB”) SlideShow (”SS”) component in XC…without getting into too much detail, developers are currently using the SS component to load child SWFs into their parent SWFs (main XC Flex application) in order to make the application smaller; however, there’s a bug in the SS component that kills any previous and new LCDS connections created in either the parent or child SWFs — this is bad — so again, I decided to create my own SWFLoader component using the native, AS3 SWFloader class.
So I rolled my own custom SWFLoader component and voila, the LCDS connections and my loader worked as expected in my small PoC. I then ported my work over to our real application, and blam…no loading…nothing…nada…crap.
Naturally I had to locate the differences in my small PoC app and our real app and the one thing that struck me was that the real app was using an OOTB servlet by Business Objects to serve up the SWFs, whereas mine was just loading them by direct URLs. I then proceeded to create my seemingly simple test servlet to do the same. Here’s a simplified version of my Servlet without all the try/catches/error handling in order to be concise and just give you the idea:
SendSWF.java
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
ServletContext servletContext = getServletContext();
String fileName = (String) request.getParameter("file");
String mimetype = "application/x-shockwave-flash";
InputStream inputStream =
servletContext.getResourceAsStream("/XcelsiusFlex/" + fileName);
// set response headers
response.setContentType(mimetype);
response.addHeader("Content-Type", mimetype);
// KILLER - You bruised my head...
//response.addHeader("Content-Disposition",
"attachment; filename=" + (String) request.getParameter("file"));
int read = 0;
byte[] bytes = new byte[1024];
OutputStream outputStream = response.getOutputStream();
while((read = inputStream.read(bytes)) != -1)
{
outputStream.write(bytes, 0, read);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
Solution
Simple enough, right? Send the binary SWF back to my Flex client and make sure it has the proper header mimetype of:
application/x-shockwave-flash
But it didn’t work…I spent some time banging my head against my MacBook Pro and my partners until one them shot me this link. As you can see in my comments in the code, the line that killed me was adding the “Content-Type” of “attachment” to my header:
Content-Disposition: attachment
Apparently this is a new security feature of FP 10 that keeps a SWF file from playing. I simply commented it out and I was good to go.
Speacial Thanks…
To my buddy Greg DeMelo for pointing me to this link.
Flex + Cairngorm + Spring ActionScript + Tomcat + WebORB/BlazeDS + Spring Java + Hibernate + MySQL Tutorial Part 2
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
Part 2 in our series will focus on the introduction of the Spring ActionScript framework (”SAS”) to our existing Flex + Cairngorm (”CG”) application from Part 1.
Tutorial Goal: Flex + Cairngorm + Spring ActionScript
Build upon the existing, foundational Flex + CG application by adding SAS and injecting the desired CG Business Delegate (”BD”) at runtime; we’ll continue working with the mock-object EmployeeASDelegate, but also add a XML based BD called EmployeeXMLDelegate so we can choose our data provider at runtime. After this tutorial you should know why and how to use SAS with CG.
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 Part 1 of this tutorial and the Cairngorm Diagram for some reference.
- Understanding of OOP and basic Design Patterns.
- 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.
What This Tutorial is Not
There’s actually a set of extensions for SAS for both CG and PureMVC (”PMVC”), but since CG is more widely used and I want to keep things simple, this tutorial will focus on SAS + CG…so leave the frameworks debate and why I chose CG for this example for another time, or at least until another post where I actually want to argue the architectural issues that both frameworks possess. I’m also not going to focus on CG best-practices and extensions that WASI currently uses in this first post…let’s just get a SAS + CG app up and running and then come back to that in a later, cleanup/best-practices post.
So without any further delay, why Spring ActionScript (”SAS”)?
Ever create an app that relies on data from a DB that isn’t created or populated yet or try to work with services that don’t return any data? Sure you have, and so we all have our own frameworks and tricks for setting up mock objects in Business Delegates (”BD”) or simply consume XML until the real data is available. And that works great for awhile. You sit down with the server-side guys and flesh out your service API, the inputs and outputs, and hardcode your data in this temporary fashion until you hit the phase of your project called “integration.” What a lovely word. I’ve spent months of fun playing in the “integration phase” where you actually hook up your app to live data services, and you spend a good deal of time just ripping out scaffolding code, those hard-coded data calls, and…bleh…what a mess. So what if there was a way to simply interchange the BDs with their hard-coded mock objects, your stubbed service calls, or your XML through a simple config file? This my friends is the beauty of SAS and is why you’ll be hooked the moment you light up your first app with it.
The idea is to decouple configuration from implementation in patterns known as Inversion of Control (”IoC”) and Dependency Injection (”DI”) which are essentially the heart of Spring. Rather than go into too much detail about either of these patterns, please read Eric Feminellas great post on the topic. Furthermore, this is being very narrow minded and I’m leaving out a ton of other great things that Spring does, but this is the meat and potatoes of it and is what we’ll focus on in our first SAS tutorial.
A huge thanks to Christophe Herreman for porting this beauteous code-base over from Java to AS! SAS, formerly Prana, is now being considered as part of the original Java SpringSource Community’s code repository. Now that we have an idea of how SAS can help us, let’s see it in practice.
Create a Flex Builder Project
If you don’t already have the project from Part 1 of this series, please download it and import it into Flex Builder. Once in FB, copy and paste it into the same workspace as “EmployeeManagementConsole2″.
Add Libraries and Dependencies
Next we’ll need to add the necessary libraries and dependencies to the project as SWCs and AS files; mainly, we’ll need:
Spring ActionScript — Download the ZIP, extract it, and import the spring-actionscript.swc into the libs folder of your Flex Builder project.
Spring ActionScript Cairngorm Extensions — I couldn’t find the SWC for this, so I just downloaded the AS source by using Subversion (I’m currently using Subclipse, the Eclipse plug-in for SVN) and going here — https://src.springframework.org/svn/se-springactionscript-as/. Checkout the project “spring-actionscript-cairngorm” as a Flex Library Project. Once the project has completely checked out, disconnect it from SVN — if you are using Subclipse, just right-click on the project -> Team -> Disconnect (and delete all the SVN contents as well.) Finally, dig into the Flex Library Project you just created and locate the following directory: trunk/core/src/main/actionscript/org. Copy the root folder for the Cairngorm Exts sourcem org and all of it’s child directories and paste it into the src folder of your original EmployeeManagementConsole2 project.
Create Simple XML Data Source File
First we need to go ahead and create our XML data source, so let’s create a new XML file called “employee_list.xml” and save it in our project in a root folder called /assets/xml. We’ll model the XML directly after the EmployeeModel.as Model object (also like the AS mock-object we created in the AS BD), except that we’ll make the ID property an attribute in each employee node. We’ll also add “XML” as a suffix to each first name node value just so we can differentiate the data source later on when we start switching between the AS mock-object BD and our new XML BD. The finished XML should look something like this: employee_list.xml
<?xml version="1.0"?>
<employee id="0">
<firstName>BrianXML</firstName>
<lastName>Riley</lastName>
</employee>
<employee id="1">
<firstName>TimXML</firstName>
<lastName>McGee</lastName>
</employee>
<employee id="2">
<firstName>JoeXML</firstName>
<lastName>Seiter</lastName>
</employee>
</employeeList>
Create New XML Business Delegate
Since we already have the application running with the AS mock-object BD and we want the app to work with XML as well, we need to go ahead and create a new XML BD, EmployeeXMLDelegate.as. The key differences between this BD and the AS BD are the following:
- Has its own HTTPService object to make requests for the XML Employee List data.
- Calls the HTTPService in the getList() method.
- Deserializes the XML result into an ArrayCollection (”AC”) of EmployeeModel objects.
These changes all exist in the constructor, getList(), and result() methods.
EmployeeXMLDelegate.as
/**
* Constructor.
*/
public function EmployeeXMLDelegate(responder:IResponder=null)
{
trace("EmployeeXMLDelegate Constructor");
this.responder = responder;
// the serives are usually created in the ServiceLocator ("SL") in
// Cairngorm but since we're going to do away with the SL when we
// introduce Spring AS, we'll just hardcode the service here for now.
this.httpService = new HTTPService();
this.httpService.url = "../assets/xml/employee_list.xml";
this.httpService.resultFormat = "e4x";
}
/**
* Get the list of employees.
*/
public function getList():void
{
trace("EmployeeXMLDelegate getList");
var responder:mx.rpc.Responder;
var token:AsyncToken;
responder = new mx.rpc.Responder(result, fault);
token = this.httpService.send();
token.addResponder(responder);
}
/**
* 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("EmployeeXMLDelegate result");
var response:ArrayCollection;
var employee:EmployeeModel;
response = new ArrayCollection();
for each(var employeeXML:XML in resultEvent.result.employee)
{
employee = new EmployeeModel();
employee.id = employeeXML.@id;
employee.firstName = employeeXML.firstName;
employee.lastName = employeeXML.lastName;
response.addItem(employee);
}
// pass the command the response object to do whatever it wants with it
this.responder.result(response);
}
Now that we have our XML BD, let’s make some quick changes in the CMD to test it out. We’ll need to modify the reference to the BD in 2 places in the CMD:
- The delegate class property
- The instantiation of that delegate in the constructor
GetEmployeeListCommand.as
public class GetEmployeeListCommand implements ICommand, IResponder
{
private var delegate:EmployeeXMLDelegate;
public function GetEmployeeListCommand()
{
trace("GetEmployeeListCommand Constructor");
this.delegate = new EmployeeXMLDelegate(this);
}
...
}
When you test your application you should see something like:

Employee Management Console with XML Business Delegate
Add Spring ActionScript
Now we have 2 possible delegates to choose from, but we have to change the AS in the CMD, recompile, and then test to see the results…this sounds tedious and leaves us with the very problem we’re trying to avoid…time for SAS.
In order to see the changes occur at run-time we’ll need to create the Spring Application Context XML configuration file that defines which BD to inject at run-time and then modify the CMD in such a way that the exact type of BD is unknown at compile time…well not exactly an unknown type, but rather the underlying implementation. To achieve this feat we’ll leverage the almighty Interface in our CMDs. We’ll come back to the Application Context config file in a bit…
Create an Employee Delegate Interface
If you look at the AS and XML BDs, you’ll notice that they both have the same method signature for getList():
public function getList():void
We’ll use this as the point of commonality to create our interface, as they both need to actually get the list of employees for our application.
IEmployeeDelegate.as
/**
* Web App Solution Confidential Information
* Copyright 2009, Web App Solution, Inc.
*
* @author Brian Riley
* @date May, 4, 2009
*/
package com.wasi.employeeconsole.business.delegates
{
public interface IEmployeeDelegate
{
function getList():void
}
}
Next we’ll make each of our BDs implement the interface.
public class EmployeeASDelegate implements IEmployeeDelegate
public class EmployeeXMLDelegate implements IEmployeeDelegate
Spring ActionScript Application Context
The SAS Application Context (”SASAC”) is the XML configuration file that’s loaded at run-time by the Spring framework that defines all the concrete implementation objects you wish to use in your application — it essentially maps interface properties in classes (like our delegate:IEmployeeDelegate property in our GetEmployeeListCommand) to fully qualified, concrete objects. Let’s actually create our ApplicationContext and see how we can either inject our AS mock-object BD or our XML BD at run-time.
Create a new XML file called “ApplicationContext.xml” and save it in our project in a root folder called /assets/springactionscript/. Add the following code, which we’ll discuss in a moment:
ApplicationContext.xml
<?xml version="1.0"?>
<objects xmlns = "http://www.pranaframework.org/objects"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.pranaframework.org/objects http://www.pranaframework.org/schema/objects/prana-objects-0.5.xsd">
<!-- =================================================================== -->
<!-- This application context defines multiple test configurations, it
can be expanded to include a deployment configuration as well,
please see comments below.
1. Testing: ActionScript Mock Delegates
2. Testing: XML Mock Delegates (Will add in next revision)
3. Deployment: Remote Object Delegates (Will add in next tutorial)
To use a configuration, uncomment it and comment the one you don't
want to use. By default, the Mock Delegates configuration is used.
-->
<!-- =================================================================== -->
<!-- =================================================================== -->
<!-- 1. Testing: ActionScript Mock Delegates & Services -->
<!-- =================================================================== -->
<object
id="delegateLocator"
class="com.wasi.employeeconsole.business.delegates.DelegateLocator"
factory-method="getInstance">
<property name="employeeDelegate">
<object class="com.wasi.employeeconsole.business.delegates.EmployeeASDelegate" />
</property>
</object>
</objects>
Walking through the SASAC XML document from the top, you’ll notice the first-child node called <object>; each object tag defines a concrete object that we’ll inject into the application at run-time, as well as any properties (ie more concrete implementaitons) that we might inject into the object itself. The first object tag defines a new object that we haven’t discussed yet called the Delegate Locator (”DL”) (see Allen Manning’s Post on SAS + CGM for additional info on the DL in SAS), which is similar to the standard Service Locator (”SL”) object in CGM. However, instead of containing a registry of services like the SL, it contains a registry of BDs.
Taking a deeper look at DL object, you can see the fully qualified path to the DL object in it’s class attribute (we’ll create the AS class for the DL in the next section), and an attribute called factory-method=getInstance, indicating that it’s a Singleton. Next we’ll examine the <property> node, which is really the crux of the entire framework — here we’re setting the class property on the DL called employeeDelegate to a value of the fully qualified name of out AS mock-object delegate called EmployeeASDelegate, signifying that we’d like to inject the AS BD into the DL at run-time. Later we will setup the SASAC to inject the XML BD, but for now let’s test out this version by loading the file at run-time and making sure that it does in fact inject our AS BD.
Create the DelegateLocator
Since our DL is really just a registry of the BDs we want to use at run-time, we need to create a getter and setter method for each BD we want to inject into it with the same property name as the one we used in the SASAC — employeeDelegate. Create a new AS class called DelegateLocator and make it a singleton. Next, create a private var representing the employeDelegate with corresponding getters and setters and make sure they use our Employee Delegate interface, IEmployeeDelegate as the type:
/**
* Reference to the employee delegate. Provides an interface
* to get the injected delegate at run-time.
*/
private var _employeeDelegate:IEmployeeDelegate;
public function get employeeDelegate():IEmployeeDelegate
{
return this._employeeDelegate;
}
public function set employeeDelegate(delegate:IEmployeeDelegate):void
{
this._employeeDelegate = delegate;
}
Modify the GetEmployeeCommand to Use the DelegateLocator
If you recall, we recently modified the GetEmployeeCommand to reference the EmployeeXMLDelegate…we’ll need to go back into the CMD and modify it again to use the DL and Interface to acquire the injected BD:
private var delegate:IEmployeeDelegate;
public function GetEmployeeListCommand()
{
trace("GetEmployeeListCommand Constructor");
this.delegate = DelegateLocator.getInstance().employeeDelegate;
this.delegate.responder = this;
}
Now we’re acquiring the BD from the DL with the injected, concrete implementation set up in the ApplicationContext file, but we need to make a couple small change to our BDs and Interfaces…we need a reference to the CMD as the responder. In our previous implmentation of the CMD, we passed in a reference of itself into the constructor of the BD, but now we’re going to set it as a property on the BD. Instead of making this change in ever BD, let’s make an abstract BD that each of our concrete BDs will subclass:
AbstractDelegate
package com.wasi.employeeconsole.business.delegates
{
import mx.rpc.IResponder;
public class AbstractDelegate
{
/**
* Constructor.
*/
public function AbstractDelegate()
{
trace("AbstractDelegate Constructor");
}
/**
* RPC Responder, used as a reference back to the command that made the request.
*/
private var _responder:IResponder;
public function get responder():IResponder
{
return this._responder;
}
public function set responder(value:IResponder):void
{
this._responder = value;
}
}
}
Now go into each BD and subclass our new AbstractDelegate:
public class EmployeeASDelegate extends AbstractDelegate implements IEmployeeDelegate
public class EmployeeXMLDelegate extends AbstractDelegate implements IEmployeeDelegate
And finally go into our IEmployeeDelegate and extend a SAS CGM extention called IResponderAware that will allow/force each of our BDs to have a set repsonder(value:IResponder) method (open up the source of IResponderAware to see what it’s doing):
public interface IEmployeeDelegate extends IResponderAware
I know, I know…this is getting long, so on with it already…
Load the Spring ApplicationContext Config
Finally, open your Application file so we can load the SASAC and instantiate the DL:
- Create a class property representing the application context.
- Listen for the Creation Complete event of the Application and handle it with an init() method.
- Create loadSpringAppContext() method and call it in the init().
- In the loadSpringAppContext() method, create a new FlexXMLApplicationContext (the application context class property we defined in step 1) and pass in the URL to the SASAC file.
- Create listeners for the success and failed requests for the SASAC.
- Load the File.
- Upon successful retrieval of the SASAC, instantiate the DL.
- Test…you’ll get an error, but this is exected and requires some explanation.
/** * Defines the application specific context by which objects and * their dependencies are loaded. */ private var applicationContext:FlexXMLApplicationContext;/** * Called when the Application component has been created. */private function init():void { trace("Application init"); this.loadSpringAppContext(); } /** * Initializes theapplicationContextinstance and adds * listeners for the context file loading events. */ private function loadSpringAppContext():void { trace("Application loadSpringAppContext"); var applicationContextURL:String; applicationContextURL = "../assets/springactionscript/applicationContext.xml"; // Initializes theapplicationContextinstance and adds listeners for the context file loading events. this.applicationContext = new FlexXMLApplicationContext(applicationContextURL); this.applicationContext.addEventListener(Event.COMPLETE, applicationContextLoadResult); this.applicationContext.addEventListener(IOErrorEvent.IO_ERROR, applicationContextLoadFault); this.applicationContext.load(); } /** *IApplicationContextLoader.applicationContextLoadResult* implementation which handles successful loading of the context * document. */ public function applicationContextLoadResult(event:Event):void { trace("Application applicationContextLoadResult"); this.applicationContext.getObject("delegateLocator"); } /** *IApplicationContextLoader.applicationContextLoadFault* implementation which handles an exception when loading the context * document. */ public function applicationContextLoadFault(iOErrorEvent:IOErrorEvent):void { trace("Application applicationContextLoadFault " + iOErrorEvent.text); // we'll go with a simple stoopid apprach for this right now and just throw an alert Alert.show("Spring Application Context Failed to Load", "Error"); }
An error!?! WTF mate?
[SWF] Users:brianmriley:projects:spring-hibernate:workspaces:flex3:EmployeeManagementConsole2:bin-debug:EmployeeManagementConsole2.swf - 1,235,684 bytes after decompression
CairngormFrontController Constructor
CairngormFrontController addCommands
Application init
Application loadSpringAppContext
5/8/2009 14:40:02.804 [INFO] SpringActionScript.FlexXMLApplicationContext Loading XML object definitions from [../assets/springactionscript/applicationContext.xml]
Error: A class with the name
'com.wasi.employeeconsole.business.delegates.EmployeeASDelegate'
could not be found.
at as3reflect::ClassUtils$/forName()[C:\Users\Christophe\workspace\as3reflect\src\as3reflect\ClassUtils.as:89]
at org.springextensions.actionscript.ioc.factory.support::DefaultListableObjectFactory/getObjectNamesForType()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\ioc\factory\support\DefaultListableObjectFactory.as:87]
at org.springextensions.actionscript.context.support::XMLApplicationContext/registerObjectPostProcessors()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\context\support\XMLApplicationContext.as:196]
at org.springextensions.actionscript.context.support::XMLApplicationContext/afterParse()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\context\support\XMLApplicationContext.as:158]
at org.springextensions.actionscript.ioc.factory.xml::XMLObjectFactory/_doParse()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\ioc\factory\xml\XMLObjectFactory.as:341]
at org.springextensions.actionscript.ioc.factory.xml::XMLObjectFactory/_loadNextProperties()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\ioc\factory\xml\XMLObjectFactory.as:315]
at org.springextensions.actionscript.ioc.factory.xml::XMLObjectFactory/_loadNextConfigLocation()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\ioc\factory\xml\XMLObjectFactory.as:291]
at org.springextensions.actionscript.ioc.factory.xml::XMLObjectFactory/_onLoaderComplete()[C:\Users\Christophe\Documents\Adobe Gumbo MAX Preview\spring-actionscript\core\src\main\actionscript\org\springextensions\actionscript\ioc\factory\xml\XMLObjectFactory.as:241]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()
Since we’re injecting our concrete types of BDs into the application at run-time, we never explicitly told the Flex compiler to add our EmployeeASDelegate class into the SWF; thus, when we try to instantiate it the Flash Player throws an error saying the class doesn’t exist…one way to get around this is to just create a reference to it somewhere in your application, but we’re going to take a slightly different approach and add it to a property file for better organization.
ClassReferences.properties
Create a new properties file and put it directly into the src folder of your project (again, we’ll come back to cleaning this up in later posts) and create a reference to both the EmployeeASDelegate and the EmployeeXMLDelegate, since we’ll be switching back and forth between the 2 shortly.
EmployeeASDelegate = ClassReference("com.wasi.employeeconsole.business.delegates.EmployeeASDelegate")
EmployeeXMLDelegate = ClassReference("com.wasi.employeeconsole.business.delegates.EmployeeXMLDelegate")
Now create a reference to your ClassProperties.properties file in your main Application:
[ResourceBundle("ClassReferences")]
private var springClassRefs:ResourceBundle;
Success & Last Touches
Run your application and click the “Refresh List” button and you should see the following:

Employee Mgmt Console Populated with AS Mock Objects
Open up the SASAC file and change the reference of the Employee Delegate from the AS impl to the XML impl:
<?xml version="1.0"?>
<objects xmlns = "http://www.pranaframework.org/objects"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.pranaframework.org/objects http://www.pranaframework.org/schema/objects/prana-objects-0.5.xsd">
<object
id="delegateLocator"
class="com.wasi.employeeconsole.business.delegates.DelegateLocator"
factory-method="getInstance">
<property name="employeeDelegate">
<object class="com.wasi.employeeconsole.business.delegates.EmployeeXMLDelegate" />
</property>
</object>
</objects>
Save it, run it, and you should see the following:

Employee Management Console with XML Business Delegate
Voila! You’ve just successfully set up your first Flex + SAS + CGM application and learned how to inject 2 different types of BDs at runtime. Say tuned for episode 3 to learn how to inject the XML HTTPService in the EmployeeXMLDelegate also via SAS.
References:
- Dependency Injection in Flex Applications - Part 1 - Spring ActionScript and Cairngorm - Allen Manning
- IoC and the Dependency Injection Pattern in Flex - Eric Feminella
- Christophe Herreman’s Blog - Christophe Herreman
Installing Tomcat in a Sensible Way in an EC2 Cloud Machine: Part 1
Tomcat on EC2
A couple of us recently attended a great seminar put on by the folks at SpringSource. They discussed some great strategies for large scale deployment of TC in a sensible and extensible fashion into productions environments. The approach works as well in our dev sandboxes as it does in production, so I’ll be following some of the best practices learned from the folks who know it best.
What do I have and what do I need?
Depending on the AMI you chose, Tomcat may or may not be installed. Some distributions come with TC installed already.
I suggest that you don’t rely on the distribution version of TC since it may be one that has been modified by the creators of the distribution. Better to just go to the source and get the latest and greatest.
One great thing about using TC is that you just download the version of your choice, unzip/untar it, and you’re essentially off to the races.
Preparation
Similarly, many disty’s come with Java installed and they again can be specific to the disty. I always like to make sure we have the latest Sun Java installed. Feel free to use the version of your choice but your mileage may vary. I’m going to be using the Sun Java6 JDK
Over to the terminal window and do:
apt-get install sun-java6-jdk
It will take a while for all this and the dependencies to all load. When it’s complete, you can verify the install by doing:
java –version

Download TC
Let’s go to http://tomcat.apache.org There’s plenty of reading there regarding which version does what which we can leave as an exercise. Let’s grab Tomcat 6.x from the left hand side of the page under Downloads. Scroll down the next page and we have some choices:

If you hover over the tar.gz link, you’ll see the path in your browser:
![]()
Cool. So back over to our terminal window on our EC2 machine.
We’ll do a wget command to get this version:
wget http://www.devlib.org/apache/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.tar.gz
When it’s completed:

Install TC
Now that you’ve downloaded it, let’s move it to someplace more permanent and untar it.
I’m using /usr/local/tomcat but you can use the location of your choice. One of the beauties of TC is that it has no requirements regarding where you install it and almost no requirements about where you store the various folders within as we’ll learn later.
mv apache-tomcat-6.0.14.tar.gz /usr/local/tomcat
tar xvzf apache-tomcat-6.0.14.tar.gz
We’ve now downloaded TC and installed it to a permanent location. Before we go any further, let’s examine what we have and what it all means.
Installing Tomcat in a Sensible Way in an EC2 Cloud Machine: Part 2
Tomcat Directories and How It Launches
Let’s pop into the tomcat directory and see what we have.
We’ll try to understand what’s in each of the directories listed
/bin
This directory is never used during runtime. It’s sole purpose is to store scripts and boostrap libs. This directory contains the startup and stop scripts used to launch and kill TC as well as all the scripts it they call
/conf
This directory contains server level versions of the following files:
- context.xml
- In TC, a context is an application deployed in TC
- tomcat-users.xml
- Provides access control to applications running on the server
- server.xml
- Provides all the connectors, ports, engines, virtual hosts configured in the server
- web.xml
- Following the J2EE spec, this is the config file for the web applications defined at the top server level. It essentially tells the servlet engine what servlets map to which URIs, maps filters, security settings, etc.
- logging.properties
- Allows you define the logging levels within the server although you’ll probably want to set this up on a per application basis. TC now uses the java.util.logging package for logging instead of the previous log4j as the former was found to be a source of memory leaks on hot swaps
- context.xml
- A place to provide <Context> snippets. Usually, each application will contain one of these in the META-INF folder so you can control context settings at the application level
- catalina.policy
- The JVM uses this for security decisions and only if you invoke TC with the –security option
- catalina.properties file
-
- A regular Java properties file sued to set class loader paths, security package lists, and some tunable parameters. One useful feature of it is the ability to set properties that can be referenced in other files.
EG: # Some Setting
some.setting=1234
And in another file such as server.xml
<Connector port=”${some.setting}”
- A regular Java properties file sued to set class loader paths, security package lists, and some tunable parameters. One useful feature of it is the ability to set properties that can be referenced in other files.
-
NOTE: another great feature of TC is that all of these files can exist on a per application basis as well.
/lib
Contains the jars necessary to launch TC. The bootstrap process looks in CATALINA_HOME/lib directory for these jars
/logs
Well, you can only imagine!
/temp
This directory is used by the JVM for temporary files. (java.io.tmpdir)
/work
This is a server level working directory for web applications
/webapps
This is where you place your applications that run within TC.
Understanding the TC Launch Procedure
Typical startup procedure for TC on EC2 machine goes something like this (assuming you’re using bash)
./usr/local/tomcat/bin/startup.sh
By default, this should launch TC on the machine at port 8080. But before you run off and do this, let’s examine the sequence of events that take place when you run this command, the actions that are performed during this launch, and ways to simplify your life in the process.
- startup.sh
The sole purpose of this file is to locate and call catalina.sh with the start option. - catalina.sh
Well, this file does quite a bit. But, the important parts are- Invokes the setclasspath.sh script
- Invokes the setenv.sh script if it exists
- Launches the JVM (if the JVM is located)
- setclasspath.sh
TC is a Java application. In order to run, it needs Java installed on the system. This script if responsible for finding the JVM and making sure it’s on the classpath to run and setting up some variables for use by the JVM. The JVM is found by examining the system classpath for the JAVA_HOME variable. Many tutorials on this subject will tell you make sure you set the JAVA_HOME var in your ~/.bashrc file or even in the startup.sh script. Although these are acceptable, they aren’t the most extensible and flexible approach to use. Which leads us to…… - setenv.sh
The catalina.sh script looks to see if there’s a setenv.sh file in CATALINA_BASE/bin. If it’s there, it’s executed prior to launching the JVM. This is the perfect place to put all of your environment settings specific to a TC instance.
Further along, we’ll examine how to set up TC instances in a way that allows you to control and isolate your deployments. The setenv.sh file is a great place to store things like your JAVA_HOME variable. This allows you to switch between, let’s say, 1.5 and 1.6 and if you find there are issues in the latter, you simple switch back as needed.The setenv.sh file doesn’t exist in the basic install. Simple create one and put all of your environment setting export lines in it. When it’s time to upgrade TC, simply copy it over. Quite slick!
Installing Tomcat in a Sensible Way in an EC2 Cloud Machine: Part 3
Putting it All Together
So, based on the brilliant approach presented by Filip Hanik at SpringSource, let’s build a directory layout and a script or two that will make deployment, management, version control, and resource management intuitive.
An interesting aspect to Filip’s presentation was that he proposed having a TC instance per application. This allows for isolation of your applications in a way that doesn’t allow performance or memory issues of one application to affect other applications. This does present more management overhead and certainly once things are clearly stable, they could be deployed in a combined environment but it was an approach I hadn’t thought of.
The directory structure
- /usr/local/tomcat/apache-tomcat-6.0.18/
This will be the basic TC install for a given version. The run script will be referencing this - /usr/local/tomcat/run.sh
The key to it all. This script will take a start|stop|run input as well as instance number(1 or 2 or etc.) - /usr/local/tomcat/shared/
This folder will contain shared instance data if you do not provide it at the instance level. So if you want to provide a specific server.xml for a given instance, place it in
instance/conf/server.xml, otherwise, the one in shared/ will be used. - /usr/local/tomcat/instance_1/
- /usr/local/tomcat/instance_2/
… - /usr/local/tomcat/instance_n/
These are specific TC instances.
Let’s examine some differences between instances
Instance_1 is running on port 8080 using jdk1.5 and has a connection timeout of 20 seconds and sets the JVM heap to 512m max and 192k per thread.
/usr/local/tomcat/instance_1/bin/setenv.sh
JAVA_HOME=”/usr/local/java/jdk1.5”
CATALINA_HOME=”/usr/local/apache_tomcat-6.0.18”
CATALINA_BASE=”/usr/local/tomcat/instance_1”
CATALINA_OPTS=”-Xmx512m –Xss192k”
/conf/catalina.properties
http.port=8080
/conf/server.xml
<Connector port=”${http.port}”
protocol=”HTTP/1.1”
connectionTimeout=”20000” />
Instance_3 is running on port 8081 and is using jdk1.5 and has a connection timeout of 60 seconds
/usr/local/tomcat/instance_3/bin/setenv.sh
JAVA_HOME=”/usr/local/java/jdk1.6”
CATALINA_HOME=”/usr/local/apache_tomcat-6.0.18”
CATALINA_BASE=”/usr/local/tomcat/instance_3”
/conf/catalina.properties
http.port=8081
/conf/server.xml
<Connector port=”${http.port}”
protocol=”HTTP/1.1”
connectionTImeout=”60000” />
You can hopefully see the beauty and the benefits of an approach like this. You can isolate instances, JVMs, applications, configurations. Or, you can share various pieces and isolate others.
If the Tomcat Seminar by SpringSource is coming to your town, it’s a great presentation for short money.
Installing Tomcat in a Sensible Way in EC2 Cloud Machine: Part 4 Final
Making Sure You Can Access Everything…all the time
So, we’ve come pretty far. We’ve learned what pieces were needed to install TC on our EC2 server. We’ve learned some sensible steps in configuring your deployment environment so that you can run multiple instances of TC in a sensible manner.
All we have left to do is make sure we can access TC via the web and ensure that the server comes back up after a re-boot (if so desired).
Making TC Accessible to the Outside World
Log into your EC2 management console and select the specific instance you have installed TC to. Note the Security Groups that have access to this instance. In order for the world to have access to your instance of TC, you need to enable the port you plan to run it on. In this case, we’ll enable it for the default group.

Navigate to the Security Groups in the console and select the security grouop you want to enable the port for. In this case, we’ll be enabling port 8080 for the default group.
In the Connection Method column, select Custom.
In the Protocol column, select tcp.
In the From Port and To Port columns, enter 8080.
In the Source (IP or Group) column, enter 0.0.0.0/0. This will make it available to the world.
Click the Save button.
![]()
Congratulations, you’re console should now be available at http://<url to your instance>:8080.
Getting TC to Survive a Reboot
Linux installs support a mechanism for restarting services via /etc/init.d. In order to create a startup script so that TC survives a reboot and comes back up, use your favorite editor and create a similar file
vi /etc/init.d/tomcat
Paste in the following:
# Tomcat auto-start
#
# description: Auto-starts tomcat
# processname: tomcat
# pidfile: /var/run/tomcat.pid
case $1 in
start)
# uncomment and supply the correct instance for default start
# we’ll only support start for this script
# sh /usr/local/tomcat/run.sh start <instance number>
;;
stop)
# No need to support this since we’ll use the run.sh stop <instance>
;;
restart)
# Ditto above
;;
esac
exit 0
Make sure the script is executable by:
chmod 755 /etc/init.d/tomcat
And finally, link the script to the startup folders with a symbolic link:
ln –s /etc/init.d/tomcat /etc/rc1.d/K99tomcat
ln –s /etc/init.d/tomcat /etc/rc2.d/S99tomcat
Flex + Cairngorm + Spring ActionScript + Tomcat + WebORB/BlazeDS + Spring Java + Hibernate + MySQL Tutorial Part 1
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