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
#1 by rico - May 19th, 2009 at 13:53
I was told that with previous versions of Spring, that Services could be loaded dynamically by extending the ServiceLocator in Flex Cairngorm architecture. Is this still possible? If so how?
#2 by brianr - May 26th, 2009 at 09:11
@rico
You can load the services dynamically into the SL, but with this approach it’s unnecessary as they’re loaded dynamically into each delegate — this essentially removes the necessity for an SL…