The “Spring ActionScript” Framework – Part 1: The Basics

The “Spring ActionScript” framework (formerly known as Prana, and brainchild of Christophe Herreman) is being built as the ActionScript version of the Spring IoC framework hugely popular in the Java world. It is also part of a growing number of Flex frameworks that revolve around the Dependency Injection approach (the list also includes Swiz and Mate).

I recently spent some time exploring “Spring ActionScript”. There aren’t a lot of resources available yet, so I figured I would contribute my own exploration.

Note: Also, to avoid confusion, this project is independent from the Spring/BlazeDS integration project I have been writing about a lot lately. These two projects could however complement each other nicely.

In this first post, I’ll cover the basics… Imagine you have an application that uses RemoteObject to access the back-end of your application. Unless your application is made of only a couple of components and will forever communicate with the same server, there are two issues you’ll have to deal with early on:

  1. How to externalize the service configuration (channels, endpoints, etc) from your code
  2. How to provide the different components of your application with a reference to that service

Notes:

  1. This first example is intentionally kept very simple. In a more partitioned application, you may want to pass a more abstract controller around as opposed to a specific RemoteObject. This will be covered in part 3 of this series.
  2. The Spring ActionScript framework is an inversion of control framework: You don’t have to use RemoteObject, any specific data access strategy, or even connect to a back-end to use it… This is just the test case I wanted to build.

Objects configuration and wiring

Spring Actionscript uses an XML file to configure and wire its components. The advantage is that you can change the configuration and the wiring of your components, or even swap the implementation of a component without having to recompile. This leads to a great deal of flexibility during development, testing, and in your production environment.

On the other hand, when you declare classes in an XML configuration file, the compiler is not aware of what you are doing: The configuration and wiring of your components is not checked at compile time, and more importantly, classes defined in the XML configuration file but not referenced directly in your code will not be linked in your SWF. This is however not a major issue as you can easily tell the compiler to include these classes (see part 3 of this series).

In this first example, we will simply configure a RemoteObject…

<?xml version="1.0" encoding="utf-8"?>
<objects>

	<object id="channelSet" class="mx.messaging.ChannelSet">
		<method-invocation name="addChannel">
			<arg>
				<object id="amfChannel" class="mx.messaging.channels.AMFChannel">
					<property name="url" value="http://localhost:8400/lcds-samples/messagebroker/amf"/>
				</object>
			</arg>
		</method-invocation>
	</object>

	<object id="contactRemoteObject" class="mx.rpc.remoting.mxml.RemoteObject">
		<property name="channelSet" ref="channelSet" />
		<property name="destination" value="contacts" />
		<property name="showBusyCursor" value="true" />
	</object>

</objects>

Notice that we first configure a ChannelSet object. In this case, we define a single AMF channel. We then configure our RemoteObject, and inject its channelSet property with the ChannelSet object we just configured.

Externalizing this configuration and the wiring between the RemoteObject and the ChannelSet from your code has many benefits… Without recompiling, you could for example:

  1. Change the AMF channel URL, point to another server, another port, another endpoint.
  2. Add more channels (fall back channels) to the ChannelSet.
  3. Change the channel type. For example, switch from AMFChannel to RTMPChannel.
  4. Change the target destination

As a (simpler) alternative you could also configure your RemoteObject as follows:

<?xml version="1.0" encoding="utf-8"?>
<objects>

	<object id="remoteObject" class="mx.rpc.remoting.mxml.RemoteObject"	abstract="true">
		<property name="endpoint" value="http://localhost:8400/lcds-samples/messagebroker/amf" />
		<property name="showBusyCursor" value="true" />
	</object>

	<object id="contactRemoteObject" parent="remoteObject">
		<property name="destination" value="contacts" />
	</object>

</objects>

Note that to avoid repetition, you can configure an “abstract” object (in this case “remoteObject”) that includes configuration settings applicable to all the concrete versions of that object (in this case “contactRemoteObject”).

Obtaining a configured object in the application.

Now that the RemoteObject is configured, let’s build a simple application using the RemoteObject we just configured.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*"
	initialize="applicationCompleteHandler()">

	<mx:Script>
		<![CDATA[
			import mx.rpc.AsyncResponder;
			import mx.controls.Alert;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.rpc.AsyncToken;
			import mx.rpc.remoting.mxml.RemoteObject;

			import org.springextensions.actionscript.context.support.FlexXMLApplicationContext;

			private var applicationContext:FlexXMLApplicationContext;

			private var remoteObject:RemoteObject;

			private function applicationCompleteHandler():void
			{
				applicationContext = new FlexXMLApplicationContext("applicationContext.xml");
				applicationContext.addEventListener(Event.COMPLETE, applicationContextLoaded);
				applicationContext.load();
			}

			private function applicationContextLoaded(event:Event):void
			{
				remoteObject = applicationContext.getObject("contactRemoteObject");
				var token:AsyncToken = remoteObject.getContacts();
				token.addResponder(new AsyncResponder(resultHandler, faultHandler, token));
			}

			private function resultHandler(event:ResultEvent, token:AsyncToken):void
			{
				dg.dataProvider = event.result;
			}

			private function faultHandler(event:FaultEvent, token:AsyncToken):void
			{
				Alert.show(event.fault.faultString);
			}

		]]>
	</mx:Script>

	<mx:DataGrid id="dg" width="100%" height="100%"/>

</mx:Application>

The first step when you build an application using the Spring ActionScript framework is to create an ApplicationContext object and use it to load your configuration. Once the configuration is loaded, you can obtain fully configured objects using the applicationContext’s getObject method, and from here it’s then business as usual.

Next Steps

In this first example, 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 get configured objects in your application using the applicationContext.

In part 2, “Autowiring”, 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.

  • A Swiz User

    I looked at Spring Actonscript and was impressed with the breadth and depth of the framework.

    However, the issues and limitations you mention around using a separate xml file for object configuration and wiring were more of a concern for me.

    It’s worth noting that in the Java world there is IDE-support that makes working with the separate Spring xml file much easier — including validation and refactoring support.

    At the moment, the project I am working on is using Swiz because it can use mxml files for object configuration and wiring and leverages the support for mxml editing, validation and refactoring provided by FlexBuilder.

    Given that these kinds of frameworks are required by “large/more complex” Flex applications I’d say that IDE-support is important.

    Looking forward to the rest of the articles in this series.

  • For the Swiz User I would say that using the prana XSD at http://www.pranaframework.org/schema/objects/prana-objects-0.7.xsd in the XML gives you all the code completion you need with any XML editor not just Flex Builder, and currently it’s the best documentation to discover what’s in Spring ActionScript when compared to the official Java Spring framework.

    Still have to make [Autowired] work in a reliable and predictable way, can’t wait for your second article on this subject, thnx christophe!

  • pavan kumar

    How different is using applicationContext.getObject(…) from ServiceLocator.getObject(…) which i feel is a better abstraction .
    I suppose frameworks like mate & flight also provide some sort of DI.

  • Thanks for the introduction!

    I just wonder whether your example compiles because I expected a type cast for
    remoteObject = applicationContext.getObject(“contactRemoteObject”);

    Anyway: very nice article and I look forward to the other article(s)!

  • Pingback: 10/03/2009 « Robertopriz’s Weblog()

  • Thanks for the plug Christophe.

    FYI, we are working on a new site, documentation and samples: http://www.springactionscript.org

    @A Swiz User: You are absolutely correct that we need better IDE support for this. I’m curious if we could plug into the Spring IDE and provide support for Spring ActionScript xml contexts. (On a sidenote: it should be fairly easy to create a new type of application context for Spring AS that is fed by an MXML config. It might be worth investigating)

    @pavan kumar: You could easily configure a custom service locator object in Spring AS and use that service locator as a facade on the application context to retrieve services.

    @Tom Van den Eynde: the return value of getObject() is typed to *, so it is not needed to do a cast.

  • As a Mate user, I am highly excited to see true DI. What I mean is that Mate has no ability to swap in and out different objects of a type. You can’t name an object with an ID, so you are dealing with concrete classes always and you can’t sub in mock objects.

    That being said, I’m diussapointed in that there is a dependency on FlexXMLApplicationContext. So, my model objects would have to be coupled to the Spring framework. It doesn’t feel too good to me. In Mate, I had no such restriction…though there were some limitations (such as having to extend InjectorTarget for models).

    I look forward to the next two articles.

  • Pingback: Christophe Coenraets » Blog Archive » The Spring ActionScript Framework — Part 3: Injecting Services (and Mock Services)()

  • @John Blanco: I’m not sure what you mean by the dependency on FlexXMLApplicationContext. How you model your domain is completely up to you and I would encourage you not to reference any framework classes in the core domain classes. Except for the main application entry point, there is no need to reference any of the Spring AS classes.

  • Pingback: Spring ActionScript - Dependency Injection and more for Flex/AIR at Springsteam - Next Generation Java Development | Spring . Flex/AIR . 3D()

  • Pingback: links for 2009-05-12 | diamondTearz()

  • Pingback: Christophe Coenraets » Blog Archive » Building a Flex Application with the Parsley Framework()

  • Pingback: Learning Spring ActionScript « tommek()

  • I am lucky that I detected this website , exactly the right info that I was looking for! .

  • Right to the purpose and also well written! The reason why can not everyone else end up like this?

css.php