In the first part of this series, we looked at how the “Spring ActionScript” framework can help you externalize the configuration and the wiring of your components, and how you can easily obtain configured objects using applicationContext.getObject().
In this second part, we will discuss how you can make these objects available to the views of your application without tightly coupling these views to the framework, and without passing references around through potentially many levels of view containment.
We will build the “Spring ActionScript” version of the InSync contact management application I often use in this blog to explore new technologies. The application has two views: MainView and ContactForm. Both need a reference to a contact RemoteObject to work.
NOTE: This example is intentionally kept simple. In a more partitioned application, you may want to pass a more abstract controller around as opposed to a specific RemoteObject. We will use this approach in part 3.
The views could use applicationContext.getObject() to access their dependencies (in this case the contact RemoteObject), but this approach has a number of problems:
- With a dependency on applicationContext, the views would be tightly coupled to the framework.
- We would still need to pass a reference to the applicationContext object to the views. This is often solved using the singleton approach which has its own set of problems.
So, instead of the views instantiating or looking up their dependencies, a better approach would be to “inject” these dependencies into the views.
Unlike Swiz, “Spring ActionScript” doesn’t currently have built-in support for an [Autowire] annotation, but Christophe Herreman seems to imply that this feature is coming, and in the meantime, he provides some sample code to support “Spring ActionScript”-powered autowiring in your application. Using this custom code, the inSync application looks like this:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="applicationCompleteHandler()">
<mx:Script>
<![CDATA[
import insync.views.MainView;
import mx.utils.DescribeTypeCacheRecord;
import mx.utils.DescribeTypeCache;
import as3reflect.ClassUtils;
import org.springextensions.actionscript.context.support.FlexXMLApplicationContext;
private var applicationContext:FlexXMLApplicationContext;
private function applicationCompleteHandler():void
{
applicationContext = new FlexXMLApplicationContext("applicationContext.xml");
applicationContext.addEventListener(Event.COMPLETE, applicationContextComplete);
applicationContext.load();
}
private function applicationContextComplete(event:Event):void
{
systemManager.addEventListener(Event.ADDED, addedEventHandler);
var mainView:MainView = new MainView();
addChild(mainView);
}
private function addedEventHandler(event:Event):void
{
var autowiredObject:Object = event.target;
trace("Added to display list: " + autowiredObject);
var typeInfo:DescribeTypeCacheRecord = DescribeTypeCache.describeType(autowiredObject);
for each (var metaDataNode:XML in typeInfo.typeDescription..metadata)
{
if (metaDataNode.attribute("name") == "Autowired")
{
var propertyNode:XML = metaDataNode.parent();
var property:String = propertyNode.@name.toString();
trace("Found Autowired property: " + property);
var objectName:String = property;
var autowireByType:Boolean = true;
for each (var arg:XML in metaDataNode.arg)
{
if (arg.attribute("value") == "byName")
{
autowireByType = false;
}
}
if (autowireByType)
{
var clazz:Class = ClassUtils.forName(propertyNode.@type.toString());
var objectNames:Array = applicationContext.getObjectNamesForType(clazz);
if (objectNames.length == 1)
{
objectName = objectNames[0];
}
}
trace("Autowiring: " + property + " in " + autowiredObject);
autowiredObject[property] = applicationContext.getObject(objectName);
}
}
}
]]>
</mx:Script>
<mx:Style source="styles.css"/>
</mx:Application>
To be able to inject properties annotated with Autowired, we register as a listener for the ADDED event on systemManager, and introspect each object added to the display list. If the object has [Autowired] properties, those properties are injected (by name or by type) using applicationContext.getObject(objectName). This is also the approach taken by Swiz.
Timing
Before you inject objects into views, you need to make sure the applicationContext.xml file has been loaded and that the objects it defines have been instantiated. To that effect, the applicationContext dispatches an Event.COMPLETE event when it is ready. To make sure all the views of my application can be properly injected (if needed), the strategy I use in this application is to start instantiating the main view only after this event has been triggered. See addChild(mainView) in the applicationContextComplete handler.
The Views
With that infrastructure in place, the two views of the InSync application are easy to write. Their basic setup looks like this:
<?xml version="1.0" encoding="utf-8"?> <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.rpc.remoting.mxml.RemoteObject; [Autowired] public var contactRemoteObject:RemoteObject; ]]> </mx:Script> </mx:Canvas>
Installation instructions
NOTE: If you already installed the Swiz version of inSync, you can skip steps 1, 3, 4, 5 and 6.
- Install the BlazeDS turnkey server. (To be clear: you don’t have to use BlazeDS to use Spring ActionScript… That’s just what this sample is using.)
- Download insyncspringas.zip, and unzip it on your local file system.
- Copy insyncspringas/java/classes/insync to blazeds/tomcat/webapps/samples/WEB-INF/classes/insync.
- Add the following destination to blazeds/tomcat/webapps/samples/WEB-INF/flex/remoting-config.xml:
- Copy insyncspringas/sampledb/insync to blazeds/sampledb/insync
- Edit server.properties in blazeds/sampledb, and modify the file as follows to add the insync database to the startup procedure.
server.database.0=file:flexdemodb/flexdemodb server.dbname.0=flexdemodb server.database.1=file:insync/insync server.dbname.1=insync server.port=9002 server.silent=true server.trace=false
- Start the database (startdb.bat or startdb.sh)
- Start BlazeDS
- In Flex Builder, create a new Flex project called insyncspringas. You don’t have to select any “Application server type”.
- Copy spring-actionscript.swc and as3reflect.swc from insyncspringas/flex/lib to the lib directory of your project
- Copy the files and folders from insyncspringas/flex/src to the src directory of your project
- Open applicationContext.xml and make sure the remoteObject endpoint value matches your server setup.
- Run the application
<destination id="contacts">
<properties>
<source>insync.dao.ContactDAO</source>
<scope>application</scope>
</properties>
</destination>
Note on Autowiring and Performance
Annotation-based dependency injection is elegant and easy to work with. However, the current implementation that requires a describeType on every object added to the display list has a performance impact. This is maybe something that the Flex framework could help with in the future. For example, we could inject code at compile time to dispatch an AutowireEvent for each Autowired property when a class is instantiated. We would leave it up to the frameworks to provide a specific injection implementation. That would give these frameworks a better event to listen to, and they wouldn’t have to introspect all the objects added to the display list. An alternative would be to have a compiler hook to allow annotation-based code injection at compile time.
In the meantime, you’ll have to identify if the performance impact of the current approach is acceptable in the context of your application. If not, there are ways to improve the basic approach described above:
- Using Swiz, Aral Balkan uses an autowire property on the views that require autowiring. In the autowiring code, he then uses the hasOwnPropety(“autowiring”) function to identify if the object needs to be autowired before using describeType. This approach still requires some level of introspection on each object added to the display list.
- Swiz now makes sure it doesn’t perform describeType on classes in the mx packages. This approach could also be added to the code above.
- Another approach would be for you to programmatically dispatch an AutowireEvent in the initialize event of the views that need to be autowired. This approach is maybe less elegant than a simple annotation, but wouldn’t have the performance impact of introspecting all the objects added to the display list. It would also work for any object in your application, not only the views.

11 Comments
Great post. I particularly liked the fact you also pointed out the performance implication.
I was looking into using the Autowire approach only yesterday and opted against it based on the performance hit.
We really need a way to add code at compile time via metadata, but another approach is to make use of the new -define argument to the compiler.
Alternatively to deal with the performance problems the Flash Player VM could add a Dynamic Proxy:
http://bugs.adobe.com/jira/browse/ASC-3136
I believe that is how most Java DI frameworks do the injection.
Until that happens another potential alternative is to monkey patch what is behind the Managed metadata tag and give it a custom implementation.
-James
Awesome! I wish you’d posted that a month ago when I was trying to do a very similar thing with Spring Actionscript.. I gave up and used SmartyPants-IOC instead: found it much easier to understand and use (not coming from a Java background). Nevertheless, very glad to find this post – perhaps I’ll give Spring Actionscript another bash :)
Can you post on how sping/blazeds integration works with spring actionscript. Seems similar to me except this autowiring part
Great explanation, so the current best approach in terms of performance with Spring AS would be using the AutowireEvent? Could it be possible to have an extended example of this?
“Another approach would be for you to programmatically dispatch an AutowireEvent in the initialize event of the views that need to be autowired. This approach is maybe less elegant than a simple annotation, but wouldn’t have the performance impact of introspecting all the objects added to the display list. It would also work for any object in your application, not only the views.”
This is the approach the Flicc framework, http://flicc.sourceforge.net, takes with the provided “Configure” tag. This approach also works well with modules – allowing loaded modules to either use thier own IOC config, or be configured by the parent application. A new version of Flicc is to be released in the coming weeks that will provide more documentation on how this benefits modular applications.
I just checked the Flicc framework, I think the idea is good and as I remember, I did read a comment from Christophe Herreman before about providing an injection via MXML instead of the XML itself as an alternative.
I really think the developers of Flicc can just work with the Spring ActionScript developers and then merge them into one so we will be able to use the DI either way. I still need to really try it out myself more to find out how different it is from the Java version of Spring Framework. I think these are all very good start, all the AC IOC framework developers should just work together to make one, instead of many of them since most of them are doing the similar thing. Then we can have a true Spring in AC.
Hi Christophe,
What we really need is a compile option that associates a class with a metatag.
for example in pseudo::
mxmlc main.xml -meta [Autowire] nl.artim.Autowire
then the class would be associated with each variable that has the tag. In your class Autowire you would have a standard interface like handleMetaData(object:*) in which you could do anything with the variable you want.
for example wiring up a model with the variable ;)
now the gui would have just the metatag and the way you compile your application determines the behaviour of the metadata tag.
If you use the the gui in another project you could use another framework and still be able to use the [autowire]. Just hook up another class to the metatag as a compiler option.
this kind of behavour is really needed and doen’t seem to complicated to build in for the flex compiler team.
what do you think?
If you like the idea please tell the flex team as i think you are pretty infulential voice for adobe….
thanx for the nice blog and extemely good examples!
Arnoud
oops sorry about the typos
I tried running the app, I was unable to run it successfully.
Couple of questions.
Dont we need to give entry for applicationContext.xml in web.xml for it to be available in application context.
While reading the child component, the code for auto wiring was not able to find and register the [Autowire] component
Kindly advice.
Why I said about the entry in web.xml is because the code is unable to read applicationContext.xml.
I debugged for numObjectDefinitions and it is ’0′
What would be the problem, kindly advice
6 Trackbacks
[...] Anyhoo.. check this out if you are interested in Spring ActionScript and Autowiring: link [...]
[...] we saw how Flex AS allows you to externalize the configuration and the wiring of objects. In part 2, we discussed how you can “autowire” view properties. We intentionally kept the example [...]
[...] automatiquement les attributs d’une classe alors que Actionscript les supporte. Un début de solution existe mais n’est pas encore inclu dans [...]
[...] also a Spring sub forum. Christophe Coenraets also offers articles about it in his blog (2). There are some infos about Maven 2 support. The latest news will be found in the future at [...]
[...] Christophe Coenraets » Blog Archive » The “Spring ActionScript” Framework – Part 2: Autowiri… (tags: actionscript flex framework springactionscript springas3 autowiring) [...]
[...] my recent explorations of “Swiz”, and “Spring ActionScript” (1,2,3), I decided to take the new version of the Parsley framework for a test drive, and build the [...]