spring action script

158
Spring ActionScript Reference Documentation

Upload: wil-shotton

Post on 29-Nov-2014

113 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Spring Action Script

Spring ActionScript

Reference Documentation

Page 2: Spring Action Script

Spring ActionScript: Reference Documentation1.1

Page 3: Spring Action Script

iii

Table of ContentsPreface ............................................................................................................................ viI. Getting Started ................................................................................................................ 1

1. Introduction ........................................................................................................... 2What is Spring Actionscript? ................................................................................ 2

2. The Inversion of Control (IoC) container ..................................................................... 3Introduction ....................................................................................................... 3

Basics - containers and objects ..................................................................... 3Dependencies ........................................................................................... 17Customizing the nature of an object ............................................................. 41Knowing who you are ............................................................................... 42Object definition inheritance ....................................................................... 42Object scopes ........................................................................................... 45Customizing the nature of an object ............................................................. 47Container extension points .......................................................................... 48Controlling collection order ........................................................................ 54

II. APIs and extensions ...................................................................................................... 553. Metadata annotations handling ................................................................................. 56

Introduction ..................................................................................................... 56Controlling the order of IMetadataProcessors ................................................. 57

4. The Operation API ................................................................................................ 58Introduction ..................................................................................................... 58

Operations, commands, services and tasks ..................................................... 585. The EventBus ....................................................................................................... 71

Introduction ..................................................................................................... 71EventBus listening .................................................................................... 71EventBus dispatching ................................................................................ 71EventBus event handling using metadata annotations ....................................... 72Routing other events through the EventBus ................................................... 73Metadata driven MVC micro-framework ....................................................... 74

6. The Component scanner and class scanning system ..................................................... 78Introduction ..................................................................................................... 78[Component] metadata explained ......................................................................... 78

Injecting constructor arguments ................................................................... 80Injecting properties .................................................................................... 80Method invocations ................................................................................... 81

Extending the class scanning system .................................................................... 82The IClassScanner interface ........................................................................ 82Controlling the order in which class scanners are executed ................................ 83

7. Testing ................................................................................................................ 84Introduction ..................................................................................................... 84Integration Testing ............................................................................................ 84

Overview ................................................................................................. 848. Spring Actionscript extensions ................................................................................. 91

Introduction ..................................................................................................... 91Cairngorm 2 ............................................................................................ 91PureMVC .............................................................................................. 111

III. Appendixes ............................................................................................................... 122A. XML Schema-based configuration ......................................................................... 123

Introduction .................................................................................................... 123XML Schema-based configuration ...................................................................... 123

Referencing the schemas .......................................................................... 123

Page 4: Spring Action Script

Spring ActionScript

iv

The util schema .............................................................................................. 124<util:constant/> ....................................................................................... 124<util:invoke/> ......................................................................................... 125

The messaging schema ..................................................................................... 125<messaging:channel-set> .......................................................................... 126<messaging:channel> ............................................................................... 126<messaging:abstract-consumer> ................................................................. 126<messaging:producer> .............................................................................. 127

The RPC schema ............................................................................................ 127The stage processing schema ............................................................................. 127

<si:genericstageprocessor> ........................................................................ 127B. Extensible XML authoring .................................................................................... 129

Introduction .................................................................................................... 129Authoring the schema ...................................................................................... 129Coding an INamespaceHandler implementation .................................................... 130Coding an IObjectDefinitionParser implementation ................................................ 131Registering the handler ..................................................................................... 132Code generator ............................................................................................... 132

C. Forcing Actionscript class inclusion ....................................................................... 134Introduction .................................................................................................... 134

Adding an anonymous code block .............................................................. 134Declaring a list of variables ...................................................................... 134Using the Frame metadata ........................................................................ 134Using a resource bundle ........................................................................... 134Using an ANT task as a prebuilder to generate a compiler config file ................. 135Using Maven .......................................................................................... 137

IV. Reference ................................................................................................................. 1399. Configuration reference ........................................................................................ 140

General description .......................................................................................... 14010. ....................................................................................................................... 151

Page 5: Spring Action Script

v

List of Tables2.1. The object definition ................................................................................................... 102.2. Autowiring modes ...................................................................................................... 262.3. Autowiring modes ...................................................................................................... 272.4. Object scopes ............................................................................................................. 45

Page 6: Spring Action Script

vi

PrefaceDeveloping software applications is hard enough even with good tools and technologies. Implementingapplications using platforms which promise everything but turn out to be heavy-weight, hard to controland not very efficient during the development cycle makes it even harder. Spring Actionscript provides afull-featured IoC container and several low-level extensions to existing frameworks which can make dailylife for a developer a little easier.

Spring Actionscript is modular, allowing you to use just those parts of it that you need, without having tobring in the rest. You can use the IoC container, but leave the Cairngorm extensions alone and use yourown solutions instead.

Spring Actionscript aims to be non-obtrusive and not to impose any kind of unnecessary structure to yourapplication while still promoting best practices in software development.

This document provides a reference guide to Spring Actionscript's features. Since this document is still tobe considered very much work-in-progress, if you have any requests or comments, please post them onthe user mailing list or on the support forums at .

Page 7: Spring Action Script

Part I. Getting StartedThe basic functionality of the IoC container

Page 8: Spring Action Script

2

Chapter 1. IntroductionWhat is Spring Actionscript?

Spring ActionScript is an offshoot of the Java-based Spring Framework written in ActionScript 3. It istargeted for the Flash, Flex and AIR platforms. The framework contains an Inversion of Control Container,an Operation and Task API, an EventBus, a metadata handling system, extensions for the Cairngorm andPureMVC frameworks and several other utilities.

Page 9: Spring Action Script

3

Chapter 2. The Inversion of Control(IoC) containerIntroduction

This chapter covers the Spring Actionscript Framework's implementation of the Inversion of Control (IoC)principle.

The and packages provide the basis for the Spring Actionscript Framework's IoC container.

The FlexXMLApplicationContext or XMLApplicationContext are the classes that any programmerstarting out with Spring Actionscript will encounter as the first pieces of code from the framework that theywill need to use. The classes are nearly identical, FlexXMLApplicationContext only adds Flex specificsupport, such as for the ArrayCollection.

These classes take care of loading and parsing of a configuration file, after which they are able to instantiate,assemble and otherwise manage objects.

In this chapter we are going to describe how to set up a configuration file, create an application contextand use it to instantiate objects.

Basics - containers and objectsThe objects that are managed by the Spring Actionscript IoC container, and the dependencies betweenthem, are reflected in the configuration metadata used by a container.

The container

The FlexXMLApplicationContext or XMLApplicationContext classes are the central IoC containerobjects in Spring Actionscript. Their responsibilities include instantiating or sourcing application objects,configuring such objects, and assembling the dependencies between these objects.

They inherit from XMLObjectFactory which allows you to express the objects that compose yourapplication, and the doubtless rich interdependencies between such objects, in terms of XML. TheXMLObjectFactory takes this XML configuration metadata and uses it to create a fully configured systemor application.

So what does this mean in plain English?

An instance of FlexXMLApplicationContext or XMLApplicationContext can read an XML file containinga description of the dependencies of your business objects and manage these dependencies. For instance,do all your business object need a reference to your model? But you want to be certain that they all receivethe same reference without having to depend on a singleton object?

This is where the IoC container comes in.

Configuration metadata

Spring Actionscript supports configurations defined in XML or MXML. When using XML-basedconfiguration metadata, you write object definitions for those objects that you want the Spring ActionscriptIoC container to manage, and then let the container do its stuff. Spring Actionscript configuration consistsof at least one object definition that the container must manage, but typically there will be more than oneobject definition. These object definitions are configured as elements inside a top-level element.

Page 10: Spring Action Script

The Inversion ofControl (IoC) container

4

(See Composing MXML based configuration metadata for how to perform this task using MXML instead).

These object definitions correspond to the actual objects that make up your application, they describe howthese objects need to be instantiated and configured.

Find below an example of the basic structure of XML-based configuration metadata.

<?xml version="1.0" encoding="utf-8"?> <objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd"> <object id="..." class="..."> <!-- collaborators and configuration for this object go here --> </object> <object id="..." class="..."> <!-- collaborators and configuration for this object go here --> </object>

<!-- more object definitions go here --></objects>

Instantiating a container

Instantiating a Spring Actionscript IoC container is straightforward.

var applicationContext:XMLApplicationContext = new XMLApplicationContext();applicationContext.addConfigLocation("application-context.xml");applicationContext.addEventListener(Event.COMPLETE, handleComplete);applicationContext.load();

The application-xml file in the above listing resides either on a remote server or a local file. Dependingon the application in question being a Flex/Flash or AIR application. Either way, the XML file is beingloaded using a URLLoader object. This means that this operation is asynchronous i.e. The applicationcan't know beforehand when this it is finished. Hence the addEventListener call: once container has fullyloaded the XML file and has successfully parsed it, the complete event is fired and the handleCompletemethod will be called.

To avoid hard coding the URL to the configuration file in the application source it is recommended topass this a flashvar into the Flex application. These flashvars can be defined in Flex Builder in the HTMLtemplate. This template can be found in the project directory root and is called html-template. In thisdirectory is resides a file called index.template.html.

Below is an example of how a flashvar defining the application-context.xml location, this example showsall the code between the <body> tag of the template. The relevant pieces of code have been marked in bold.

<script language="JavaScript" type="text/javascript"><!--// Version check for the Flash Player that has the ability to start Player Product Install (6.0r65)var hasProductInstall = DetectFlashVer(6, 0, 65);

// Version check based upon the values defined in globalsvar hasRequestedVersion = DetectFlashVer(requiredMajorVersion, requiredMinorVersion, requiredRevision);

if ( hasProductInstall && !hasRequestedVersion ) {

Page 11: Spring Action Script

The Inversion ofControl (IoC) container

5

// DO NOT MODIFY THE FOLLOWING FOUR LINES // Location visited after installation is complete if installation is required var MMPlayerType = (isIE == true) ? "ActiveX" : "PlugIn"; var MMredirectURL = window.location; document.title = document.title.slice(0, 47) + " - Flash Player Installation"; var MMdoctitle = document.title;

AC_FL_RunContent( "src", "playerProductInstall", "FlashVars", "MMredirectURL="+MMredirectURL+'&MMplayerType='+MMPlayerType+'&MMdoctitle='+MMdoctitle+"", "width", "${width}", "height", "${height}", "align", "middle", "id", "${application}", "quality", "high", "bgcolor", "${bgcolor}", "name", "${application}", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" );} else if (hasRequestedVersion) { // if we've detected an acceptable version // embed the Flash Content SWF when all tests are passed AC_FL_RunContent( "src", "${swf}", "FlashVars", "ContextURL=application-context.xml", "width", "${width}", "height", "${height}", "align", "middle", "id", "${application}", "quality", "high", "bgcolor", "${bgcolor}", "name", "${application}", "allowScriptAccess","sameDomain", "type", "application/x-shockwave-flash", "pluginspage", "http://www.adobe.com/go/getflashplayer" ); } else { // flash is too old or we can't detect the plugin var alternateContent = 'Alternate HTML content should be placed here. ' + 'This content requires the Adobe Flash Player. ' + '<a href=http://www.adobe.com/go/getflash/>Get Flash</a>'; document.write(alternateContent); // insert non-flash content }// --></script><noscript> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="${application}" width="${width}" height="${height}" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="FlashVars" value="ContextURL=application-context.xml" /> <param name="movie" value="${swf}.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="${bgcolor}" />

Page 12: Spring Action Script

The Inversion ofControl (IoC) container

6

<param name="allowScriptAccess" value="sameDomain" /> <embed src="${swf}.swf" quality="high" bgcolor="${bgcolor}" width="${width}" height="${height}" name="${application}" align="middle" play="true" loop="false" quality="high" flashvars="ContextURL=application-context.xml" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"> </embed> </object></noscript>

To access the flashvar parameters add an eventhandler for the preinitialize event in your application, likeso:

addEventListener(FlexEvent.PREINITIALIZE,handlePreInit);

or in MXML:

<mx:Application preinitialize="handlePreInit(event)"/>

Then in the event handling method retrieve the flashvar parameter like this:

private function handlePreInit(event:FlexEvent):void {

_contextURL = parameters['ContextURL'];}

Then later on (after the APPLICATION_COMPLETE event) the context URL can be fed to the applicationcontext instance again:

var applicationContext:XMLApplicationContext = new XMLApplicationContext();applicationContext.addConfigLocation(_contextURL);applicationContext.addEventListener(Event.COMPLETE, handleComplete);applicationContext.load();

Composing XML-based configuration metadata

It can often be useful to split up container definitions into multiple XML files. One way to then loadan application context which is configured from all these XML fragments is to use the applicationcontext constructor which takes multiple resource locations. Also, after construction of the container, morelocations can be added with the addConfigLocation() method.

Generally, the Spring Actionscript team prefers the above approach, since it keeps container configurationfiles unaware of the fact that they are being combined with others. An alternate approach is to use oneor more occurrences of the element to load object definitions from another file (or files). Let's look ata sample:

<objects>

<import file="services.xml"/> <import file="resources/messageSource.xml"/> <import file="/resources/themeSource.xml"/>

Page 13: Spring Action Script

The Inversion ofControl (IoC) container

7

<object id="object1" class="..."/> <object id="object2" class="..."/>

</objects>

The contents of the files being imported must be valid XML object definition files according to the SpringActionscript schema, including the top level element.

the object definition

<object/> elements can have a number of attributes that determine various properties and behaviorsof an object, its creation and wiring. Here's a list of all these properties with a link to their respectivedocumentation sections:

• abstract

• autowire

• autowire-candidate

• class

• dependency-check

• depends-on

• destroy-method

• factory-method

• factory-object

• id

• init-method

• lazy-init

• parent

• primary

• scope

• singleton (deprecated, use scope attribute instead)

• skip-metadata

• skip-postprocessors

• template

These element attributes will be mapped onto IObjectDefiniton instances after the XML has been parsedby the application context. Object definitions can be defined in XML, MXML or annotations. Objectdefinitions can be augmented with constructor, property and method invocation definitions.

Embedding the XML metadata

In the case where an external XML file is not desirable or practical Spring Actionscript also allows youto embed the XML metadata file in the application.

Page 14: Spring Action Script

The Inversion ofControl (IoC) container

8

To do so embed the XML file like this:

[Bindable][Embed(source="application-context.xml",mimeType ="application/octet-stream")]public var contextConfig:Class;

Note

For more information about embedding files visit this link:

After that the way to add the configuration location is slightly different:

var applicationContext:XMLApplicationContext = new XMLApplicationContext();applicationContext.addEmbeddedConfig(contextConfig);applicationContext.load();

Notice that we no longer need the Event.COMPLETE handler, since the configurations are embeddedthey will be loaded and parsed synchronously, so after invoking addEmbeddedConfig() once or more andcalling load() the application context will be ready for use immediately.

Note

Of course, if you mix embedded and external metadata you will need to keep theEvent.COMPLETE handler and load() invocation for obvious reasons.

And that's all there is to it!

Declaring embedded import files

If your embedded configuration file also contains import declarations you will have to change the markupslightly to let Spring Actionscript know where to find them. But first add your import configurations likethis:

[Bindable][Embed(source="services.xml",mimeType ="application/octet-stream")]public var servicesContext:Class;

[Bindable][Embed(source="resources/messageSource.xml",mimeType ="application/octet-stream")]public var messageSourceContext:Class;

[Bindable][Embed(source="/resources/themeSource.xml",mimeType ="application/octet-stream")]public var themeSourceContext:Class;

Then inside your main configuration file, change the import markup like this:

<objects>

<import file="servicesContext" type="class"/> <import file="messageSourceContext" type="class"/> <import file="themeSourceContext" type="class"/>

<object id="object1" class="..."/> <object id="object2" class="..."/>

Page 15: Spring Action Script

The Inversion ofControl (IoC) container

9

</objects>

And again, that's all there is to it!

Note

Make sure to add the embedded Class instances as properties of your Application object, thisis the place where Spring Actionscript will look for these property names. If it fails to find thespecified names an Error will be thrown. Also, because this functionality is depended on the Flexframework, it is only available when using the FlexXMLApplicationContext class, in other casesthe type='class' attribute will be ignored.

External property files

In some scenarios it might be useful to store certain properties of the config XML file externally so thatyou can easily change them without having to wade through the entire configuration file or if you want tore-use certain global values in different parts of the configuration, such as path data or URLs.

The application context allows you to specify external properties in separate Ant-like *.properties files.

You can then define property placeholders in your config files with the ${...} syntax. Here's an example.Note that the path to the *.properties file is relative to the path of the configuration file.

<objects>

<property file="strings.properties" />

<object id="string1" class="String"> <constructor-arg value="${s1}"/> </object> <object id="string2" class="String"> <constructor-arg value="${s2}"/> </object>

</objects>

And the strings.properties file contents would look like this:

s1=First strings2=Second string

Its also possible to combine property values, that way a property value can be injected with other values,for example:

s1=First String and {$s2}s2=Second string

Note

To prevent the properties file from being cached by the web browser the XMLObjectFactoryby default will suffix the URL with a random number. To turn this off for a specified propertyfile use the prevent-cache attribute. For example: <property file="strings.properties" prevent-cache="false"/>.

Page 16: Spring Action Script

The Inversion ofControl (IoC) container

10

Note

By default the properties loader will throw an error if a properties file could not beloaded, to ignore the error and resume loading set the required attribute to false: <propertyfile="strings.properties" required="false"/>

Define external properties explicitly

If you don't need an external file to store your properties in, yet you would like to define global propertiesto be used throughout your configuration, its also possible to define the property values directly on the<property/> tag:

<property name="s1" value="First string"/><property name="s2" value="Second string"/>

And, of course, here it is also possible to combine property values:

<property name="s1" value="First string and {$s2}"/><property name="s2" value="Second string"/>

Note

The file attribute will take precedence over the name and value attributes, so when both aredeclared the name and value attributes will be ignored.

Flashvars converted to properties

The FlexXMLApplicationContext will automatically add any flashvars that were passed to the applicationto its properties collection. The name of the flashvar can then be used in the same way as an applicationsetting property. For example: ${application.myFlashVar}.

The class responsible for this is the FlexPropertyPlaceholderConfigurer. For more about the applicationsetting read this section.

The objects

A Spring Actionscript IoC container manages one or more objects. These objects are created using theconfiguration metadata that has been supplied to the container (typically in the form of XML definitions).

Within the container itself, these object definitions are represented as ObjectDefinition objects, whichcontain (among other information) the following metadata:

Table 2.1. The object definition

Feature Explained in...

class Instantiating objects

name Naming objects

constructor arguments Injecting dependencies

properties Injecting dependencies

autowiring mode Autowiring collaborators

lazy-initialization mode Lazily-instantiated objects

initialization method Initialization callbacks

Page 17: Spring Action Script

The Inversion ofControl (IoC) container

11

Naming objects

Every object has one or more ids (also called identifiers, or names; these terms refer to the same thing).These ids must be unique within the container the object is hosted in.

When using XML-based configuration metadata, you use the 'id' attribute to specify the object identifier(s).The 'id' attribute allows you to specify exactly one id, and as it is a real XML element ID attribute, theXML parser is able to do some extra validation when other elements reference the id; as such, it is thepreferred way to specify an object id. However, the XML specification does limit the characters whichare legal in XML IDs.

Instantiating objects

An object definition essentially is a recipe for creating one or more objects. The container looks at therecipe for a named object when asked, and uses the configuration metadata encapsulated by that objectdefinition to create (or acquire) an actual object.

If you are using XML-based configuration metadata, you can specify the type (or class) of the objectthat is to be instantiated using the 'class' attribute of the element. This 'class' attribute (which internallyeventually boils down to being a Class property on a ObjectDefinition instance) is normally mandatory(see Section "" for the exception) and is used for one of two purposes. The class property specifies theclass of the object to be constructed in the common case where the container itself directly creates theobject by calling its constructor (somewhat equivalent to Actionscript code using the 'new' operator). Inthe less common case where the container invokes a static, factory method on a class to create the object,the class property specifies the actual class containing the static factory method that is to be invoked tocreate the object (the type of the object returned from the invocation of the static factory method may bethe same class or another class entirely, it doesn't matter).

Instantiation through a parent factory

Object factories can form a hierarchy through the parent property of an IObjectFactory implementationsuch as the AbstractObjectFactory. By assigning another IObjectFactory instance to this parent propertythe getObject() method will first see if the current object factory can create the requested object instance,if no appropriate ObjectDefinition can be found it will request it from its parent factory.

A simple example of an application context hierarchy

Imagine a scenario with two application contexts. One is created by the main application and the other iscreated inside a module that is loaded at a later time.

We will refer to the first as application context and the latter as module context.

Now imagine the configuration of the application context to look like this:

<objects>

<object class="com.myclasses.MyObject" id="myObject" scope="singleton"/> <object class="com.myclasses.MyOtherObject" id="myOtherObject" scope="prototype"/>

</objects>

And the module context looking like this:

<objects>

Page 18: Spring Action Script

The Inversion ofControl (IoC) container

12

<object class="com.myclasses.moduleimplementations.MyOtherObject" id="myOtherObject" scope="prototype"/>

</objects>

When the module context is created, we will set the application context as its parent:

var moduleContext:XMLApplicationContext = new XMLApplicationContext("module-context.xml");moduleContext.parent = applicationContext;

The result of this is that, when an object with id myOtherObject is requested from the applicationcontext, you will receive an instance of type com.myclasses.MyOtherObject. However, when yourequest the same object id from the module context, you will receive an instance of typecom.myclasses.moduleimplementations.MyOtherObject.

Next, we change both configurations slightly, add some dependencies and show how to override thosedependencies in a the module configuration.

Here's how the application context's configuration looks:

<objects>

<object class="com.myclasses.MyObject" id="myObject" scope="singleton"/> <object class="com.myclasses.MyOtherObject" id="myOtherObject" scope="prototype"> <property name="dependency" ref="myDependency"/> </object> <object class="com.dependencies.MyDependency" id="myDependency"/>

</objects>

Now requesting an object with id myOtherObject from the application context will yield you an instanceof type com.myclasses.MyOtherObject with a dependency property value set to an instance of typecom.dependencies.MyDependency.

After that we change the module context configuration to look like this:

<objects>

<object class="com.moduledependencies.MyDependency" id="myDependency"/>

</objects>

When we subsequently request an object with id myOtherObject from the module context the result willbe an instance of type com.myclasses.MyOtherObject with a dependency property value set to an instanceof type com.moduledependencies.MyDependency.

Note

Overriding references like this will only work on objects that are scoped as prototype, this isbecause its very probable that the object has already been cached by the parent context whenrequested, and injecting singletons created by the parent with dependencies created by the modulecontext will suddenly put a dependency from the application context on the module context,which is undesirable.

Page 19: Spring Action Script

The Inversion ofControl (IoC) container

13

It is also possible to replace properties with values that are available in the parent context, but this is notenabled by default. To enable this, the "useParentObjectFactoryPostProcessors" on the child context mustbe set to "true". (note: as the name of this property suggests, all ObjectFactoryPostProcessors defined inparent contexts will be applied to the child context. The PropertyPlaceholderConfigurer that is responsiblefor replacing property placeholders is one of them.)

So if the application context holds an external property by the name of prop1 it is possible declare anobject definition in the module context like this:

<objects>

<object class="com.moduleclasses.MyObjectWithAProperty" id="myObjectWithAProperty"> <property name="myProperty" value="{$prop1}"/> </object>

</objects>

Unloading modules

Before unloading a module, be sure to invoke the dispose() method on any application context instancethat is associated with it. This will release all the resources that the context is holding and will make it,and the module, eligible for garbage collection after unloading.

Disposing (releasing) container managed objects

Like the application context, also objects that are managed by the context may need to have a disposalmethod in which they are able to release any resources they are holding. There are two ways of letting thecontext know which methods need to be invoked on an object once the context itself is being disposed:

• The IDisposable interface

• The destroy-method attribute on an object definition

The IDisposable interface

The IDisposable interface is quite small, its signature look like this and is self-explanatory:

public interface IDisposable { function get isDisposed():Boolean; function dispose():void;}

If an object is encountered in the context that implements this interface its dispose() method will be invokedonce the context itself is being disposed.

The destroy-method attribute

To avoid any dependencies on framework classes and interfaces the destroy (for the IDisposable interfacethis would be its dispose() method) method for an object can also be defined in its associated objectdefinition like this:

<object class="..." destroy-method="release"/>

Destroying stage components

The DefaultAutowiringStageProcessor will also be invoked after a component is removed from the stage.It will check the application context for the existence of an object definition for the specified component,and when found, see if a destroy method has been defined. If this is the case, this method will be invoked.

Page 20: Spring Action Script

The Inversion ofControl (IoC) container

14

If an IObjectDefinition wasn't found for the specified component it will check if the component perhapsimplements the IDisposable interface. If so, its dispose() method will be invoked. See the section 'TheIStageDestroyer interface' to learn more about the underlying architecture for this functionality and howto extend it.

Instantiation using a constructor

When creating an object using the constructor approach, all normal classes are usable by and compatiblewith Spring Actionscript. That is, the class being created does not need to implement any specific interfacesor be coded in a specific fashion. Just specifying the object class should be enough. However, depending onwhat type of IoC you are going to use for that specific object, you may need a default (empty) constructor.

When using XML-based configuration metadata you can specify your object class like so:

<object id="exampleObject" class="examples.ExampleObject"/>

<object name="anotherExample" class="examples.ExampleObjectTwo"/>

The Actionscript equivalent of which would be:

var exampleObject:ExampleObject;

var anotherExample:ExampleObjectTwo;

And instantiating one of them by the IoC container would look like this:

var exampleObject:ExampleObject = applicationContext.getObject("exampleObject") as ExampleObject;

Which in regular Actionscript would look like this:

var exampleObject:ExampleObject = new ExampleObject();

The mechanism for supplying arguments to the constructor (if required), or setting properties of the objectinstance after it has been constructed, is described shortly.

Object factory events

The object factory dispatches two events after creating or retrieving an object instance from it. NamelyObjectFactoryEvent.OBJECT_CREATED and ObjectFactoryEvent.OBJECT_RETRIEVED. The first isdispatched right after an object instance has been instantiated and wored by the object factory, the secondright before its returned by the getObject() method. These events are both dispatched by the object factoryand through the EventBus. To learn more about the EventBus, check out the chapter 'The EventBus'.

Instantiation using a static factory method

When defining an object which is to be created using a static factory method, along with the class attributewhich specifies the class containing the static factory method, another attribute named factory-method isneeded to specify the name of the factory method itself. Spring Actionscript expects to be able to call thismethod and get back a live object, which from that point on is treated as if it had been created normallyvia a constructor. One use for such an object definition is to call static factories in legacy code, but it canalso be used to retrieve objects that have been instantiated in MXML and are later pulled into the IoCcontainer to be configured.

The following example shows an object definition which specifies that the object is to be created by callinga factory-method. Note that the definition does not specify the type (class) of the returned object, only theclass containing the factory method. In this example, the getInstance() method must be a static method.

<object id="exampleObject"

Page 21: Spring Action Script

The Inversion ofControl (IoC) container

15

class="examples.ExampleObjectLocator" factory-method="getInstance"/>

Of which the Actionscript equivalent would be:

var exampleObject:ExampleObject = ExampleObjectLocator.getInstance();

Instantiation using a factory method on a different instance

The previous section explained how to use a static factory method on a class, here's how to use a factorymethod on a different instance.

<object id="exampleFactory" class="examples.ExampleObjectFactory"/>

<object id="exampleObject" class="examples.Example" factory-object="exampleFactory" factory-method="getInstance"/>

And for this the Actionscript equivalent would be:

var exampleFactory:ExampleObjectFactory = new ExampleObjectFactory();

var exampleObject:ExampleObject = exampleFactory.getInstance();

Composing MXML-based configuration metadata

Besides an external or embedded configuration defined in an XML file, Spring Actionscript also offersyou the ability to configure your objects through MXML markup. The markup is very similar to the regularXML version, but with some slight differences, we will list them below.

MXML configuration is done by creating one or more MXML files containing objects or object definitionsand loading them via the MXMLApplicationContext class. The difference here with XML configurationsis that you can either define objects explicitly in MXML (e.g. <mx:RemoteObject/>) or implicitly via the<Object/> element. The <Object/> element is the same as using the <object/> in XML configuration.

Declaring the Spring Actionscript namespace

In order to create object definitions in MXML, we let Flex know where to find the components. We dothat by declaring its namespace as follows (in MyConfig.mxml for instance):

<?xml version="1.0"?><Objects xmlns="http://www.springactionscript.org/mxml/config" xmlns:mx="http://www.adobe.com/2006/mxml">

Adding object definitions

Now to add object definitions you add these MXML components as children to the MXML config.

<Object id="remoteObject" clazz={mx.rpc.remoting.mxml.RemoteObject}> <Property name="destination" value="ColdFusion"/> <Property name="concurrency" value="multiple"/> <Property name="makeObjectsBindable" value="false"/> <Property name="showBusyCursor" value="true"/> <Property name="source" value="com.serverside.remote.remoteGateway"/></Object>

Page 22: Spring Action Script

The Inversion ofControl (IoC) container

16

Notice you can define the class of the object with the clazz property which is of type Class. This wayyou will have compile-time checking of the classes you include in your application context. This is anadvantage over regular XML based configuration where you need to make sure that all classes are includedby hand.

Instantiating the MXMLApplicationContext

To use this configuration, all we need to do is create an instance of the MXMLApplicationContext class,add the configurations to it and invoke its load method. This will (asynchronously) load and initialize theapplication context.

private var appContext:MXMLApplicationContext;

public function applicationCompleteHandler(event:FlexEvent):void { appContext = new MXMLApplicationContext(); appContext.addConfig(MyConfig); appContext.addEventListener(Event.COMPLETE, appContext_completeHandler); appContext.load();}

Notice that we pass in the class of the configuration file and not an instance.

Using property placeholders

We can also use property placeholders inside objects and object definitions defined in MXML. This hasthe advantage that we can load properties defined externally into the MXML configuration so we do notneed to recompile the application when these properties need to be changed. A typical example of this isthe configuration of service endpoints.

Below are some examples of property placeholders in MXML configuration.

<Objects xmlns="http://www.springactionscript.org/mxml/config" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:context="org.springextensions.actionscript.ioc.factory.config.*">

<mx:Script> <![CDATA[ import mx.rpc.remoting.mxml.RemoteObject; ]]> </mx:Script>

<context:PropertyPlaceholderConfigurer locations="{['properties.properties.txt', 'server.properties.txt']}"/>

<Object id="string1" clazz="{String}"> <ConstructorArg>$(property1)</ConstructorArg> </Object>

<mx:Array id="propertiesArray"> <mx:String>$(property1)</mx:String> <mx:String>$(property2)</mx:String> <mx:String>$(property3)</mx:String> </mx:Array>

<mx:RemoteObject endpoint="http://$(host):$(port)/$(context-root)/messagebroker/amf"/>

Page 23: Spring Action Script

The Inversion ofControl (IoC) container

17

<mx:RemoteObject id="remoteObject1" endpoint="http://$(host):$(port)/$(context-root)/messagebroker/amf"/>

<mx:RemoteObject id="remoteObject2"> <mx:endpoint>http://$(host):$(port)/$(context-root)/messagebroker/amf</mx:endpoint> </mx:RemoteObject>

<Object id="remoteObjectDefinitionWithPlaceHolders" clazz="{RemoteObject}"> <Property name="endpoint" value="http://$(host):$(port)/$(context-root)/messagebroker/amf"/> </Object>

</Objects>

Using the container

An XMLApplicationContext (or FlexXMLApplicationContext) is essentially nothing more than theinterface for an advanced factory capable of maintaining a registry of different objects and theirdependencies. The XMLApplicationContext, which is also an implementation of the IObjectFactoryinterface, enables you to read object definitions and access them using the getObject() method. Whenusing just the XMLApplicationContext you would create one and read in some object definitions in theXML format as follows:

var applicationContext:XMLApplicationContext = new XMLApplicationContext();applicationContext.addConfigLocation("application-context.xml");applicationContext.addEventListener(Event.COMPLETE, handleComplete);applicationContext.load();

And in the handleComplete method (or any other code which runs after this event has fired) you accessyour object like this:

public function handleComplete(event:FlexEvent):void {

var exampleObject:ExampleObject = applicationContext.getObject("exampleObject") as ExampleObject;}

Basically that is all there is to it. Using getObject(String) you can retrieve instances of your object; theclient-side view of the XMLApplicationContext is simple. The XMLApplicationContext object has justa few other methods, but ideally your application code should never use them... Ideally, your applicationcode should have no calls to the getObject(String) method at all, and thus no dependency on SpringActionscript APIs at all.

DependenciesYour typical enterprise application is not made up of a single object. Even the simplest of applicationswill no doubt have at least a handful of objects that work together to present what the end-user sees as acoherent application. This next section explains how you go from defining a number of object definitionsthat stand-alone, each to themselves, to a fully realized application where objects work (or collaborate)together to achieve some goal (usually an application that does what the end-user wants).

Injecting dependencies

The basic principle behind Dependency Injection (DI) is that objects define their dependencies (that is tosay the other objects they work with) only through constructor arguments, arguments to a factory method,or properties which are set on the object instance after it has been constructed or returned from a factorymethod. Then, it is the job of the container to actually inject those dependencies when it creates the object.

Page 24: Spring Action Script

The Inversion ofControl (IoC) container

18

This is fundamentally the inverse, hence the name Inversion of Control (IoC), of the object itself beingin control of instantiating or locating its dependencies on its own using direct construction of classes, orsomething like the Service Locator pattern.

It becomes evident upon usage that code gets much cleaner when the DI principle is applied, and reaching ahigher grade of decoupling is much easier when objects do not look up their dependencies, but are providedwith them (and additionally do not even know where the dependencies are located and of what concreteclass they are). DI exists in two major variants, namely and .

Constructor Injection

Constructor-based DI is effected by invoking a constructor with a number of arguments, each representinga dependency. Find below an example of a class that could only be dependency injected using constructorinjection. Notice that there is nothing special about this class.

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on a MovieFinder private _movieFinder:MovieFinder;

// a constructor so that the Spring Actionscript container can 'inject' a MovieFinder public SimpleMovieLister(movieFinder:MovieFinder) { _movieFinder = movieFinder; } // business logic that actually 'uses' the injected MovieFinder is omitted...}

Setter Injection

Setter-based DI is realized by calling setter methods or plainly setting properties on your objects afterinvoking a no-argument constructor or no-argument static factory method to instantiate your object. Findbelow an example of a class that can only be dependency injected using pure setter injection. Note thatthere is nothing special about this class... it is plain old Actionscript.

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on the MovieFinder private _movieFinder:MovieFinder;

// a setter method so that the Spring container can 'inject' a MovieFinder public function set movieFinder(value:MovieFinder):void { if (value !== this._movieFinder){ this._movieFinder = movieFinder; } }

// business logic that actually 'uses' the injected MovieFinder is omitted...}

The XMLObjectFactory supports both of these variants for injecting dependencies into objects it manages.(It in fact also supports injecting setter-based dependencies after some dependencies have already beensupplied via the constructor approach.) The configuration for the dependencies comes in the form of anObjectDefinition, which is used together with IPropertyEditor implementations to know how to convertproperties from one format to another. However, most users of Spring Actionscript will not be dealing

Page 25: Spring Action Script

The Inversion ofControl (IoC) container

19

with these classes directly (that is programmatically), but rather with an XML definition file which willbe converted internally into instances of these classes, and used to load an entire Spring IoC containerinstance.

Object dependency resolution generally happens as follows:

• The XMLObjectFactory is created and initialized with a configuration which describes all the objects.(Most Spring Actionscript users use an ApplicationContext implementation that supports XML formatconfiguration files.)

• Each object has dependencies expressed in the form of properties, constructor arguments, or argumentsto the static-factory method when that is used instead of a normal constructor. These dependencies willbe provided to the object, when the object is actually created.

• Each property or constructor argument is either an actual definition of the value to set, or a referenceto another object in the container.

• Each property or constructor argument which is a value must be able to be converted from whateverformat it was specified in, to the actual type of that property or constructor argument. By default Springcan convert a value supplied in string format to all built-in types, such as int, uint, String, Boolean, etc.

The Spring Actionscript container validates the configuration of each object as the container is created,including the validation that properties which are object references are actually referring to validobjects. However, the object properties themselves are not set until the object is actually created. Forthose objects that are singleton-scoped and set to be pre-instantiated (such as singleton objects in anApplicationContext), creation happens at the time that the container is created, but otherwise this is onlywhen the object is requested. When an object actually has to be created, this will potentially cause a graphof other objects to be created, as its dependencies and its dependencies' dependencies (and so on) arecreated and assigned.

You can generally trust Spring Actionscript to do the right thing. It will detect misconfiguration issues, suchas references to non-existent objects and circular dependencies, at container load-time. It will actually setproperties and resolve dependencies as late as possible, which is when the object is actually created. Thismeans that a Spring Actionscript container which has loaded correctly can later generate an exception whenyou request an object if there is a problem creating that object or one of its dependencies. This could happenif the object throws an exception as a result of a missing or invalid property, for example. This potentiallydelayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton objects. At the cost of some upfront time and memory to create these objects beforethey are actually needed, you find out about configuration issues when the ApplicationContext is created,not later. If you wish, you can still override this default behavior and set any of these singleton objects tolazy-initialize (that is not be pre-instantiated).

If no circular dependencies are involved (see sidebar for a discussion of circular dependencies), when oneor more collaborating objects are being injected into a dependent object, each collaborating object is totallyconfigured prior to being passed (via one of the DI flavors) to the dependent object. This means that ifobject A has a dependency on object B, the Spring Actionscript IoC container will totally configure objectB prior to invoking the setter method on object A; you can read 'totally configure' to mean that the objectwill be instantiated (if not a pre-instantiated singleton), all of its dependencies will be set, and the relevantlifecycle methods (such as a configured init method) will all be invoked.

Method invocations

To invoke one or more methods after the object has been constructed by the container add <method-invocation/> elements to the <object/> element.

<object id="exampleObject" class="examples.ExampleObject">

Page 26: Spring Action Script

The Inversion ofControl (IoC) container

20

<method-invocation name="someMethod"/></object>

If the method in question needs any kind of arguments, add them like this:

<object id="exampleObject" class="examples.ExampleObject"> <method-invocation name="someMethod"> <arg value="${externalPropertyName}"/> //External property value <arg ref="anotherExampleObject"/> //Another object instance managed by the container <arg> //Another object instance defined inline <object class="..."/> </arg> </method-invocation></object>

<object id="anotherExampleObject" class="examples.AnotherObject"/>

Some examples

First, an example of using XML-based configuration metadata for setter-based DI. Find below a small partof a Spring Actionscript XML configuration file specifying some object definitions.

<object id="exampleObject" class="examples.ExampleObject">

<!-- setter injection using the nested <ref/> element --> <property name="objectOne"><ref>anotherExampleObject</ref></property>

<!-- setter injection using the neater 'ref' attribute --> <property name="objectTwo" ref="yetAnotherObject"/>

<property name="integerProperty" value="1"/>

<property name="booleanProperty" value="true"/></object>

<object id="anotherExampleObject" class="examples.AnotherObject"/>

<object id="yetAnotherObject" class="examples.YetAnotherObject"/>

public class ExampleObject {

private var _objectOne:AnotherObject; private var _objectTwo:YetAnotherObject; private var _i:int; private var _bool:Boolean;

public function set objectOne(value:AnotherObject):void { if (value !== _objectOne){ _objectOne = value; } }

public function set objectTwo(value:YetAnotherObject):void { if (value !== _objectTwo) _objectTwo = value;

Page 27: Spring Action Script

The Inversion ofControl (IoC) container

21

} }

public function set integerProperty(value:int):void { if (value != _i){ _i = value; } }

public function set booleanProperty(value:Boolean):void { if (value != _bool){ _bool = value; } } }

As you can see, setters have been declared to match against the properties specified in the XML file. Findbelow an example of using constructor-based DI.

<object id="exampleObject" class="examples.ExampleObject">

<!-- constructor injection using the nested <ref/> element --> <constructor-arg> <ref>anotherExampleObject</ref> </constructor-arg> <!-- constructor injection using the neater 'ref' attribute --> <constructor-arg ref="yetAnotherObject"/> <constructor-arg value="1"/>

<constructor-arg value="true"/></object>

<object id="anotherExampleObject" class="examples.AnotherObject"/><object id="yetAnotherObject" class="examples.YetAnotherObject"/>

public class ExampleObject {

private var _objectOne:AnotherObject; private var _objectTwo:YetAnotherObject; private var _i:int; private var _bool:Boolean; public ExampleObject(anotherObject:AnotherObject, yetAnotherObject:YetAnotherObject, i:int, b:Boolean) { _objectOne = anotherobject; _objectTwo = yetAnotherobject; _i = i; _bool = b; }}

Notice, the constructor arguments specified in the object definition will be used to pass in as arguments tothe constructor of the ExampleObject. Now consider a variant of this where instead of using a constructor,Spring Actionscript is told to call a static factory method to return an instance of the object:

Page 28: Spring Action Script

The Inversion ofControl (IoC) container

22

<object id="exampleObject" class="examples.ExampleObjectFactory" factory-method="createInstance"> <constructor-arg ref="anotherExampleObject"/> <constructor-arg ref="yetAnotherObject"/> <constructor-arg value="1"/> </object>

<object id="anotherExampleObject" class="examples.AnotherObject"/><object id="yetAnotherObject" class="examples.YetAnotherObject"/>

public final class ExampleObjectFactory {

// a static factory method; the arguments to this method can be // considered the dependencies of the object that is returned, // regardless of how those arguments are actually used. public static createInstance(anotherObject:AnotherObject, yetAnotherObject:YetAnotherObject, i:int):ExampleObject {

var eb:ExampleObject = new ExampleObject(...); // some other operations... return eb; }}

Note that arguments to the static factory method are supplied via elements, exactly the same as if aconstructor had actually been used. Also, it is important to realize that the type of the class being returnedby the factory method does not have to be of the same type as the class which contains the static factorymethod.

Dependencies and configuration in detail

As mentioned in the previous section, object properties and constructor arguments can be defined as eitherreferences to other managed objects (collaborators), or values defined inline. Spring Actionscript's XML-based configuration metadata supports a number of sub-element types within its and elements for justthis purpose.

Straight values (primitives, Strings, etc.)

The element specifies a property or constructor argument as a human-readable string representation. Asmentioned previously, IPropertyEditor implementations are used to convert these string values from aString to the actual type of the property or argument.

<object id="amfChannel" class="mx.messaging.channels.AMFChannel"> <constructor-arg> <value>my-amf</value> </constructor-arg> <constructor-arg> <value>http://{server.name}:{server.port}/flex2gateway/</value> </constructor-arg> <property name="pollingEnabled"> <value>false</value> </property></object>

The and elements also support the use of the 'value' attribute, which can lead to much more succinctconfiguration. When using the 'value' attribute, the above object definition reads like so:

Page 29: Spring Action Script

The Inversion ofControl (IoC) container

23

<object id="amfChannel" class="mx.messaging.channels.AMFChannel"> <constructor-arg value="my-amf"/> <constructor-arg value="http://{server.name}:{server.port}/flex2gateway/"/> <property name="pollingEnabled" value="false"/></object>

References to other objects (collaborators)

The ref element is the final element allowed inside a or definition element. It is used to set the valueof the specified property to be a reference to another object managed by the container (a collaborator).As mentioned in a previous section, the referred-to object is considered to be a dependency of the objectwho's property is being set, and will be initialized on demand as needed (if it is a singleton object it mayhave already been initialized by the container) before the property is set. All references are ultimately justa reference to another object.

Specifying the target object by using the tag is the most general form.

<ref>myTargetObject</ref>

Inner objects

An element inside the or elements is used to define a so-called inner object. An inner object definitiondoes not need to have any id defined, and it is best not to even specify any id value because the id valuesimply will be ignored by the container.

<object id="outer" class="..."> <!-- instead of using a reference to a target object, simply define the target object inline --> <property name="target"> <object class="com.example.Person"> <!-- this is the inner object --> <property name="name" value="Fiona Apple"/> <property name="age" value="25"/> </object> </property></object>

Note that in the specific case of inner objects, the 'scope' flag and any 'id' attribute are effectively ignored.Inner objects are always anonymous and they are always scoped as prototypes. Please also note that it isnot possible to inject inner objects into collaborating objects other than the enclosing object.

Collections

The , , and <vector/> elements allow properties and arguments of the Actionscript collection typeArray, ArrayCollection, Dictionary and Vector, respectively, to be defined and set.

Be aware that the array-collection type can only be used in a Flex based application (using theFlexXMLApplicationContext) object since it is part of the framework.

Also be careful only to use the Vector type in applications that are made for Flash player version 10 orhigher.

<object id="moreComplexObject" class="example.ComplexObject"> <property name="adminEmails"> <dictionary> <entry key="administrator" value="[email protected]"/>

Page 30: Spring Action Script

The Inversion ofControl (IoC) container

24

<entry key="support" value="[email protected]"/> <!-- or a more verbose way of defining an entry --> <entry> <key>development</key> <value>[email protected]</value> </entry> </dictionary> </property>

<property name="someList"> <array> <value>a list element followed by a reference</value> <value><ref object="myOtherObject" /></value> </array> </property>

<!-- Only use this in a Flex based application --> <property name="someOtherList"> <array-collection> <value>a list element followed by a reference</value> <value><ref object="myOtherObject" /></value> </array-collection> </property>

<!-- Only use this in an application made for Flash player 10 and higher --> <property name="vectorProperty"> <vector type="String"> <value>string1</value> <value>string2</value> <value>string3</value> <value>string4</value> </vector> </property>

</object>

Note

The nested element style used this initial example tends to become quite verbose. Fortunately,there are attribute shortcuts for most elements, which you can read about in Shortcuts and otherconvenience options for XML-based configuration metadata.

Injecting the application context using the 'this' reference

Injecting the application context can be achieved by using the id 'this' as reference:

<method-invocation name="someMethod"> <arg ref="this"/></method-invocation>

This works for property chains on the application context as well, for example:

<method-invocation name="someMethod"> <arg ref="this.applicationDomain"/>

Page 31: Spring Action Script

The Inversion ofControl (IoC) container

25

</method-invocation>

Shortcuts and other convenience options for XML-basedconfiguration metadata

The configuration metadata shown so far is a tad verbose. That is why there are several options availablefor you to limit the amount of XML you have to write to configure your components. The first is a shortcutto define values and references to other objects as part of a definition. The second is slightly differentformat of specifying properties altogether.

XML-based configuration metadata shortcuts

The , , and elements all support a 'value' attribute which may be used instead of embedding a full element.Therefore, the following:

<property name="myProperty"> <value>hello</value></property>

<constructor-arg> <value>hello</value></constructor-arg>

<entry key="myKey"> <value>hello</value></entry>

are equivalent to:

<property name="myProperty" value="hello"/>

<constructor-arg value="hello"/>

<entry key="myKey" value="hello"/>

Using depends-on

For most situations, the fact that an object is a dependency of another is expressed by the fact that oneobject is set as a property of another. This is typically accomplished with the element in XML-basedconfiguration metadata. For the relatively infrequent situations where dependencies between objects areless direct, the 'depends-on' attribute may be used to explicitly force one or more objects to be initializedbefore the object using this element is initialized. Find below an example of using the 'depends-on' attributeto express a dependency on a single object.

<object id="objectOne" class="ExampleObject" depends-on="manager"/>

<object id="manager" class="ManagerObject" />

If you need to express a dependency on multiple objects, you can supply a list of object names as the valueof the 'depends-on' attribute, with commas, whitespace and semicolons all valid delimiters, like so:

<object id="objectOne" class="ExampleObject" depends-on="manager,accountDao"> <property name="manager" ref="manager" /></object>

Page 32: Spring Action Script

The Inversion ofControl (IoC) container

26

<object id="manager" class="ManagerObject" /><object id="accountDao" class="x.y.as.AccountDao" />

Ensuring dependency injection with dependency check

Spring Actionscript has 4 different validation modes to check if properties have been on an object. Thedifferent dependency check modes are 'none', 'simple', 'object', and 'all'. The default mode is 'none', sothere isn't any dependency check validation unless explicitly configured. All values being checked musthave been set in the configuration file or by autowiring. If a class has any defaults or fields that don't needto be set, the dependency check modes won't be of any use.

Table 2.2. Autowiring modes

Mode Explanation

none No dependency checking. This is the default.

simple Dependency check for primitives and collections.

object Dependency check for objects (collaborators).

all Dependency check for primitives, collections, andobjects (collaborators).

The 'simple' mode checks that all primitive and collection values have been set. The 'object' mode checksthat all collaborators (objects) have been set. The 'all' mode checks for everything that the 'simple' and'object' modes do.

Lazily-instantiated objects

The default behavior for IApplicationContext implementations is to eagerly pre-instantiate all singletonobjects at startup. Pre-instantiation means that an IApplicationContext will eagerly create and configure allof its singleton objects as part of its initialization process. Generally this is a good thing, because it meansthat any errors in the configuration or in the surrounding environment will be discovered immediately (asopposed to possibly hours down the line).

However, there are times when this behavior is not what is desired. If you do not want a singleton objectto be pre-instantiated when using an IApplicationContext, you can selectively control this by marking anobject definition as lazily-initialized. A lazily-initialized object indicates to the IoC container whether ornot an object instance should be created at startup or when it is first requested.

When configuring objects via XML, this lazy loading is controlled by the 'lazy-init' attribute on theelement; for example:

<object id="lazy" class="com.foo.ExpensiveToCreateObject" lazy-init="true"/>

<object name="not.lazy" class="com.foo.AnotherObject"/>

When the above configuration is consumed by an IApplicationContext, the object named 'lazy' will notbe eagerly pre-instantiated when the IApplicationContext is starting up, whereas the 'not.lazy' object willbe eagerly pre-instantiated.

One thing to understand about lazy-initialization is that even though an object definition may be markedup as being lazy-initialized, if the lazy-initialized object is the dependency of a singleton object that isnot lazy-initialized, when the IApplicationContext is eagerly pre-instantiating the singleton, it will haveto satisfy all of the singletons dependencies, one of which will be the lazy-initialized object! So don'tbe confused if the IoC container creates one of the objects that you have explicitly configured as lazy-

Page 33: Spring Action Script

The Inversion ofControl (IoC) container

27

initialized at startup; all that means is that the lazy-initialized object is being injected into a non-lazy-initialized singleton object elsewhere.

A graphical overview of the getObject() flow

See below for a graphical overview of the program flow that happens after you call the getObject() methodon an application context instance.

A graphical overview of the wiring flow of an object

See below for a graphical overview of the program flow that happens when an object is being wired bythe application context.

Autowiring collaborators

The Spring Actionscript container is able to autowire relationships between collaborating objects. Thismeans that it is possible to automatically let Spring Actionscript resolve collaborators (other objects)for your object by inspecting the contents of the ObjectDefinition. The autowiring functionality has fivemodes. Autowiring is specified per object and can thus be enabled for some objects, while other objects willnot be autowired. Using autowiring, it is possible to reduce or eliminate the need to specify properties orconstructor arguments, thus saving a significant amount of typing. When using XML-based configurationmetadata, the autowire mode for a object definition is specified by using the autowire attribute of theelement. The following values are allowed:

Table 2.3. Autowiring modes

Mode Explanation

no No autowiring at all. Object references must bedefined via a ref element. This is the default, andchanging this is discouraged for larger deployments,since explicitly specifying collaborators givesgreater control and clarity. To some extent, it isa form of documentation about the structure of asystem.

byName Autowiring by property name. This option willinspect the container and look for an object namedexactly the same as the property which needs tobe autowired. For example, if you have an objectdefinition which is set to autowire by name, and itcontains a master property, Spring Actionscript willlook for an object definition named master, anduse it to set the property.

byType Allows a property to be autowired if there is exactlyone object of the property type in the container. Ifthere is more than one, a fatal exception is thrown,and this indicates that you may not use byTypeautowiring for that object. If there are no matchingobjects, nothing happens; the property is not set.

Page 34: Spring Action Script

The Inversion ofControl (IoC) container

28

Mode Explanation

constructor This is analogous to byType, but applies toconstructor arguments. If there isn't exactly oneobject of the constructor argument type in thecontainer, a fatal error is raised.

autodetect Chooses constructor or byType throughintrospection of the object class. If a default(parameterless) constructor is found, the byTypemode will be applied.

Note that explicit dependencies in and settings always override autowiring. Please also note that it is notcurrently possible to autowire so-called simple properties such as primitives, Strings, and Classes(and arrays of such simple properties). (This is by-design and should be considered a feature.) When usingeither the byType or constructor autowiring mode, it is possible to wire arrays. In such cases all autowirecandidates within the container that match the expected type will be provided to satisfy the dependency.

It is important to understand the various advantages and disadvantages of autowiring. Some advantagesof autowiring include:

• Autowiring can significantly reduce the volume of configuration required. However, mechanisms suchas the use of a object template (discussed elsewhere in this chapter) are also valuable in this regard.

• Autowiring can cause configuration to keep itself up to date as your objects evolve. For example, if youneed to add an additional dependency to a class, that dependency can be satisfied automatically withoutthe need to modify configuration. Thus there may be a strong case for autowiring during development,without ruling out the option of switching to explicit wiring when the code base becomes more stable.

Some disadvantages of autowiring:

• Autowiring is more magical than explicit wiring. Although, as noted in the above table, SpringActionscript is careful to avoid guessing in case of ambiguity which might have unexpected results, therelationships between your Spring Actionscript-managed objects are no longer documented explicitly.

• Wiring information may not be available to tools that may generate documentation from a SpringActionscript container.

Another issue to consider when autowiring by type is that multiple object definitions within the containermay match the type specified by the setter method or constructor argument to be autowired. For arrays,collections, or maps, this is not necessarily a problem. However for dependencies that expect a singlevalue, this ambiguity will not be arbitrarily resolved. Instead, if no unique object definition is available,an Exception will be thrown. You do have several options when confronted with this scenario. First,you may abandon autowiring in favor of explicit wiring. Second, you may designate that certain objectdefinitions are never to be considered as candidates by setting their 'autowire-candidate' attributes to'false' as described in the next section. Third, you may designate a single object definition as the primarycandidate by setting the 'primary' attribute of its element to 'true'.

When deciding whether to use autowiring, there is no wrong or right answer in all cases. A degree ofconsistency across a project is best though; for example, if autowiring is not used in general, it might beconfusing to developers to use it just to wire one or two object definitions.

Note

If a property is of type IApplicationContext or ApplicationDomain the application contextinstance or its ApplicationDomain will be injected when autowiring byType.

Page 35: Spring Action Script

The Inversion ofControl (IoC) container

29

A graphical overview of the autowiring flow of an object

As you can see its possible to combine the different types of wiring, the types take this override precedence:

1. Wire properties explicitly defined in the IObjectDefinition from the configuration

2. Wire properties by name or type as defined by the class annotations (metadata)

3. Wire properties by name or type as defined in the IObjectDefinition

Autowiring objects using annotations

A different way of letting the Spring Actionscript container know how to configure an object is byadding specific metadata annotations to the component's sources. Obviously this is only possible whenthe developer actually has access to the source code. Thus, this solution does not apply to the situation inwhich you'd like to autowire existing objects, such as the ones that are already part of the Flex framework.

The simplest way to inject a property by type is by decorating its source like this:

public class ExampleComponent extends UIComponent {

[Autowired] public var modelInstance:IModelLocator;

public function ExampleComponent() { super(); }

}

Once this component is created (or added to the stage), the Spring Actionscript container will searchin its container an object of type IModelLocator and assign it to the modelInstance property of theExampleComponent.

Wiring by name is also possible, all that is needed is a little extra metadata:

public class ExampleComponent extends UIComponent {

[Autowired(mode='byName')] public var modelInstance:IModelLocator;

public function ExampleComponent() { super(); }

}

Now the Spring Actionscript container will look for an object in its configuration with the id'modelInstance' and assign this to the modelInstance property of the ExampleComponent.

There's another way of injecting by name, suited for the situation where the name of the property and theid in the configuration don't match. What if the IModelLocator instance described in the configuration hasan id called 'modelLocator' and for some reason this can't be easily changed?

Page 36: Spring Action Script

The Inversion ofControl (IoC) container

30

Easy, you can define the exact name in the metadata as follows:

public class ExampleComponent extends UIComponent {

[Autowired(name='ModelLocator')] public var modelInstance:IModelLocator;

public function ExampleComponent() { super(); }

}

Note

When using the Autowired metadata do not forget to add these compiler settings to your Flexproject: -keep-as3-metadata += Autowired.

Apparently Flexbuilder on OSX behaves slightly different and needs you to add the metadataone-by-one and quoted, like this: -keep-as3-metadata "Autowired".

Binding an object property to a property of an object in thecontainer

To keep your objects as decoupled as possible it might be preferred not to inject the modelInstance intoit, but just a certain property of the model. Since the data in the model is subject to change (usually it ispopulated with data retrieved from remote method invocations), it would also be good to bind your viewto the model.

This can be achieved by using the following metadata:

public class ExampleProductListComponent extends UIComponent {

[Autowired(name='ModelLocator',property='products')] public var products:ArrayCollection;

public function ExampleProductListComponent() { super(); }

}

This example assumes that the ModelLocator object has a property called 'products' of typeArrayCollection. A binding is established between these two objects, so when the products ArrayCollectionin the model in updated, so will the component.

The property value can also be a chain of objects, so this will work as well:

public class ExampleProductListComponent extends UIComponent {

[Autowired(name='ModelLocator',property='productManager.products')] public var products:ArrayCollection;

public function ExampleProductListComponent() {

Page 37: Spring Action Script

The Inversion ofControl (IoC) container

31

super(); }

}

Note

Since this functionality makes use of Flex binding it is therefore only available through theFlexXMLApplicationContext.

Injecting an object property with an external property value

Its also possible to inject the value of an external property into a stage component. (If you want to knowmore about external properties read the section 'External property files').

To do this add metadata to your source like this:

public class ExampleComponent extends UIComponent {

[Autowired(externalProperty='currentURL')] public var websiteURL:String;

public function ExampleComponent() { super(); }

}

Where the value of the propertyName metadata argument key matches the key in one of the loadedproperty files.

Instantiating a Class with [Autowired] annotations

When a Class only uses [Autowired] annotations to define its dependencies it is a waste to have to addan object definition for these classes to the XML configuration. Therefore its also possible to directly letthe application context instantiate the class:

var example:ExampleObject = applicationContext.createInstance(ExampleObject);

The createInstance() method will instantiate the Class and pass it through the rest of the wiring pipeline,so also object post processing and metadata wiring.

Autowiring stage components

Spring Actionscript has one situation when used in conjunction with the Flex framework which differs fromother Spring implementations. This is when visual components (often declared as MXML components)need to be autowired. In this case the container can't be responsible for the actual creation of thecomponents, so it is deferred back to the Flex application.

Concretely, we want to retain the expressiveness of MXML declaration and combine it with the IoCcapabilities of Spring Actionscript.

For example, given this (very simple) piece of MXML markup:

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

Page 38: Spring Action Script

The Inversion ofControl (IoC) container

32

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:custom="http://www.mydomain.com/flexcomponents" layout="vertical">

<custom:OrderView myDependency="{this.applicationModel}"/>

</mx:Application>

In this case the application model instance is directly injected through concrete markup. In a lot of casesthis is perfectly acceptable, but Spring Actionscript offers a little extra flexibility by being able to injectthe model instance at runtime.

Spring Actionscript is able to perform these dependency injections by hooking an event listener into theEvent.ADDED_TO_STAGE event and process the components right after they have been added to thestage.

To make use of the metadata processor that handles all of the functionality described in the followingsections add this to the XML configuration:

<object id="autowiringStageProcessor" class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor"/>

There are several ways of configuration for this stituation, in the following sections we will look at themone by one.

Note

Spring Actionscript will wait until the container has finished loading and parsing its configuration,after which it will loop through the entire current displaylist once to autowire the already createdstage components.

Note

If you'd like to learn more about the underlying architecture of stage wiring and how to extendit, check out the section 'The IStageProcessor interface'.

Note

You can force the autowiring process to ignore the metadata on a given object by setting its skip-metadata attribute to true. This will yield a small performance boost.

Autowiring stage components in a pure actionscript project

The FlexXMLApplicationContext take care all by itself of creating the necessary objects to facilitate stagewiring. In a pure actionscript situation, however, a little bit of extra code is required. The stage wiringsystem needs at one point to have a reference to the stage. In case of Flex this is easy, the SystemManagersingleton is used. In case of pure actionscript, the stage property will have to be set manually before anyXMLApplicationContext has been created. Add this code before the context's instantiation:

FlashStageProcessorRegistry.getInstance().stage = stage; //this being a valid reference to the flash player's stagecontext = new XMLApplicationContext('application-context.xml');context.addEventListener(Event.COMPLETE, completeHandler);context.load();//etc...

Page 39: Spring Action Script

The Inversion ofControl (IoC) container

33

Autowiring stage components using XML configuration

Stage components can be configured using metadata that describes the desired injections, but this can alsobe entirely expressed in XML metadata. Here is how to configure the ExampleComponent to be autowiredby type:

<object id="exampleComponent" class="classes.components.ExampleComponent" autowire="byType" singleton="false"/>

In this example we assume that the ExampleComponent instance on the stage has an id with the valueexampleComponent.

Let us be clear immediately though, autowiring a stage component in this way is a bad idea. The SpringActionscript container will, in this case, actually loop through every property of the ExampleComponentinstance and try to find a matching wiring candidate in the container. This will very quickly become veryslow, so please regard this example as a proof of concept but don't use it in any actual production code.

Autowiring by name is almost the same and the same warning as the wiring by type is applicable: don'tdo it.

<object id="exampleComponent" class="classes.components.ExampleComponent" autowire="byName" singleton="false"/>

The most obvious way of configuring the ExampleComponent is by simply injecting the property explicitlylike this:

<object id="exampleComponent" class="classes.components.ExampleComponent" singleton="false"> <property name="modelInstance" ref="ModelLocator"/></object>

Note

Do take notice of the singleton="false" attribute on each of these configuration examples.Don't forget to add this value to each and every stage component definition entry. SpringActionscript defaults an object definition to a singleton scope and instantiates every singleton inthe configuration at startup. Failing to add the singleton="false" attribute will result in SpringActionscript creating a whole bunch of stage component instances unnecessarily.

How to determine which stage components are eligible forconfiguration

The Event.ADDED_TO_STAGE event is fired a lot during the lifetime of a Flex application. It istherefore paramount to make the event handler as efficient as possible and thus determine as quickly aspossible if the component in question is eligible for configuration or not.

Again Spring Actionscript offers several ways to do this. First of all we introduce the IObjectSelectorinterface. This interface is a modest one:

public interface IObjectSelector { function approve(object:Object):Boolean;}

An object that implements this interface is responsible for determining whether a specific instance iseligible for autowiring. The how and why is up to the implementation. Spring Actionscript by default usesa FlexStageDefaultObjectSelector instance.

The FlexStageDefaultObjectSelector is a fairly simple implementation of the IObjectSelector interfacethat, by default, rejects any component whose namespace starts with either 'flash.*' or 'mx.*', after that it

Page 40: Spring Action Script

The Inversion ofControl (IoC) container

34

checks if the specified object inherits from UIComponent, if not, the object is rejected as well. (This is toprevent embedded images in skins from clogging up the wiring pipeline).

Once a component is approved by the IObjectSelector it will be ready for configuration, the exact wiringinformation will be determined by either reading the metadata or retrieving an object definition from theconfiguration.

Naturally, Spring Actionscript also offers you the possibility to easily implement and plug in your ownIObjectSelector implementations. Let's have a look at how this works.

Creating and using a custom IObjectSelector implementation

By default the DefaultAutowiringStageProcessor is fitted with a FlexStageDefaultObjectSelector toapprove or reject stage components that have been added to the stage. To override this behaviour youcan create your own IObjectSelector implementation and add an object definition for it in the XMLconfiguration. A custom implementation might look something like this in your configuration:

<object id="flexStageObjectSelector" class="com.classes.objectselectors.MyCustomObjectSelector"/>

To use this IObjectSelector instance you must also override the default autowiring processor with a newinstance and assign this object selector to it:

<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor"> <property name="objectSelector" ref="flexStageObjectSelector"/></object>

How to determine which object definition to use for which stagecomponent

Once a stage component is approved by an IObjectSelector instance the DefaultAutowiringStageProcessormight need an object definition to be able to pass it on to the wire() method of the object factory (thisvalue can also be null, for the case where the components are solely configured with annotations). Thisparticular task is bestowed upon the IObjectDefinitionResolver interface. Like the IObjectSelector, thisinterface is a simple one:

public interface IObjectDefinitionResolver { function resolveObjectDefinition(object:*):IObjectDefinition;}

An object that implements this interface is responsible for retrieving, or creating, an object definition fora given object instance. Spring Actionscript by default offer the DefaultObjectDefinitionResolver class.This implementation uses different strategies to retrieve the appropriate IObjectDefinition for an object.First of all it uses the value of its objectIdProperty property to find the object definition by name. Bydefault the value of this property is 'name'. This means that if a stage component is being examined whosename property has a value of 'MyStageComponent', the DefaultObjectDefinitionResolver will look foran object definition with an id of 'MyStageComponent'. If the object definition can't be found it willfall back on trying to find an object definition by type, but only if the lookupByType property on theDefaultObjectDefinitionResolver is set to true.

If both of these options fail the DefaultObjectDefinitionResolver will return null. This will happen in thecase that a stage component has been decorated with autowiring metadata and has no further use for anobject definition. Of course, the both can combined as well, but its open to discussion whether this isadvisable. To use the DefaultObjectDefinitionResolver use this XML configuration:

<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor"> <property name="objectDefinitionResolver">

Page 41: Spring Action Script

The Inversion ofControl (IoC) container

35

<object id="defaultObjectDefinitionResolver" class="org.springextensions.actionscript.stage.DefaultObjectDefinitionResolver"/> </property></object>

Just like the IObjectSelector its also possible to plug in your own IObjectDefinitionResolverimplementation. What follows is how to do this.

Creating and using a custom IObjectDefinitionResolver implementation

By default the DefaultAutowiringStageProcessor is fitted with a DefaultObjectDefinitionResolver toretrieve an appropriate IObjectDefinition instance for a given object. To override this behaviour you cancreate your own IObjectDefinitionResolver implementation and add an object definition for it in the XMLconfiguration. So you can simply add your IObjectDefinitionResolver implementation as follows:

<object id="flexStageObjectDefinitionResolver" class="com.classes.definitionresolvers.MyCustomDefinitionResolver"/>

To use this IObjectDefinitionResolver instance you must also override the default autowiring processorwith a new instance and assign this object selector to it:

<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor"> <property name="objectSelector" ref="flexStageObjectSelector"/> <property name="objectDefinitionResolver" ref="flexStageObjectDefinitionResolver"/></object>

Optimizing the stage component selection process

The Event.ADDED_TO_STAGE that is being used by the stage wiring system gets dispatched a LOTin the lifetime of a Flex application. It is therefore paramount to keep the selection and wiring process asoptimized as possible. First of all it is recommended to use a custom IObjectSelector as much as possible.The one created by default by the DefaultAutowiringStageProcessor, the FlexStageDefaultObjectSelector,uses this code for the selection process:

public function approve(object:Object):Boolean {

var className:String; try { className = getQualifiedClassName(object); } catch (e:*) { return false; }

if (className.search("^spark.*") > -1 || className.search("^flash.*") > -1 || className.search("^mx.*") > -1 || className.indexOf("_") > -1) { return false; }

if (!(object is UIComponent)) { return false; }

try { ObjectUtils.getClass(object); return true; } catch (e:*) { }

Page 42: Spring Action Script

The Inversion ofControl (IoC) container

36

return false;}

These are quite a few calls for every component being added to the stage. Now, imagine a situationwhere you know beforehand that only components that implement a specific marker interface need to beautowired. In that case you can implement a much simpler selection process. Let's say the marker interfaceis called IAutowiredComponent, then the implementation of the approve() method needs to be simply this:

public function approve(object:Object):Boolean { return (object is IAutowiredComponent);}

Injecting stage components into other objects

It is also possible to inject a stage component into a 'regular' object. To achieve this Spring Actionscriptoffers an IStageProcessor implementation called GenericStageProcessor. What this stageprocessor does isit will assign a component that was added to the stage to a previously configured object. This assignmentcan either be done by property assignement or method invocation.

To determine which object will 'receive' the selected components the GenericStageProcessor has a propertycalled targetObject. This targetObject is a reference to another object that is declared in the applicationcontext, so to configure the GenericStageProcessor you will need to add this markup to your applicationcontext:

<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor"> <property name="targetObject" ref="stageComponentRegistry"/></object>

Let's say this stageComponentRegistry object has a method called registerComponent that is used togather a list of stage components. To have the GenericStageProcessor invoke this method with each stagecomponent it approves, add this bit of markup:

<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor"> <property name="targetObject" ref="stageComponentRegistry"/> <property name="targetMethod" value="registerComponent"/></object>

Right, that was easy so far. Now all we need to do is put the mechanism in place that willdetermine which stage components will be passed to the stageComponentRegistry instance. For thiswe need to declare an IObjectSelector instance, in this example we use one of the pre-existingimplementations offered by Spring Actionscript called ClassBasedObjectSelector. This IObjectSelectorapproves objects based on their classname and uses regular expressions to evaluate these names. To addthe ClassBasedObjectSelector to your application add this markup:

<object class="org.springextensions.actionscript.ioc.wire.ClassBasedObjectSelector" id="registrySelector"> <property name="approveOnMatch" value="true"/> <property name="classRegexpArray"> <value> <array> <value>com\.components*</value> </array> </value> </property></object>

Page 43: Spring Action Script

The Inversion ofControl (IoC) container

37

Change the regular expression pattern to suit your own needs.

After this all we need to do is assign this selector to the GenericStageProcessor like this:

<object class="org.springextensions.actionscript.stage.GenericStageProcessor" id="stageProcessor"> <property name="targetObject" ref="stageComponentRegistry"/> <property name="targetMethod" value="registerComponent"/> <property name="objectSelector" ref="registrySelector"/></object>

And that's it, from now on every component that is added to the stage and has a class name that starts withcom.components will be passed to the registerComponent method of the stageComponentRegistry object.

To make life a little easier by reducing the amount of markup for the GenericStageProcessor SpringActionscript also offers a custom namespace with some special markup for this class. See The StageProcessing schema for more details.

Implementing custom autowiring support using theIAutowireProcessor interface

Spring Actionscript wouldn't be Spring Actionscript if it didn't allow you to implement your own brandof autowiring. Naturally the Spring Actionscript team is of the opinion that the offered autowiringfunctionality is about as broad as one can imagine, but should the need arise to step outside the confinesof Spring Actionscript autowiring than this entirely possible.

In this particular case the IAutowireProcessor is your friend. And as you are used to, its not a verycomplicated one, see for yourself:

public interface IAutowireProcessor {

function autoWire(object:Object, objectDefinition:IObjectDefinition, objectName:String=null):void;

function preprocessObjectDefinition(objectDefinition:IObjectDefinition):void;}

The first method is the main autoWire() method that is invoked by the object container immediately aftercreation. (see 'A graphical overview of the wiring flow of an object' for more details.)

The second method is invoked by the container right before an object is actually created, so this wouldtypically be a good moment to change any kind of constructor argument autowiring or perhaps change theautowiring strategy of the current IObjectDefinition based on some pre-configured logic.

As you can see in the default implementation used by the AbstractObjectFactory, (fittingly titledDefaultAutowireProcessor),it is also possible for your own IAutowireProcessor implementation toinclude the IObjectFactoryAware interface. If your instance implements this particular interface it willautomatically be injected by the object factory instance to which the IAutowireProcessor is assigned.

Now, after you've created your own implementation, its time to hook it up to the object container, typicallythis would be done something like this:

var xmlApplicationContext:XMLApplicationContext = new XMLApplicationContext();xmlApplicationContext.autowireProcessor = new MyCustomAutowireProcessor();

After that your own autowiring logic will be performed on any object created by theXMLApplicationContext instance.

Page 44: Spring Action Script

The Inversion ofControl (IoC) container

38

Note

Consequently, when you don't need the autowiring functionality at all in your application, it mightbe an idea to set the autowireProcessor property to null as this will yield a small performancebenefit.

The IStageProcessor interface

The underlying architecture for stage component wiring can be easily extended, the basicsare very simple: An IStageProcessorRegistry implementation (in most cases that would be theFlexXMLApplicationContext) adds an event listener to the SystemManager and listens for anEvent.ADDED_TO_STAGE event to be fired. After that an IObjectSelector instance determines whetherthe DefaultAutowiringStageProcessor should process the object or not.

Here's a quick overview of how the IStageProcessorRegistry, IObjectSelector and IStageProcessorinterfaces work together:

This pattern can naturally be used to perform other kinds of operations on stage components.

Note

To automatically register any IStageProcessor instances declared in the configuration, aFlexXMLApplicationContext instance creates a StageProcessorFactoryPostprocessor for itself.

As you can see the DefaultAutowiringStageProcessor is an implementation of the IStageProcessorinterface, this interface is, as usual, fairly simple:

public interface IStageProcessor {

function get selector():IObjectSelector;

function set selector(value:IObjectSelector):void;

function process(object:Object):Object;}

The IObjectSelector instance can be shared among IStageProcessor instances, so that way only oneIObjectSelector's approval can invoke multiple IStageProcessor process() methods. So, if you wantthe same IObjectSelector to also trigger your custom IStageProcessor, add their configurations like this:

<object class="org.springextensions.actionscript.ioc.wire.ClassBasedObjectSelector" id="globalSelector"> <property name="approveOnMatch" value="true"/> <property name="classRegexpArray"> <value> <array> <value>com\.components*</value> </array> </value> </property></object>

<object class="org.springextensions.actionscript.stage.DefaultAutowiringStageProcessor" id="defaultAutowiringStageProcessor"> <property name="objectSelector" ref="globalSelector"/>

Page 45: Spring Action Script

The Inversion ofControl (IoC) container

39

<property name="objectDefinitionResolver" ref="flexStageObjectDefinitionResolver"/></object>

<object class="com.classesMyCustomStageProcessor" id="myCustomStageProcessor"> <property name="objectSelector" ref="globalSelector"/></object>

Although probably you will need different approval strategies for each IStageProcessor instance, in thatcase declare separate IObjectSelector instances per IStageProcessor.

Note

For another example of an IStageProcessor implementation, see the section 'Injecting stagecomponents into other objects'.

The LocalizationStageProcessor class

A good example of an IStageProcessor implementation is the LocalizationStageProcessor, found in thepackage. This class enables you to assign resource values to stage components at runtime based on thevalue of the component's id. To use this class add this bit of markup to your configuration:

<object id="resourceManager" class="mx.resources.ResourceManager" factory-method="getInstance"/>

<object id="localizationProcessor" class="org.springextensions.actionscript.localization.LocalizationStageProcessor"> <property name="resourceManager" ref="resourceManager"/> <property name="bundleName" value="mySampleResources"/><!-- change this to the name of your bundle --></object>

The LocalizationStageProcessor uses a PropertyValueBasedObjectSelector instance by default, thisselector approves only components whose id property is set. When the LocalizationStageProcessorreceives a component it will use its id as a base name to look up resource strings and assign these to arbitraryproperties on the component. For instance, if a button is added to the stage with an id called 'myButton'and you want the label property on the button to be set to 'Click me' add a resource string like this:

myButton_label=Click me

If you want the tooltip property to be set to 'Click this button for fun!', then add a resource string like this:

myButton_toolTip=Click this button for fun!

By default the LocalizationStageProcessor looks for resource strings for the following property names:text, label, toolTip, prompt, dataProvider, title, headerText.

To add to this list, or replace it with your own array of names, use the LocalizationStageProcessor'sresourceSuffixes property.

There is a sample project that demonstrates the LocalizationStageProcessor class, you can take a look byfollowing this .

Note

To learn more about flex resource management, follow this .

The SimpleSecurityStageProcessor class

The stage processing pattern can also be used to add role and rights based security to anapplication. For this specific task Spring Actionscript offers the package. Part of this package is the

Page 46: Spring Action Script

The Inversion ofControl (IoC) container

40

SimpleSecurityStageProcessor which is able to create a SimpleStageSecurityManager for specifiedcomponents after they have been added to the stage.

To add the SimpleSecurityStageProcessor to your configuration add this bit of markup:

<object id="securityProcessor" class="org.springextensions.actionscript.security.SimpleSecurityStageProcessor"/>

Now just adding this stage processor to your application context isn't going to achieve much. Somehowthe data needed to create what kind of SimpleStageSecurityManager for which stage component needs tobe fed to the stage processor.

The SimpleSecurityStageProcessor creates a SimpleSecurityManagerFactory instance for itself by default,this ISecurityManagerFactory implementation uses a Dictionary of MembershipAccessData to hold themembership information for stage components. The key of the Dictionary is the id of the stage componentto which the MembershipAccessData is applicable. The MembershipAccessData determines which rolesand rights are applicable and what strategy is to be used to restrict access to the component.

For example, to assign the right called 'canClickButton' to a Button instance with the id 'myButton' and tohave the button be invisible when access is restricted, create a MembershipAccessData instance like this:

var md:MembershipAccessData = new MembershipAccessData();md.rights.push("canClickButton");md.accessStrategy = AccessStrategy.VISIBLE;

To have this membership data be used by the stage processor, assign it like this:

var sp:SimpleSecurityStageProcessor = _applicationContext.getObject("securityProcessor") as SimpleSecurityStageProcessor;(sp.securityManagerFactory as SimpleSecurityManagerFactory).membershipData["myButton"] = md;

This will cause the SimpleSecurityStageProcessor to create a SimpleSecurityManager instance for thebutton instance with id 'myButton' after it has been added to the stage.

Finally, the SimpleSecurityManagerFactory needs an IMembershipOwner instance to evaluate against.Typically this would be a user object representing the currently logged in user. The IMembershipOwnerinterface is a modest one and only exposes two properties: rights and roles:

public interface IMembershipOwner extends IEventDispatcher {

function get roles():Array; [Bindable(event="rolesChanged")] function set roles(value:Array):void;

function get rights():Array; [Bindable(event="rightsChanged")] function set rights(value:Array):void;

}

You can either have your user object implement this interface or simple inherit from the Spring ActionscriptSimpleMembershipOwner class.

Lastly, it is necessary to assign the user object to the ISecurityManagerFactory that the stage processorexposes. This enables the ISecurityManagers to determine whether they will grant access to their stagecomponents for the currently logged in user, based on the roles and rights that this user owns.

You can perform this assignment like so:

Page 47: Spring Action Script

The Inversion ofControl (IoC) container

41

var sp:SimpleSecurityStageProcessor = _applicationContext.getObject("securityProcessor") as SimpleSecurityStageProcessor;sp.securityManagerFactory.membershipOwner = currentUser; //Where the currentUser variable is an implementation of IMembershipOwner or a subclass of SimpleMembershipOwner.

And that's it! If the currentUser also owns the right called 'canClickButton' the button with id 'myButton'will become visible after the sp.securityManagerFactory.membershipOwner = currentUser assignmenthas been performed.

To simulate the user logging out simply set the membershipOwner property to null.

Note

There is a sample project that demonstrates the SimpleSecurityStageProcessor class, you can takea look by following this .

The IStageDestroyer interface

The IStageProcessor interface also has a counterpart called the IStageDestroyer interface. Implementationsof this interface aim to process a component after it has been removed from the stage. TheDefaultAutowiringStageProcessor class is also an implementation of this interface and can be used toinvoke disposal methods on a stage components after its been removed. The interface is an extension ofIStageProcessor and adds only one method:

public interface IStageDestroyer extends IStageProcessor { function destroy(object:Object):Object;}

Implementations can check for interfaces or methods or perform other logic which will eventually helpthe specified object to become eligible for garbage collection. See 'Destroying stage components' to findout how the DefaultAutowiringStageProcessor goes about this.

A graphical overview of the initialization of theFlexXMLApplicationContext

Customizing the nature of an object

Initialization callbacks

Object definitions provide support for a generic initialization method to be specified. In the case of XML-based configuration metadata, this is done using the 'init-method' attribute. For example, the followingdefinition:

<object id="exampleInitObject" class="examples.ExampleObject" init-method="init"/>

public class ExampleObject { public init():void { // do some initialization work }}

...is exactly the same as...

Page 48: Spring Action Script

The Inversion ofControl (IoC) container

42

<object id="exampleInitObject" class="examples.ExampleObject"> <method-invocation name="init"/></object>

But a whole lot shorter...

Knowing who you are

IApplicationContextAware

A class which implements the IApplicationContextAware interface is provided with a reference to theFlexXMLApplicationContext or XMLApplicationContext that created it, when it is created by thatApplicationContext.

public interface IApplicationContextAware {

function set applicationContext(value:IApplicationContext):void;

}

This allows objects to manipulate the FlexXMLApplicationContext or XMLApplicationContext thatcreated them programmatically, through the IApplicationContextAware interface, or by casting thereference to a known subclass of this which exposes additional functionality. Primarily this would consistof programmatic retrieval of other objects. While there are cases when this capability is useful, it shouldgenerally be avoided, since it couples the code to Spring Actionscript and does not follow the Inversionof Control style, where collaborators are provided to objects as properties.

Object definition inheritanceAn object definition potentially contains a large amount of configuration information, including containerspecific information (for example initialization method, static factory method name, and so forth) andconstructor arguments and property values. A child object definition is an object definition that inheritsconfiguration data from a parent definition. It is then able to override some values, or add others, as needed.Using parent and child objects definitions can potentially save a lot of typing. Effectively, this is a formof templating.

When working with an IApplicationContext programmatically, child object definitions are represented bythe ChildObjectDefinition class. Most users will never work with them on this level, instead configuringobject definitions declaratively. When using XML-based configuration metadata a child object definitionis indicated simply by using the 'parent' attribute, specifying the parent object as the value of this attribute.

<object id="inheritedTestObject" abstract="true" class="org.springactionscript.objects.TestObject"> <property name="name" value="parent"/> <property name="age" value="1"/></object>

<object id="inheritsWithDifferentClass" class="org.springactionscript.objects.DerivedTestObject" parent="inheritedTestObject" init-method="initialize"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --></object>

Page 49: Spring Action Script

The Inversion ofControl (IoC) container

43

A child object definition will use the object class from the parent definition if none is specified, but canalso override it. In the latter case, the child object class must be compatible with the parent, that is it mustaccept the parent's property values.

A child object definition will inherit constructor argument values, property values and method overridesfrom the parent, with the option to add new values. If any init-method and/or static factory method settingsare specified, they will override the corresponding parent settings.

The remaining settings will always be taken from the child definition: depends on, autowire mode,dependency check, singleton, scope, lazy init.

Note that in the example above, we have explicitly marked the parent object definition as abstract byusing the abstract attribute. In the case that the parent definition does not specify a class, and so explicitlymarking the parent object definition as abstract is required:

<object id="inheritedTestObject" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/></object>

<object id="inheritsWithDifferentClass" class="org.springactionscript.objects.DerivedTestObject" parent="inheritedTestObject" init-method="initialize"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --></object>

The parent object cannot get instantiated on its own since it is incomplete, and it is also explicitlymarked as abstract. When a definition is defined to be abstract like this, it is usable only as a puretemplate object definition that will serve as a parent definition for child definitions. Trying to use suchan abstract parent object on its own (by referring to it as a ref property of another object, or doing anexplicit getObject() call with the parent object id), will result in an error. Similarly, the container's internalpreInstantiateSingletons() method will completely ignore object definitions which are defined as abstract.

Note

ApplicationContexts will by default pre-instantiate all singletons. Therefore it is important (atleast for singleton objects) that if you have a (parent) object definition which you intend to useonly as a template, and this definition specifies a class, you must make sure to set the 'abstract'attribute to 'true', otherwise the application context will actually (attempt to) pre-instantiate theabstract object.

Spring Actionscript offers a second way of defining a template which is almost identical to the above way.There is a specific element called that offers the same kind of functionality but also has a way of addingparameters to the template's definition. Let's take a look at the following XML metadata:

<template id="remoteObject"> <object class="mx.rpc.remoting.mxml.RemoteObject"> <property name="destination" value="ColdFusion"/> <property name="endpoint" value="/flex2gateway/"/> <property name="concurrency" value="multiple"/> <property name="makeObjectsBindable" value="${makeBindable}"/> <property name="showBusyCursor" value="${showCursor}"/> <property name="source" value="com.path.to.remoteobjects.${serviceClass}"/>

Page 50: Spring Action Script

The Inversion ofControl (IoC) container

44

<property name="channelSet"> <ref>channelset</ref> </property> </object></template>

This shows the definition of a RemoteObject template which can be re-used for creating different instancesof a RemoteObject with different parameters. In the XML metadata you can see a number of placeholdersrecognizable by the fact that they are enclosed by braces and prefixed with a dollar-sign like this:${placeholder}. These placeholders will be replaced by the values of the parameters that are sent to thetemplate when instantiating an object.

Here is an example of an object definition that makes use of the template described above:

<object id="concreteService" template="remoteObject"> <param name="makeBindable" value="false"/> <param name="showCursor" value="true"/> <param name="serviceClass" value="gatewayname"/></object>

Note

The class that takes care of this functionality is the TemplatePreprocessor, this class isautomatically created by the XMLObjectDefinitionsParser in its preProcessXML() method.

Handling object inheritance using interfaces

Another way of defining object configurations is by using the interfaces they might implement. Imagineseveral classes implementing the same interface, if only one interface is implemented then using an objectdefinition with an 'abstract="true"' attribute and having all implementing object definitions refer to thisdefinition with their 'parent' attribute would suffice, even a template would do.

However, when multiple interfaces are being implemented is when you hit the limitations of theseconfiguration options. In this case the element might be able to help you out and in this section we willexplain how.

Let's make up two simple interfaces for this example:

public interface ISimpleInterface { function get myStringProperty():String; function set myStringProperty(value:String):void;}

public interface ISimpleInitializingInterface { function initialize():void;}

These interfaces can be configured in the XML configuration like this:

<interface class="com.mycompany.interfaces.ISimpleInterface"> <property name="myStringProperty" value="This is my test value!"/></interface>

<interface class="com.mycompany.interfaces.ISimpleInitializingInterface" init-method="initialize"/>

Page 51: Spring Action Script

The Inversion ofControl (IoC) container

45

Now, imagine creating a class that implements the aforementioned ISimpleInterface:

public class MySimpleClass implements ISimpleInterface { //implementation omitted}

To configure this object in your XML markup all you need to do is declare the object:

<object id="mySimpleInstance" class="com.mycompany.classes.MySimpleClass"/>

Afterwards Spring Actionscript will take care of combining the configurations for the implementedinterfaces with your object definition.

This works for multiple interfaces as well, so another class that would implement both interfaces. Say,something like this:

public class MySimpleInitializingClass implements ISimpleInterface, ISimpleInitializingInterface { //implementation omitted}

To receive a fully configured instance of this object, all you need to do again is simply declare the objectlike this:

<object id="mySimpleInitialzingInstance" class="com.mycompany.classes.MySimpleInitializingClass"/>

And in this case Spring Actionscript will have combined the configurations for the ISimpleInterface andISimpleInitializingInterface and added it to the mySimpleInitialzingInstance configuration.

Note

The class that takes care of this functionality is the InterfacePreprocessor, this class isautomatically created by the XMLObjectDefinitionsParser in its preProcessXML() method.

Object scopesWhen you create an object definition what you are actually creating is a recipe for creating actual instancesof the class defined by that object definition. The idea that an object definition is a recipe is important,because it means that, just like a class, you can potentially have many object instances created from asingle recipe.

You can control not only the various dependencies and configuration values that are to be plugged intoan object that is created from a particular object definition, but also the scope of the objects created froma particular object definition. This approach is very powerful and gives you the flexibility to choose thescope of the objects you create through configuration instead of having to 'bake in' the scope of an objectat the Actionscript class level. Objects can be defined to be deployed in one of a number of scopes: out ofthe box, Spring Actionscript supports exactly two scopes.

The scopes supported out of the box are listed below:

Table 2.4. Object scopes

Scope Description

singleton Scopes a single object definition to a single objectinstance per Spring Actionscript IoC container.

Page 52: Spring Action Script

The Inversion ofControl (IoC) container

46

prototype Scopes a single object definition to any number ofobject instances.

The singleton scope

When an object is a singleton, only one shared instance of the object will be managed, and all requestsfor objects with an id matching that object definition will result in that one specific object instance beingreturned by the Spring Actionscript container.

To put it another way, when you define an object definition and it is scoped as a singleton, then the SpringActionscript IoC container will create exactly one instance of the object defined by that object definition.This single instance will be stored in a cache of such singleton objects, and all subsequent requests andreferences for that named object will result in the cached object being returned.

Please be aware that Spring Actionscript's concept of a singleton object is quite different from the Singletonpattern as defined in the seminal Gang of Four (GoF) patterns book. The GoF Singleton hard codes thescope of an object such that one and only one instance of a particular class will ever be created. The scopeof the Spring Actionscript singleton is best described as per container and per object. This means thatif you define one object for a particular class in a single Spring Actionscript container, then the SpringActionscript container will create one and only one instance of the class defined by that object definition.The singleton scope is the default scope in Spring Actionscript. To define an object as a singleton in XML,you would write configuration like so:

<object id="accountService" class="com.foo.DefaultAccountService"/>

<!-- the following is equivalent, though redundant (singleton scope is the default) --><object id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>

<!-- the following is equivalent and preserved for backward compatibility --><object id="accountService" class="com.foo.DefaultAccountService" singleton="true"/>

The prototype scope

The non-singleton, prototype scope of object deployment results in the creation of a new object instanceevery time a request for that specific object is made (that is, it is injected into another object or it isrequested via a programmatic getObject() method call on the container). As a rule of thumb, you shoulduse the prototype scope for all objecs that are stateful, while the singleton scope should be used for statelessobjects.

To define an object as a prototype in XML, you would write configuration like so:

<!-- recommended markup --><object id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>

<!-- the following is equivalent and preserved for backward compatibility --><object id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>

Singleton objecs with prototype-object dependencies

When using singleton-scoped objects that have dependencies on objects that are scoped as prototypes,please be aware that dependencies are resolved at instantiation time. This means that if you dependencyinject a prototype-scoped object into a singleton-scoped object, a brand new prototype object will beinstantiated and then dependency injected into the singleton object... but that is all. That exact sameprototype instance will be the sole instance that is ever supplied to the singleton-scoped object, which isfine if that is what you want.

Page 53: Spring Action Script

The Inversion ofControl (IoC) container

47

However, sometimes what you actually want is for the singleton-scoped object to be able to acquire abrand new instance of the prototype-scoped bean again and again and again at runtime. In that case it is nouse just dependency injecting a prototype-scoped object into your singleton object, because as explainedabove, that only happens once when the Spring Actionscript container is instantiating the singleton objectand resolving and injecting its dependencies.

Customizing the nature of an object

Lifecycle callbacks

The Spring Actionscript Framework provides a callback interface to change the behavior of your objectin the container; this is the IInitializingObject interface. Implementing this interface will result in thecontainer calling the afterPropertiesSet() method immediately after the object has been created andconfigured, but before its initialization method is called (defined by the init-method attribute).

Internally, the Spring Actionscript Framework uses IObjectPostProcessor implementations to processany callback interfaces it can find and call the appropriate methods. If you need custom featuresor other lifecycle behavior Spring Actionscript doesn't offer out-of-the-box, you can implement anIObjectPostProcessor yourself. More information about this can be found in the section entitled .

Initialization callbacks

Implementing the org.springextensions.actionscript.ioc.factory.IInitializingObject interface allows anobject to perform initialization work after all necessary properties on the object have been set by thecontainer. The IInitializingObject interface specifies exactly one method:

function afterPropertiesSet():void;

Generally, the use of the IInitializingObject interface can be avoided and is actually discouraged sinceit unnecessarily couples the code to Spring Actionscript. As an alternative, objects definitions providesupport for a generic initialization method to be specified. In the case of XML-based configurationmetadata, this is done using the 'init-method' attribute. For example, the following definition:

<object id="exampleInitObject" class="examples.ExampleObject" init-method="init"/>

public class ExampleObject { public function init():void { // do some initialization work }}

...is exactly the same as...

<object id="exampleInitObject" class="examples.AnotherExampleObject"/>

public class AnotherExampleObject implements IInitializingObject { public function afterPropertiesSet():void { // do some initialization work }}

... but does not couple the code to Spring Actionscript.

Page 54: Spring Action Script

The Inversion ofControl (IoC) container

48

Container extension pointsThe IoC component of the Spring Actionscript Framework has been designed for extension. There istypically no need for an application developer to subclass the ApplicationContext class. The SpringActionscript IoC container can be infinitely extended by plugging in implementations of special integrationinterfaces.

Spring Actionscript can be extended through the IObjectPostProcessor, IObjectFactoryPostProcessor andIFactoryObject interfaces.

First we look at some existing examples of these interfaces and after that there is a small tutorial on howto build your own implementation.

The following are a few implementations of these interfaces that Spring Actionscript supports 'out of thebox' to help you out in daily development life.

Flex application settings

Specifically for the FlexXMLApplicationContext there is the ability to refer to the properties of theApplication class directly from the container's metadata. These properties can be used as regular propertyplaceholders in an application context or a properties file. e.g. ${application.url}.

The following properties are supported:

• application.frameRate

• application.historyManagementEnabled

• application.pageTitle

• application.resetHistory

• application.scriptRecursionLimit

• application.scriptTimeLimit

• application.url

• application.url.protocol

• application.url.host

• application.url.port

• application.usePreloader

• application.viewSourceURL

• application.parameters (when they exist)

Individual flashvars are automatically added to the application settings, so if a flashvar called myFlashVaris passed to the application it will be available as application.myFlashVar in the context.

Logging target factory

The logging target this factory creates will automatically be added to the log manager class.

<object id="traceTarget" class="org.springextensions.actionscript.ioc.factory.config.LoggingTargetFactoryObject">

Page 55: Spring Action Script

The Inversion ofControl (IoC) container

49

<property name="loggingTargetClass" value="mx.logging.targets.TraceTarget"/> <property name="includeCategory" value="true"/> <property name="includeDate" value="true"/> <property name="includeLevel" value="true"/> <property name="includeTime" value="true"/> <property name="level" value="2"/> <property name="filters"> <array> <value>com.domain.model.*</value> <value>com.domain.view.*</value> </array> </property></object>

Enforcing required property injections

This is an IObjectPostProcessor implementation that enforces required properties to be injected. A propertyis marked as required by adding [Required] metadata to the property definition:

[Required]public var myProperty:Type;

If the property has been defined as required but a suitable injection candidate cannot be found by thecontainer it will throw an IllegalArgumentError exception.

In order to use it in your application, include it as an object in your application context:

<object class="org.springextensions.actionscript.ioc.factory.config.RequiredMetadataObjectPostProcessor"/>

Injecting the object factory

The ObjectFactoryAwarePostProcessor will check if the object that has just been created by the containerimplements the IObjectContainerAware interface. If this is found to be true it will inject the container asa property on the specified object.

In order to use it in your application, include it as an object in your application context:

<object class="org.springextensions.actionscript.ioc.factory.config.ObjectFactoryAwarePostProcessor"/>

Injecting fields from other objects

Sometimes it is necessary to use the value of another object's field to be injected into a new object. SpringActionscript offers the FieldRetrievingFactoryObject the this specific task. Configuration for this objectis fairly straightforward, here is an example of its usage:

<object id="trafficEventManager" class="com.myclasses.TrafficEventManager"> <constructor-arg> <object class="org.springextensions.actionscript.ioc.factory.config.FieldRetrievingFactoryObject"> <property name="targetObject" ref="modelLocator" /> <property name="targetField" value="trafficEventTypes" /> </object> </constructor-arg></object>

The TrafficEventManager instance requires an ArrayCollection of event types to be passed to itsconstructor. In this example we assume this list of event types is defined in the modelLocator

Page 56: Spring Action Script

The Inversion ofControl (IoC) container

50

instance by its trafficEventTypes property. With the above example this value is now injected into theTrafficEventManager's constructor.

Note

The FieldRetrievingFactoryObject supports both instance and static properties.

Here's how the FieldRetrievingFactoryObject can be used to retrieve a static field:

<object class="org.springextensions.actionscript.ioc.factory.config.FieldRetrievingFactoryObject"> <property name="staticField" value="CURRENT_VERSION"/> <property name="targetClass" value="mx.core.FlexVersion/></object>

Injecting method invocation results from other objects

Not just properties can be retrieved from other objects, also the result of method invocations on theseobjects can be used to inject into other objects. The MethodInvokingFactoryObject deals with these kindsof situations. Here is an example:

<object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject" id="resourceManager"> <property name="targetClass" value="mx.resources.ResourceManager"/> <property name="targetMethod" value="getInstance"/></object>

This will call the static getInstance() method on the mx.resources.ResourceManager class. It is alsopossible to call a method on an instance, here's how:

<object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject" id="resourceValue"> <property name="targetObject" value="resourceManager"/> <property name="targetMethod" value="getString"/> <property name="arguments"> <array> <value>bundleName</value> <value>resourceName</value> </array> </property></object>

This will retrieve the previously instantiated resourceManager from the first example and invokes thegetString() method on it using the specified array of arguments.

Customizing objects using ObjectPostProcessors

The first extension point that we will look at is the IObjectPostProcessor interface. This interface definesa number of callback methods that you as an application developer can implement in order to provideyour own (or override the containers default) instantiation logic, dependency-resolution logic, and so forth.If you want to do some custom logic after the Spring Actionscript container has finished instantiating,configuring and otherwise initializing an object, you can plug in one or more IObjectPostProcessorimplementations.

Note

IObjectPostProcessors operate on object instances; that is to say, the Spring Actionscript IoCcontainer will have instantiated an object instance for you, and then IObjectPostProcessors get a

Page 57: Spring Action Script

The Inversion ofControl (IoC) container

51

chance to do their stuff. If you want to change the actual object definition (that is the recipe thatdefines the object), then you rather need to use a IObjectFactoryPostProcessor (described belowin the section entitled .

The org.springextensions.actionscript.ioc.factory.config.IObjectPostProcessor interface consists ofexactly two callback methods. When such a class is registered as a post-processor with the container,for each object instance that is created by the container, the post-processor will get a callback from thecontainer both before any container initialization methods (such as afterPropertiesSet and any declaredinit method) are called, and also afterwards. The post-processor is free to do what it wishes with the objectinstance, including ignoring the callback completely. An object post-processor will typically check forcallback interfaces, or do something such as wrap an object with a proxy.

An ApplicationContext will automatically detect any objects which are defined in the configurationmetadata which is supplied to it that implement the IObjectPostProcessor interface, and register them aspost-processors, to be then called appropriately by the container on object creation. Nothing else needs tobe done other than deploying the post-processors in a similar fashion to any other object.

Note

You can force the object factory to ignore its list of IObjectPostProcessors for a givenObjectDefinition by setting its skip-postprocessors attribute to true. This will yield a smallperformance boost.

Creating a postprocessor

Let's see how we can build our own processor. Suppose we have an IProductManager interface that lookslike this:

public interface IProductManager {

function get items():ArrayCollection; function set items(value:ArrayCollection):void;}

At runtime the actual items will be loaded by a server call and stored in the application model. Since wewon't know exactly when the items will be loaded we can't use the FieldRetrievingFactoryObject to simplyassign the model's items to the items property of the IProductManager instance. What we'd like to do isactually bind the productmanager's items to the model items.

Let's see if we can build something that performs this task. We will implement the IObjectPostProcessorinterfaces like this:

public class PropertyBindingPostProcessor implements IObjectPostProcessor {

public function PropertyBindingPostProcessor() { super(); } private var _host:Object; public set host(value:Object):void { _host = host; } private var _chain:Object; public set chain(value:Object):void { _chain = value;

Page 58: Spring Action Script

The Inversion ofControl (IoC) container

52

}

public function postProcessBeforeInitialization(object:*, objectName:String):* { Assert.notNull(_host,"host property cannot be null"); Assert.notNull(_chain,"chain property cannot be null"); if (object is IProductManager) { BindingUtils.bindProperty(object,'items',host,chain); } } public function postProcessAfterInitialization(object:*, objectName:String):* { return null; }

}

Now all we need to do is add this bit of configuration and the post processor is ready to do its work:

<object id="propertyBindingPostProcessor" class="com.myclasses.postprocessors.PropertyBindingPostProcessor"> <property name="host" ref="modelInstance"/> <property name="chain" value="items"/></object>

That's it basically it! Now its certainly possible to come up with a much more generic solution than this,but it does show its fairly easy to create your own post processors for specific tasks.

Customizing instantiation logic using the IFactoryObject interface

The org.springextensions.actionscript.ioc.factory.IFactoryObject interface is to be implemented by objectsthat are themselves factories.

The IFactoryObject interface is a point of pluggability into the Spring Actionscript IoC containersinstantiation logic. If you have some complex initialization code that is better expressed in Actionscriptas opposed to a (potentially) verbose amount of XML, you can create your own IFactoryObject, write thecomplex initialization inside that class, and then plug your custom IFactoryObject into the container.

Now when you request an instance of such an IFactoryObject from the container, it doesn't actuallyreturn an IFactoryObject instance, instead, it calls the getObject() method on the object and returns theresult of this method.

The IFactoryObject interface provides three methods:

• getObject():*; has to return an instance of the object this factory creates. The instance can possibly beshared (depending on whether this factory returns singletons or prototypes).

• isSingleton():Boolean; has to return true if this IFactoryObject returns singletons, false otherwise

• getObjectType():Class; has to return either the object type returned by the getObject() method or nullif the type isn't known in advance

Let's say we need to instantiate an object of class IncrediblyComplicatedObject. The initialization of thisobject involves some kind of logic that is beyond the scope of Spring Actionscript and way too complicatedto be expressed in XML. We are of course able to write our own code to perform this. We can now buildan IFactoryObject that implements this task:

Page 59: Spring Action Script

The Inversion ofControl (IoC) container

53

public class IncrediblyComplicatedObjectFactory implements IFactoryObject {

public function getObject():* { var instance:IncrediblyComplicatedObject = new IncrediblyComplicatedObject(); //creation logic ommitted return instance; }

public function getObjectType():Class { return IncrediblyComplicatedObject; }

public function get isSingleton():Boolean { return false; }

}

The isSingleton() method returns false, this means that every time this IFactoryObject is requestedfrom the container, it creates a new instance of IncrediblyComplicatedObject. When set to true it willcreate an instance once, and return this on every subsequent call. (At least, if the interface is properlyimplemented :) ).

In order to use an IFactoryObject in your application, include it as an object in your application context:

<object class="com.myclasses.factories.IncrediblyComplicatedObjectFactory" id="incrediblyComplicatedObject"/>

After that, requesting an instance of IncrediblyComplicatedObject is the same as requesting any otherordinary object from the container:

var complicated:IncrediblyComplicatedObject = applicationContext.getObject("incrediblyComplicatedObject") as IncrediblyComplicatedObject;

Finally, there is sometimes a need to ask a container for an actual IFactoryObject instance itself, not theobject it produces. This may be achieved by prepending the object id with '&' (sans quotes) when callingthe getObject method of the ObjectFactory (including ApplicationContext). So for a given IFactoryObjectwith an id of myObject, invoking getObject("myObject") on the container will return the product of theIFactoryObject, but invoking getObject("&myObject") will return the IFactoryObject instance itself.

Customizing configuration metadata with theIObjectFactoryPostProcessor interface

The next extension point that we will look at is theorg.springextensions.actionscript.ioc.factory.config.IObjectFactoryPostProcessor. The semantics of thisinterface are similar to the IObjectPostProcessor, with one major difference: IObjectFactoryPostProcessorsoperate on the object configuration metadata; that is, the Spring Actionscript IoC container will allowIObjectFactoryPostProcessors to read the configuration metadata and potentially change it before thecontainer has actually instantiated any other objects.

The interface is fairly simple as you can see:

public interface IObjectFactoryPostProcessor {

function postProcessObjectFactory(objectFactory:IConfigurableListableObjectFactory):void;}

Page 60: Spring Action Script

The Inversion ofControl (IoC) container

54

In order to use an IObjectFactoryPostProcessor in your application, include the implementation as anobject in your application context:

<object class="com.myclasses.postprocessors.MyObjectFactoryPostProcessor" id="objectFactoryPostProcessor"/>

Now after the application context has finished loading its configuration file, and before it startsinstantiating any objects every IObjectFactoryPostProcessor that was found in the configurationwill be invoked by calling its postProcessObjectFactory() method and passing the currentIConfigurableListableObjectFactory instance as the argument. The IObjectFactoryPostProcessor can thenuse the IConfigurableObjectFactory, IListableObjectFactory and IConfigurableListableObjectFactoryinterfaces to perform whatever postprocessing logic is necessary.

Note

Just as in the case of IObjectPostProcessors, you typically don't want to haveIObjectFactoryPostProcessors marked as being lazily-initialized. If they are marked as such, thenthe Spring Actionscript container will never instantiate them, and thus they won't get a chanceto apply their custom logic.

Controlling collection orderSeveral collections (ObjectFactoryPostProcessors, ObjectPostProcessors, ClassScanners andMetadataProcessors) available in the application context can be sorted into a prefered order using theIOrdered interface. Let's have a look at it:

public interface IOrdered {

function get order():int;

function set order(value:int):void;

}

The actual order can be interpreted as prioritization, with the first object (with the lowest order value)having the highest priority. When collections are sorted that contain objects that do not implement theIOrdered interface first the IOrdered implementations will be sorted with the lowest order value first, afterthat the remaining objects will be concatenated unordered. For sorting such a collection the static methodOrderedUtils.sortOrderedArray() may be used.

Page 61: Spring Action Script

Part II. APIs and extensionsOther Spring Actionscript APIs and extensions for 3rd party frameworks

Page 62: Spring Action Script

56

Chapter 3. Metadata annotationshandlingIntroduction

Spring Actionscript offers an easy way to process actionscript metadata annotations. The main interfaceof interest for this task is IMetadataProcessor.

Here's what it looks like up close:

public interface IMetadataProcessor {

function get metadataNames():Array;

function get processBeforeInitialization():Boolean;

function process(instance:Object, container:IMetaDataContainer, name:String, objectName:String):void;}

The basic properties have already been implemented by the AbstractMetadataProcessor base class whichcan be used for convenience.

Let's take a look at the various properties and methods and see what they do and mean.

• metadataNames - This is an Array of metadata names that will trigger the process() method of theIMetadataProcessor implementation.

• processBeforeInitialization - When set to true the IMetadataProcessor instance will be able to processthe annotated instance before it has been initialized by the Spring Actionscript container.

• process - This method will contain the processing logic that is associated with the various namesspecified by the metadataNames property.

The process() method will naturally be the most important aspect in any implementation of theIMetadataProcessor interface. It receives three parameters:

• instance - This is the object instance that was encountered with the specified metadata name on its classor its methods or properties.

• container - The IMetaDataContainer that is associated with the instance, this can be any of thesesubclasses: Type, Method, Accessor, Constant, Variable.

• name - The metadata name that triggered the invocation of the process() method.

• objectName - The name of the object definition in the Spring Actionscript container.

To use the IMetadataProcessor in an application add the implementation as an object definition to theapplication context configuration like this:

<object id="mvcEventsProcessor" class="org.springextensions.actionscript.core.mvc.MVCRouteEventsMetaDataProcessor"/>

After that the processor is ready to go, when used in combination with the autowiring stage processor (asdescribed in this section) it will process both objects created by the container and components thatwere added to the stage.

Page 63: Spring Action Script

Metadata annotations handling

57

Note

Credit where credit is due: This type of metadata handling was pioneered by the team, the SpringActionscript team both acknowledges and appreciates their work.

Controlling the order of IMetadataProcessorsThe order in which IMetadataProcessors are executed is controlled by the IOrdered interface. See the'Controlling collection order' section for more information on this interface.

Page 64: Spring Action Script

58

Chapter 4. The Operation APIIntroduction

One of the most prevalent actions in any Flash or Flex application is: Get stuff from the server back-end.Be it calling a remote object, loading a sub-application, module or resource file, all of these actions haveone thing in common: They are asynchronous.

The Flex framework and Flash player seem to use different kinds of asynchronous patterns for differentkinds of retrieval. There's the responder method, the event based method (all be it with an optionalprogress reporting mechanism), calls to a singleton that returns an IEventDispatcher instance or some otherinterface, etc.

The Spring Actionscript Operation API aims to facilitate a common wrapper for these different patterns inorder to make using and combining them a little easier. The provided interfaces and base classes will givea developer the opportunity to easily write his own logic. In addition to this, Spring Actionscript alreadyoffers classes for the most common asynchronous tasks such as the loading of Flex modules, resourcemodules and remote object calls.

Note

The Operation API is not an MVC or MVCS framework. The Spring Actionscript team believesthat a framework approach is too rigid, instead it offers a set of low-level classes and interfacesthat allows a developer to create a custom solution for each project/application he/she is workingon. No application is the same, therefore Spring Actionscript chose to offer building blocksinstead of a framework.

All the classes and interfaces described in this chapter can be found in the package.

Operations, commands, services and tasksThe Operation API, broadly speaking, has four concepts:

1. Operation: An asynchronous action.

2. Command: An action with deferred execution.

3. Service: A collection of related operations.

4. Task: A collection of commands that are executed using a control flow.

Operations

An operation represents any kind of asynchronous action and is described by the IOperation interface:

public interface IOperation extends IEventDispatcher {

function get result():*;

function get error():*;

function addCompleteListener(listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;

Page 65: Spring Action Script

The Operation API

59

function addErrorListener(listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;

function removeCompleteListener(listener:Function, useCapture:Boolean = false):void;

function removeErrorListener(listener:Function, useCapture:Boolean = false):void;

}

The most important properties of this interface are the result and error properties, these will be assignedwith the results of the asynchronous action. The names speak for themselves.

Note

An IOperation implementation will always execute its action immediately after creation, allnecessary parameters are therefore typically passed to the constructor of an implementation.

Long running operations

Operations that take long amounts of time to complete, such as downloading modules or other types ofassets benefit from being able to notify the user of their progress. Typically a progress bar could be displaythis. For these types of operations there is the IProgressOperation interface, which is a simple extensionof IOperation:

public interface IProgressOperation extends IOperation {

function get progress():uint;

function get total():uint;

function addProgressListener(listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void;

function removeProgressListener(listener:Function, useCapture:Boolean = false):void;}

Operation queues

In some cases a collection of IOperations need to be run at once, yet each individualOperationEvent.COMPLETE event doesn't need to be listened for. All that is important is that all of theIOperations are completed successfully. For this situation the OperationQueue class can help out. A simpleusage of this class might be like this:

var queue:OperationQueue = new OperationQueue();queue.addCompleteListener(handleQueueComplete);queue.addOperation(new FirstOperation());queue.addOperation(new SecondOperation());queue.addOperation(new ThirdOperation());queue.addOperation(new FourthOperation());

And that's all, upon adding the operations the queue immediately starts running. So after all four operationshave completed the specified handleQueueComplete method will be invoked and the application can goon about its business.

Common Spring Actionscript operations

Here is a list of all the IOperation implementations for common usage scenarios that Spring Actionscriptcontains:

Page 66: Spring Action Script

The Operation API

60

• LoadPropertiesOperation

• LoadPropertiesBatchOperation

• LoadStyleModuleOperation

• LoadURLOperation

• LoadModuleOperation

• NetConnectionOperation

• RemoteObjectOperation

• LoadResourceBundleOperation

• LoadResourceModuleOperation

• LoadURLStreamOperation

• HTTPServiceOperation

• WebServiceOperation

Commands

A command is any kind of action whose execution is deferred. Only after invoking the command'sexecute() method will the action do its work. The basic ICommand interface is very modest:

public interface ICommand {

function execute():*;

}

This represents a synchronous command, so the logic that is executed by an implementation will beavailable immediately after the call to the execute() method, and typically be returned in the execute()'sresult.

More interesting is the IAsyncCommand interface which is actually just a combination of the ICommandand IOperation interfaces:

public interface IAsyncCommand extends ICommand, IOperation {

}

This interface allows a command to be constructed that will execute an asynchronous action. So contraryto an IOperation instance an IAsyncCommand can be created, but its logic executed at a later moment.

Because the command is asynchronous the result property will be null directly after the execute() methodhas been called, also the result of the execute() method will be either null or undefined. To retrieve the resultof the IAsyncCommand, add listeners for the OperationEvent.COMPLETE and OperationEvent.ERRORevents.

Composite commands

Just like IOperations its very well possible that a collection of ICommands or IAsyncCommands (or amixed collection of them) needs to be executed. For this scenario the CompositeCommand class is ideal.

Page 67: Spring Action Script

The Operation API

61

It allows a list of ICommands to be executed in parallel or sequence. The CompositeCommand class is animplementation of the ICompositeCommand interface:

public interface ICompositeCommand extends ICommand, IOperation {

function addCommand(command:ICommand):void;

function get numCommands():uint;

function get kind():ComposeiteCommandKind;}

A simple example of the usage of a CompositeCommand instance would be like this:

var compositeCommand:CompositeCommand = new CompositeCommand(ComposeiteCommandKind.SEQUENCE);compositeCommand.addCommand(new FirstCommand());compositeCommand.addCommand(new SecondCommand());compositeCommand.addCommand(new ThirdCommand());compositeCommand.addCommand(new FourthCommand());compositeCommand.addCompleteListener(handleCompositeCommandComplete);compositeCommand.addErrorListener(handleCompositeCommandError);compositeCommand.execute();

This will execute the FirstCommand instance, wait for it to complete, execute the SecondCommandinstance, wait for it to complete, etc.

If all commands complete successfully the specified handleCompositeCommandComplete method willbe invoked, if an error occurs the handleCompositeCommandError method is invoked instead.

Note

The failOnFault property determines whether the CompositeCommand instance should stopexecuting its list of commands in the case of an error. Default this property is set to false. So allcommands will be executed no matter what their result is.

See the section 'the composite-command XML shortcut' to find out about custom XML configuration forthis class.

GenericOperationCommand

Having an ICommand implementation of each and every IOperation in an application isn't always practical,therefore the GenericOperationCommand might help out a little. The GenericOperationCommand isnothing more than a simple IAsyncCommand wrapper. All that a GenericOperationCommand needs is theClass of an arbitrary IOperation and an optional list of constructor arguments. For example, here is howthe LoadModuleOperation would be wrapped:

var genericOperationCommand = new GenericOperationCommand(LoadModuleOperation, 'module.swf');genericOperationCommand.addCompleteHandler(operationCompleteHandler);genericOperationCommand.execute();

GenericOperationCommand inside a CompositeCommand

Its not necessary to wrap an IOperation in a GenericOperationCommand when adding it to aCompositeCommand. The CompositeCommand also has an addOperation() method which has thissignature:

Page 68: Spring Action Script

The Operation API

62

function addOperation(operationClass:Class, ...constructorArgs):ICompositeCommand;

Which is basically the same as the constructor for a GenericOperationCommand, so adding aLoadModuleOperation to a CompositeCommand instance would work like this:

compositeCommand.addOperation(LoadModuleOperation, 'module.swf');

The OperationHandler helper class

The OperationHandler is a helper class that generically handles IOperation events and either routes theirresult or error data to a specified method or assigns them to a specified property on an object instance.

Below are some examples of its usage.

Assigning an operation result to an instance property

public class MyPresentationModel {

private var _operationHandler:OperationHandler

public var products:Array;

public function MyPresentationModel(){ _operationHandler = new OperationHandler(this.errorHandler); }

public function getProducts():void { var operation:IOperation = serviceImplementation.getProducts(); _operationHandler.handleOperation(operation,null,this,"products"); }

protected function errorHandler(error:):void { //implementation omitted }}

Assigning an operation result to an instance property using an extra method

If the data returned from the IOperation needs some extra processing, specify an extra method for it likein this example:

public class MyPresentationModel {

private var _operationHandler:OperationHandler

public var products:ArrayCollection;

public function MyPresentationModel(){ _operationHandler = new OperationHandler(this.errorHandler); }

public function getProducts():void { var operation:IOperation = serviceImplementation.getProducts(); _operationHandler.handleOperation(operation,convertArray,this,"products"); }

Page 69: Spring Action Script

The Operation API

63

protected function convertArray(input:Array):ArrayCollection { return new ArrayCollection(input); }

protected function errorHandler(error:):void { //implementation omitted }}

Services

It makes sense to encapsulate a number of operations in one interface. The easiest example would be theCRUD operations for a specific object.

Let's imagine a user service whose interface looks like this:

public interface IUserService {

function createUser():IOperation;

function updateUser(user:User):IOperation;

function deleteUser(user:User):IOperation;

}

In a lot of cases the implementation for such a service will rely on a RemoteObject. For this situation SpringActionscript offers the base class RemoteObjectService. So the implementation for the IUserService couldinherit from this:

public class UserService extends RemoteObjectService implements IUserService {

public function UserService(remoteObject:RemoteObject) { Assert.notNull(remoteObject,"remoteObject argument must not be null"); super(remoteObject); }

public function createUser():IOperation { return call('createUser'); }

public function updateUser(user:User):IOperation { return call('updateUser',user); }

public function deleteUser(user:User):IOperation { return call('deleteUser',user); }}

This service could be injected into a presentation model, a command, a supervising presenter, etc. Alldepending on the specific patterns used in an application.

Let's look at a command example:

Page 70: Spring Action Script

The Operation API

64

public class CreateUserCommand extends AbstractOperation implements IAsyncCommand {

private var _userService:IUserService; private var _applicationModel:IApplicationModel;

public function CreateUserCommand(userService:IUserService, applicationModel:IApplicationModel) { Assert.notNull(userService,"userService argument must not be null"); Assert.notNull(applicationModel,"applicationModel argument must not be null"); _userService = userService; _applicationModel = applicationModel; }

public function execute():* { var operation:IOperation = _userService.createUser(); operation.addCompleteListener(handleComplete); operation.addErrorListener(handleError); }

protected function handleComplete(event:OperationEvent):void { _applicationModel.users.addItem(event.result as User); dispatchCompleteEvent(event.result); }

protected function handleError(event:OperationEvent):void { dispatchErrorEvent(event.error); }

}

In this example the command receives a reference to an IUserService and IApplicationModel instance.In this example we assume the IApplicationModel instance has a property called users of typeArrayCollection. Once the IOperation that was received from the service completes it adds the result ofthe IOperation (which is a User object) to the user collection in the application model.

Tasks

In order to support more complex execution of ICommand collections there is finally the ITask interface.This interface describes an object that not only can execute collections of ICommands both in parallel andin sequence, but also does this with basic control flow functionality.

First let's take a quick look and the ITask interface:

public interface ITask extends ICommand, IOperation {

function get context():Object; function set context(value:Object):void;

function get parent():ITask; function set parent(value:ITask):void;

function next(item:Object, ...constructorArgs):ITask;

function and(item:Object, ...constructorArgs):ITask;

Page 71: Spring Action Script

The Operation API

65

function if_(condition:IConditionProvider=null, ifElseBlock:IIfElseBlock=null):IIfElseBlock;

function else_():IIfElseBlock;

function while_(condition:IConditionProvider=null, whileBlock:IWhileBlock=null):IWhileBlock;

function for_(count:uint, countProvider:ICountProvider=null, forBlock:IForBlock=null):IForBlock;

function exit():ITask;

function reset(doHardReset:Boolean = false):ITask;

function pause(duration:uint, pauseCommand:ICommand=null):ITask;

function end():ITask;}

First thing that is apparent in this interface is that almost each method returns an ITask instance. Thisactually implies that this is a so-called fluent interface. Meaning that method calls to a single instance ofan ITask can be chained. For instance, if we want to use a Task instance to execute a number of commandsin parallel we can write this:

var task:Task = new Task().and(new FirstCommand()).and(new SecondCommand()).and(new ThirdCommand()).and(new FourthCommand());task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);task.execute();

This is basically the same as an ICompositeCommand set to CompositeCommandKind.PARALLEL, sonot that interesting. But the nice thing about a Task is the opportunity to mix the different types ofexecution. So if we first want to execute a number of commands in parallel but after that a few in sequence,we can use the same Task instance:

var task:Task = new Task().and(new FirstCommand()).and(new SecondCommand()).next(new ThirdCommand()).next(new FourthCommand());task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);task.execute();

This will first execute FirstCommand and SecondCommand in parallel and afterwards executeThirdCommand and FourthCommand in sequence.

The first argument for the next() and and() methods can be either an ICommand implementation, or aClass that implements the IOperation interface along with an optional list of constructor arguments for theIOperation instantiation. So this can also be a valid invocation:

new Task().and(LoadModuleOperation, 'module.swf');

Now let's have a look at some control flow elements, what if a certain command needs to be executedmore than once? We can use a for_() invocation for this:

var task:Task = new Task();

task.for_(10) .next(new FirstCommand()).end();

task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);task.execute();

Page 72: Spring Action Script

The Operation API

66

This will execute the FirstCommand 10 times. Now, it won't always be possible to know the exact numberof iterations at compile-time. Therefore its possible to pass an optional ICountProvider instance to thefor_() method. The ICountProvider interface is quite small:

public interface ICountProvider { function getCount():uint;}

Any implementations of this interface can perform their own kind of logic to determine the exact count,this implementation can also be an IOperation so the logic for retrieving the count may be asynchronous,internally the ForBlock will take care of this.

An ICommand may also be executed conditionally, for this use the if_() method and pass anIConditionProvider to it:

var task:Task = new Task();

task.if_(new MyConditionProvider()) .next(new FirstCommand()).end();

task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);task.execute();

Now let's take a look at the IConditionProvider interface:

public interface IConditionProvider { function getResult():Boolean;}

The result of the getResult() method determines whether the commands inside the if block will be executedor not. Again, an IConditionProvider implementation may also itself be an IOperation, and therefore haveits logic be executed in an asynchronous manner.

Of course, the if block may also have an else block:

var task:Task = new Task();

task.if_(new ConditionProvider()) .next(new FirstCommand()) .else_() .next(new SecondCommand()).end();

task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);task.execute();

An IConditionProvider can also be used by a while block:

var task:Task = new Task();

task.while_(new MyConditionProvider()) .next(new FirstCommand()).end();

task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete);

Page 73: Spring Action Script

The Operation API

67

task.execute();

In this case the FirstCommand will be executed for as long as the IConditionProvider.getResult() methodreturns true.

In closing there are three last methods that an ITask implementation offers:

1. Exit(): stops the execution of the entire task.

2. Reset(): restarts the execution of the current task.

3. Pause(): pauses the execution of the current task for a specified period.

The task namespace handler

Configuring a task in Spring Actionscript XML is of course the final piece of functionality that SpringActionscript offers. There is a namespace handler to make task configuration a little easier. There's twothings that need to be added to the context and configuration.

First of all add the namespace to the configuration:

<?xml version="1.0" encoding="utf-8"?><objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://www.springactionscript.org/schema/task" xsi:schemaLocation=" http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/task http://www.springactionscript.org/schema/util/spring-actionscript-task-1.1.xsd">

<!-- further markup ommitted --></objects>

After that an instance of the TaskNamespaceHandler class needs to be added to the application context:

applicationContext.addNamespaceHandler(new TaskNamespaceHandler());

That's it, the application context is now ready to be able to parse task specific configuration XML.

Let's re-create the example where two commands are executed in parallel and two in sequence:

<t:task id="testTask" scope="prototype"> <t:and> <object id="command1" scope="prototype" class="classes.commands.FirstCommand"/> </t:and> <t:and> <object id="command2" scope="prototype" class="classes.commands.SecondCommand"/> </t:and> <t:next> <object id="command3" scope="prototype" class="classes.commands.ThirdCommand"/> </t:next> <t:next> <object id="command3" scope="prototype" class="classes.commands.FourthCommand"/> </t:next></t:task>

Its also possible to declare the command objects outside of the task specific XML:

Page 74: Spring Action Script

The Operation API

68

<object id="command1" scope="prototype" class="classes.commands.FirstCommand"/><object id="command2" scope="prototype" class="classes.commands.SecondCommand"/><object id="command3" scope="prototype" class="classes.commands.ThirdCommand"/><object id="command3" scope="prototype" class="classes.commands.FourthCommand"/>

<t:task id="testTask" scope="prototype"> <t:and command="command1"/> <t:and command="command2"/> <t:next command="command3"/> <t:next command="command4"/></t:task>

A conditional execution could be configured like this:

<object id="command1" scope="prototype" class="classes.commands.FirstCommand"/><object id="command2" scope="prototype" class="classes.commands.SecondCommand"/><object id="myCondition" scope="prototype" class="classes.condition.MyConditionProvider"/>

<t:task id="testTask" scope="prototype"> <t:if condition="myCondition"> <t:next command="command1"/> <t:else/> <t:next command="command2"/> </t:if></t:task>

A for loop would look like this:

<object id="command1" scope="prototype" class="classes.commands.FirstCommand"/><object id="command2" scope="prototype" class="classes.commands.SecondCommand"/>

<t:task id="testTask" scope="prototype"> <t:for count="10"> <t:next command="command1"/> <t:next command="command2"/> </t:for></t:task>

Or, when using an ICountProvider:

<object id="command1" scope="prototype" class="classes.commands.FirstCommand"/><object id="command2" scope="prototype" class="classes.commands.SecondCommand"/><object id="myCount" scope="prototype" class="classes.counts.MyCountProvider"/>

<t:task id="testTask" scope="prototype"> <t:for count-provider="myCount"> <t:next command="command1"/> <t:next command="command2"/> </t:for></t:task>

And finally, of course, the while loop:

<object id="command1" scope="prototype" class="classes.commands.FirstCommand"/><object id="command2" scope="prototype" class="classes.commands.SecondCommand"/>

Page 75: Spring Action Script

The Operation API

69

<object id="myCondition" scope="prototype" class="classes.condition.MyConditionProvider"/>

<t:task id="testTask" scope="prototype"> <t:while condition="myCondition"> <t:next command="command1"/> <t:next command="command2"/> </t:while></t:task>

Common operation XML shortcuts

To add, for instance, a LoadModuleOperation to a task, this XML mark up would normally be needed:

<t:task id="testTask" scope="prototype"> <t:and> <object class="org.springextensions.actionscript.core.command.GenericOperationCommand"> <constructor-arg value="org.springextensions.actionscript.module.LoadModuleOperation" type="Class"/> <constructor-arg value="modules/mymodule.swf"/> </object> </t:and> //etc...</t:task>

This is quite verbose so Spring Actionscript offers XML shortcuts for a number of common operations:

• LoadModuleOperation

• LoadPropertiesBatchOperation

• LoadPropertiesOperation

• LoadResourceModuleOperation

• LoadStyleModuleOperation

• LoadURLOperation

• LoadURLStreamOperation

Here's an example of how all these operations can be configured in XML for a task:

<t:task id="testTask" scope="prototype"> <t:next> <t:load-module url="modules/mymodule.swf" application-domain="appDomainObjectName" security-domain="secDomainObjectName"/> </t:next> <t:next> <t:load-properties-batch locations="props/properties1.properties,props/properties2.properties" ignore-resource-not-found="true" prevent-cache="false"/> </t:next> <t:next> <t:load-properties location="props/properties1.properties" prevent-cache="false"/> </t:next> <t:next> <t:load-resource-module url="resource.swf" update="false" application-domain="appDomainObjectName" security-domain="secDomainObjectName"/> </t:next>

Page 76: Spring Action Script

The Operation API

70

<t:next> <t:load-style-module url="styles.swf" update="false" application-domain="appDomainObjectName" security-domain="secDomainObjectName" flex-module-factory="moduleFactoryName"/> </t:next> <t:next> <t:load-url url="someAsset.png" data-format="binary"/> </t:next> <t:next> <t:load-url-stream url="someAsset.png"/> </t:next></t:task>

The application domain attributes could be configured like this as well:

<t:load-resource-module url="resource.swf" update="false" application-domain="this.applicationDomain"/>

This would assign the application domain that is associated with the application context that has consumedthis configuration. See this section: 'Injecting the application context using the 'this' reference' for moreinformation.

In that same vain the flex module factory for a LoadStyleModuleOperation could be configured like this:

<t:load-style-module url="styles.swf" update="false" application-domain="this.applicationDomain" flex-module-factory="this.ownerModule.moduleFactory"/>

The composite-command XML shortcut

A CompositeCommand can also be configured using a bit of custom XML, instead of writing this...

<object id="myCompositeCommand" class="org.springextensions.actionscript.core.command.CompositeCommand"> <property name="failOnFault" value="true"/> <property name="kind"> <ref> <util:constant static-field="org.springextensions.actionscript.core.command.CompositeCommandKind.PARALLEL.value"/> </ref> </property> <method-invocation name="addCommand"> <arg> <object id="myCommand1" class="..."/> </arg> </method-invocation> <method-invocation name="addCommand"> <arg> <object id="myCommand2" class="..."/> </arg> </method-invocation> <!-- etc, etc --></object>

...this rather more abbreviated form is possible using the Task namespace handler:

<t:composite-command fail-on-fault="true" kind="parallel"> <object id="myCommand1" class="..."/> <object id="myCommand2" class="..."/></t:composite-command>

Page 77: Spring Action Script

71

Chapter 5. The EventBusIntroduction

In a de-coupled environment, its not always easy to let various components communicate with each other.In order to make this task slightly easier Spring Actionscript includes the EventBus class.

The EventBus is a final class with only static methods. In Actionscript it is not possible to define aninterface with static methods. In order to still provide an interface there does exist the IEventBus. Thisinterface is implemented by the EventBusFacade, which re-routes all of its methods to their EventBusequivalent. This way it is easier to mock up an IEventBus for unit testing purposes.

EventBus listeningThere are a number of different ways to subscribe to events that are dispatched through the EventBus:

The first is to listen to all events that are dispatched through the EventBus. This is possible throughthe EventBus.addListener method. This method expects an IEventBusListener as an argument. TheIEventBusListener looks like this:

public interface IEventBusListener {

function onEvent(event:Event):void;

}

Every event dispatched by the EventBus will be passed into the onEvent method.

The second method is to only listen for events of a specific type. Use the EventBus.addEventListener forthis task. The addEventListener method expects two arguments, the first is a string representing the eventtype, and the second is a Function instance which will be invoked with every event of the specified type.

Instead of a Function it is also possible to supply a proxy instead. This is what the addEventListenerProxymethod is for. Instead of a Function this expects a instance. The class is part of the package.

The last option is to add a listener for events of a certain class. To get this to happen use theaddEventClassListener or addEventClassListenerProxy methods. The same arguments apply to these asfor their addEventListener and addEventListenerProxy neighbours, except they expect a Class instanceinstead of a type.

All these methods naturally have a removal counterpart: removeListener, removeEventListener,removeEventListenerProxy, removeEventClassListener and removeEventClassListenerProxy.

To clear all types of registered eventlisteners at once simply call the removeAll() method.

EventBus dispatchingThis is the easiest part, to dispatch an event through the EventBus invoke either the dispatchEvent ordispatch methods. The former expects an Event instance while the latter expects a string that indicates acertain type of Event. This event will be created by this method and subsequently dispatched. For example:

EventBus.dispatchEvent(new MyCustomEvent("myCustomEventType"));

Page 78: Spring Action Script

The EventBus

72

or

EventBus.dispatch("myCustomEventType");

EventBus event handling using metadata annotationsTo prevent a lot of boilerplate code consisting of long lists of addEventListener* calls, Spring Actionscriptincludes an alternative way to define event handlers for events that are dispatched through the EventBus.

Instead of adding specific listeners functions through the addEventListener calls simply add a bit ofmetadata to the particular method:

[EventHandler]protected function saveUserHandler(event:Event):void {//implementation ommitted...}

This is the most basic way of annotating a method and immediately implies certain assumptions. In thiscase it is assumed that the saveUser method will handle an event of the type "saveUser". Another validmethod name for this handler could also be:

[EventHandler]protected function saveUser(event:Event):void {//implementation ommitted...}

If, for some reason, this naming convention is not desired then add the name of the type of the specificevent to the metadata:

[EventHandler(name="saveUser")]protected function saveTheUserNow(event:Event):void {//implementation ommitted...}

By default, an event handler function is expected to have a single argument of type Event (or any subclass).It is however possible to let Spring Actionscript match the properties of the specified event with thearguments of the event handler. For instance, if the event passed to the saveUser event is not an ordinaryevent, but a subclass called SaveUserEvent with a property that is called "user" of the type "User". In thiscase an event handler with the following signature will work just a well:

[EventHandler]protected function saveUser(user:User):void {//implementation ommitted...}

The property/argument matching is done by type, so this will fail in the case where an event has multipleproperties of the same kind. If the SaveUserEvent should have two user properties, called userA or userBfor example, the matching will fail. In that case it is possible to define the properties by name directlyin the metadata:

[EventHandler(properties="userA,userB")]protected function saveUser(userA:User, userB:User):void {//implementation ommitted...}

To annotate a handler for a certain event Class, define the fully qualified class name like this:

Page 79: Spring Action Script

The EventBus

73

[EventHandler(clazz="com.classes.events.UserEvent")]protected function saveTheUserNow(event:UserEvent):void {//implementation ommitted...}

To enable the processing of these kinds of annotations it is necessary to add an instance of theEventHandlerMetaDataPostProcessor to the application context. The easiest way to do so is to add thisbit of XML to the configuration:

<object id="eventhandlerProcessor" class="org.springextensions.actionscript.ioc.factory.config.EventHandlerMetaDataPostProcessor"/>

This will automatically register the processor with the application context.

Note

Do not forget to add the EventHandler metadata to the compiler arguments: -keep-as3-metadata+=EventHandler. Failing to do so will prevent the EventHandlerMetaDataPostProcessor to doits work.

Note

Credit where credit is due: The [EventHandler] handling is similar to the [Mediate] metadataas first introduced by in the , the Spring Actionscript team both acknowledges and appreciateshis work.

Routing other events through the EventBusOn the other side of the spectrum there is event dispatching and a way to avoid having to callEventBus.dispatch(someEvent) a zillion times. For this particular goal there is the [RouteEvents] metadatawhich can be handled by the RouteEventsMetaDataPostProcessor. Let's take a look at simple example,imagine a class that is able to dispatch a number of events:

[Event(name="eventName1",type="...")][Event(name="eventName2",type="...")][Event(name="eventName3",type="...")]public class MyClass { //implementation omitted..}

To let Spring Actionscript catch all these events, and redispatch them through the EventBus, all that isnecessary is the addition of the [RouteEvents] metadata:

[RouteEvents][Event(name="eventName1",type="...")][Event(name="eventName2",type="...")][Event(name="eventName3",type="...")]public class MyClass { //implementation omitted...}

If not all events need to be re-routed then use the 'events' argument of the [RouteEvents] metadata:

[RouteEvents(events="eventName1,eventName2")][Event(name="eventName1",type="...")][Event(name="eventName2",type="...")]

Page 80: Spring Action Script

The EventBus

74

[Event(name="eventName3",type="...")]public class MyClass { //implementation omitted...}

And that's all there is to it, now to enable this functionality add this object definition to the XMLconfiguration:

<object id="routeEventsProcessor" class="org.springextensions.actionscript.ioc.factory.config.RouteEventsMetaDataPostProcessor"/>

This will automatically register the processor with the application context.

Note

Do not forget to add the RouteEvents metadata to the compiler arguments: -keep-as3-metadata+=RouteEvents. Failing to do so will prevent the RouteEventsMetaDataPostProcessor to do itswork.

The combination of the [RouteEvents] and [EventHandler] enables a developer to leverage the EventBuswithout directly depending on it.

Metadata driven MVC micro-frameworkLeveraging the above described classes and techniques Spring Actionscript offers a small metadata drivenMVC micro-framework. These are the key components that this framework provides:

• Fully metadata driven

• Works with regular Flash events (flash.events.Event)

• No need to implement Spring Actionscript interfaces or inherit from base classes

• Plays nice in multi-module environments

The framework uses metadata tags in event and command classes to define mappings between them andthe application context as a class factory for the commands.

Getting started

First add this object definition to the application context XML configuration:

<object id="mvcFactory" class="org.springextensions.actionscript.core.mvc.MVCControllerObjectFactoryPostProcessor"/>

The MVCControllerObjectFactoryPostProcessor is an IObjectFactoryPostProcessor implementation thattakes care of all the metadata processing and event/command mapping.

This factory postprocessor first checks for the existence of an IMVCEventObjectPostProcessorimplementation in the application context, when none is found it creates an instance of theMVCRouteEventsMetaDataProcessor class and adds it to the application context singleton cache. Thisallows for the events postprocessor to be overridden by another implementation.

After that the factory postprocessor checks if an IController implementation exists in the applicationcontext, of not a Controller instance is created and added to the context so, if necessary, the IControllerinstance can be overridden again.

This takes care of the preparatory work, now all that remains is defining the event/command mappings.

Page 81: Spring Action Script

The EventBus

75

Annotating classes that dispatch MVC events

Annotating components and classes that dispatch events that need to be mapped to a command is almost thesame as annotating them for dispatch through the EventBus (the EventBus is used by this MVC frameworkas the main communication pipeline). So, let's have a simple example:

[RouteMVCEvents][Event(name="someEventType","flash.events.Event")]public class SomeClassThatDispatchesMVCEvents { //implementation ommitted...}

This means that [RouteEvents] and [RouteMVCEvents] metadata can be combined. (A class could evenbe annotated with both types of metadata.)

This is all that is necessary for the event side of things of the MVC functionality.

Annotating classes that act as MVC commands

To define a command that is to be triggered by the aforementioned event can be annotated in its simplestform like this:

[Command(eventType="someEventType")]public class CommandClass { function execute():void { //implementation ommitted... } //further implementation ommitted...}

When the command is triggered by a certain event Class, define the class like this:

[Command(eventClass="com.events.CustomEvent")]public class CommandClass { function execute():void { //implementation ommitted... } //further implementation ommitted...}

The command class does not need to implement any kind of interfaces or inherit from any base classes.By default the MVC framework will assume that a method called execute needs to be invoked. When adifferent method name is needed this can be defined in the metadata tag:

[Command(eventType="someEventType",executeMethod="process")]public class CommandClass { function process():void { //implementation ommitted... } //further implementation ommitted...}

When the execution method needs to receive a reference to the event instance it will be automaticallymapped:

[Command(eventType="someEventType",executeMethod="process")]

Page 82: Spring Action Script

The EventBus

76

public class CommandClass { function process(event:Event):void { //implementation ommitted... } //further implementation ommitted...}

Properties on the event can be automatically mapped to the method arguments as well. Imagine for instancethis event class:

public class CustomEvent extends flash.events.Event { public static const EVENT_ID:String = "someEventType";

public var user:User; //further implementation ommitted...

}

If the command class has this definition, the property will be mapped automatically:

[Command(eventType="someEventType",executeMethod="process")]public class CommandClass { function process(user:User):void { //implementation ommitted... } //further implementation ommitted...}

The event properties can also be mapped to properties on the command:

[Command(eventType="someEventType",executeMethod="process")]public class CommandClass {

public var user:User;

function process():void { //implementation ommitted... } //further implementation ommitted...}

The mapped event properties can also be explicitly named:

[Command(eventType="someEventType",executeMethod="process",properties="userA,userB")]public class CommandClass {

function process(userA:User, userB:User):void { //implementation ommitted... } //further implementation ommitted...}

Now all that is left is to add object definitions for each command that is used to the application contextXML configuration:

<object id="myCommand" class="com.classes.commands.CommandClass"/>

Page 83: Spring Action Script

The EventBus

77

Or, alternatively, every command class can be annotated with the [Component] metadata and thus will bepicked up by the class scanning system:

[Component][Command(eventType="someEventType",executeMethod="process")]public class CommandClass {}

For further information on the class scanning system see section 'The Component scanner and classscanning system'

Note

The application context can now be used as the main command classfactory, leveraging all of itsrich DI functionality. Services, models and other dependencies can be easily defined and injected.

Page 84: Spring Action Script

78

Chapter 6. The Component scannerand class scanning systemIntroduction

Besides XML and MXML, it is possible to define object definitions through metadata annotations. Thisis done using a system called component scanning.

What this does is, at application context startup, the system will scan all the classes that are defined in thecurrently loaded SWF, examine them to determine whether they have been annotated with [Component]metadata, and if so, create an ObjectDefinition based on the metadata arguments and register it with theapplication context.

To use the below explained functionality, add these elements to the XML configuration:

<objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springactionscript.org/schema/context" xsi:schemaLocation=" http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/context http://www.springactionscript.org/schema/context/spring-actionscript-context-2.0.xsd">

<context:metadata-config/> <context:component-scan/>

</objects>

or add it programmatically like this:

flexXMLApplicationContext.addObjectFactoryPostProcessor(new ClassScannerObjectFactoryPostProcessor());

Note

For now this functionality will only work with the FlexXMLApplicationContext since it makesuse of the SystemManager, at a later date we will try and implement this as well for pureactionscript projects.

Note

Don't forget to add these compiler arguments to your project to be able tomake use of the annotations as described in this chapter: -keep-as3-metadata+=Component,Property,Invoke,Constructor

[Component] metadata explainedHere is a simple example of a class that is annotated with [Component] metadata:

[Component]public class AnnotatedComponent {

Page 85: Spring Action Script

The Component scannerand class scanning system

79

public function AnnotatedComponent() { super(); }}

This will register an object definition with a generated id for the AnnotatedComponent class. The XMLequivalent of this would be:

<object class="com.class.AnnotatedComponent" id="scannedComponent#1"/>

This in itself is not very useful yet, but here is how you can set different ObjectDefinition properties usingmetadata arguments:

[Component(id="myComponent",scope="prototype",factoryMethod="getInstance")]public class AnnotatedComponent {

public function AnnotatedComponent() { super(); } public static function getInstance():AnnotatedComponent { //...implementation omitted }}

The XML equivalent for the above would be:

<object class="com.class.AnnotatedComponent" id="myComponent" scope="singleton"/>

Here is a list of all the metadata arguments that are available:

• [Component(id="componentId")]

• [Component(scope="singleton/prototype")]

• [Component(lazyInit="true/false")]

• [Component(factoryMethod="methodName")]

• [Component(factoryObjectName="objectName")]

• [Component(initMethod="methodName")]

• [Component(destroyMethod="methodName")]

• [Component(primary="true/false")]

• [Component(autowireCandidate="true/false")]

• [Component(dependencyCheck="none/simple/objects/all")]

• [Component(dependsOn="comma,delimited,list,of,object,names")]

• [Component(autowire="no,byName,byType,constructor,autodetect")]

• [Component(skipMetaData="true/false")]

• [Component(skipPostProcessors="true/false")]

Page 86: Spring Action Script

The Component scannerand class scanning system

80

Injecting constructor argumentsSince it is not possible to annotate actionscript constructors with metadata its constructor arguments willneed to be defined at class level, like so:

[Constructor(args="ref=objectName1")][Component(id="myComponent",scope="prototype")]public class AnnotatedComponent {

public function AnnotatedComponent(obj:Object) { super(); }

}

Its XML equivalent would be written like this:

<object id="myComponent" scope="prototype"> <constructor-arg ref="objectName1"/></object>

If the [Constructor] annotation is ommitted Spring Actionscript will try to resolve any availableconstructor arguments through reflection in the same way that the 'constructor' autowiring logic isperformed. See the section 'Autowiring collaborators' for more info.

Injecting propertiesNext up is how to inject property values, annotate property declarations as follows to achieve this:

[Component(id="myComponent",scope="prototype")]public class AnnotatedComponent {

public function AnnotatedComponent() { super(); } [Property(ref="someObjectNameOfMyType")] public var someProperty():MyType;

[Property(value="${propertyName}")] public var someOtherProperty():String;

}

The '${propertyName}' value means that this placeholder will be replaced by a 'real' property value oncethe ObjectDefinition is registered in the application context. The above annotations would look as followswhen configured in XML.

<object id="myComponent" scope="prototype"> <property name="someProperty" ref="someObjectNameOfMyType"/> <property name="someOtherProperty" value="${propertyName}"/></object>

The same results can also be achieved by using these annotations:

Page 87: Spring Action Script

The Component scannerand class scanning system

81

[Component(id="myComponent",scope="prototype")]public class AnnotatedComponent {

public function AnnotatedComponent() { super(); } [Autowired(name="someObjectNameOfMyType")] public var someProperty():MyType;

[Autowired(externalProperty="propertyName")] public var someOtherProperty():String;

}

There is however a subtle difference between these two techniques. In the first case, the [Property] case,the property injection will be defined as a property on the object definition. Therefore it is possible that thisdefinition will be processed by other IObjectFactoryPostProcessor implementations (and thus the propertymight be processed too) later in the application context bootstrap. In the second case, the [Autowired]case, the injections will be resolved at runtime, at the moment that the context instantiates the object.

Both cases lead to the same result, but keep these small differences in mind when choosing whichannotation to use.

Method invocationsLastly there are, of course, the method invocations. Annotating a method declaration as follows will adda MethodInvocation to the generated ObjectDefinition:

[Component(id="myComponent",scope="prototype")]public class AnnotatedComponent {

public function AnnotatedComponent() { super(); } [Invoke] public var someFunction():void;

}

Of which the XML equivalent would look as below:

<object id="myComponent" scope="prototype"> <method-invocation name="someFunction"/></object>

If the method expects arguments they can be defined like this:

[Component(id="myComponent",scope="prototype")]public class AnnotatedComponent {

public function AnnotatedComponent() { super(); }

Page 88: Spring Action Script

The Component scannerand class scanning system

82

[Invoke(args="ref=someObjectNameOfMyType, value=10")] public var someFunction(arg1:SomeType, arg2:uint):void;

}

And of course, its XML mirror:

<object id="myComponent" scope="prototype"> <method-invocation name="someFunction"> <arg ref="someObjectNameOfMyType"/> <arg value="10"/> </method-invocation></object>

Extending the class scanning systemThe component scanner is part of the more generic class scanning system. It is quite easy to extend thiswith custom scanners, in this section it will be explained how.

The IClassScanner interfaceThe ClassScannerObjectFactoryPostProcessor factory postprocessor mentioned in the introduction of thischapter will query its associated application context for the existence of any implementations.

This interface looks like this:

public interface IClassScanner {

function scan(className:String):void;

function get metaDataNames():Array;}

The metadataNames property determines which class level metadata annotations will trigger theimplementation. Once the ClassScannerObjectFactoryPostProcessor encounters a class that is annotatedwith any of this metadata, its fully qualified class name will be passed to the method.

Let's imagine an that is interested in classes that are annotated with [Service] metadata, an implementationcould inherit from the provided base class like this:

public class ServiceClassScanner extends AbstractClassScanner {

public static const SERVICE_METADATA:String = "Service";

public function ServiceClassScanner() { super([SERVICE_METADATA]); }

function scan(className:String):void { var type:Type = Type.forName(className); //... further implementation ommitted }

Page 89: Spring Action Script

The Component scannerand class scanning system

83

}

To register this implementation with the ClassScannerObjectFactoryPostProcessor add this bit of XMLconfiguration:

<object id="serviceScanner" class="com.classes.ServiceClassScanner"/>

<object id="classScanObjectFactoryPostProcessor" class="org.springextensions.actionscript.context.metadata.ClassScannerObjectFactoryPostProcessor"> <method-invocation name="addScanner"> <arg ref="serviceScanner"/> </method-invocation></object>

Or add it programmatically like this:

var factory:ClassScannerObjectFactoryPostProcessor = new ClassScannerObjectFactoryPostProcessor();factory.addScanner(new ServiceClassScanner());flexXMLApplicationContext.addObjectFactoryPostProcessor(factory);

Note

Be careful, when defining class scanners in XML, not to let them be injected with any otherinstances defined in the configuration. The ClassScannerObjectFactoryPostProcessor runs beforethe application context has finished its bootstrap, so therefore cannot be used for IoC at this stage.

Controlling the order in which class scanners areexecuted

The order in which a collection of IClassScanner implementations is executed can be controlled by havingthem implement the IOrdered interface. See the 'Controlling collection order' section for more informationon this interface.

Page 90: Spring Action Script

84

Chapter 7. TestingIntroduction

Testing is a fundamental part of software development.

Integration Testing

OverviewIt is important to be able to perform some integration testing without requiring deployment of yourapplication or connecting to other enterprise infrastructure. This will enable you to test things such as:

• The correct wiring of your Spring IOC container contexts.

The Spring ActionScript Framework provides first class support for integration testing in the form ofclasses that are packaged in the spring-actionscript-test.swc library. In this library youwill find the org.springextensisons.actionscript.test package which contain valuableclasses for integration testing using a Spring container, while at the same time not being reliant on adeployment environment. Such tests will be slower to run than unit tests, but much faster to run than theequivalent remote tests relying on deployment.

Spring ActionScript offers support for unit and integration testing in the form the Spring ActionScriptTestContext Framework, which is agnostic to the actual testing framework in use, thus allowinginstrumentation of tests in various environments. Note that the Spring ActionScript TestContextFramework currently only supports FlexUnit 4.

Common Goals

The Spring ActionScript integration testing support framework has several goals, including:

• Spring IoC Container caching between test execution.

• Dependency Injection of test fixture instances.

• Spring-specific support classes that are really useful when writing integration tests.

The following sections outline each of these goals and provide direct link to information specific to theparticular support framework.

Context management and caching

The Spring integration testing support framework provide consistent loading of SpringIApplicationContexts and caching of those context. Support for the caching of loaded contexts isimportant, because if you are working on a large project, startup time may become an issue - not because ofthe overhead of Spring itself, but because the objects instantiated by the Spring container will themselvestake time to instantiate.

Test classes will generally provide an array containing the resource locations of XML configurationmetadata - typically on the deploy path - used to configure the application. This will be the same, or nearlythe same, as the list of configuration locations specified in deployment configuration.

Page 91: Spring Action Script

Testing

85

By default, once loaded, the configured IApplicationContext will be reused for each test. Thusthe setup cost will be incurred only once (per test fixture), and subsequent test execution will be muchfaster. In the unlikely cases that a test may 'dirty' the application context, require reloading - for example,by changing an object definition or the state of an application object - Spring's testing support providesmechanisms to cause the test fixture to reload the configurations and rebuild the application context beforeexecuting the next test.

Context management and caching with:

• The TestContext Framework

Dependency Injection of test fixtures

When the Spring integration testing support framework loads your application context, it can optionallyconfigure instances of your test classes via Dependency Injection. This provides a convenient mechanismfor setting up test fixtures using pre-configured objects from your application context. A strong benefithere is that you can reuse application context across various testing scenarios (e.g., for configuring Spring-managed object graphs, DataSources, etc.), this avoiding the need to duplicate complex test fixture setup for individual test cases.

Dependency Injection of test fixtures with:

• The TestContext Framework

Integration testing support classes

The Spring integration testing support framework provides several abstract support classes that cansimplify writing integration tests. These base test classes provide well defined hooks into the testingframework as well as convenient instance variable and methods, allowing access to such things as:

• The IApplicationContext: useful for performing explicit object lookups or testing the state ofthe context as a whole.

Often you will provide an application-wide superclass for integration tests that provides further usefulinstance variables used in many tests.

Support classes for:

• The TestContext Framework

Common Metadata

The Spring ActionScript Framework provides a common set of Spring-specific metadata that you can usein your testing.

• [DirtiesContext]

The presence of this metadata on a test method indicates the underlying Spring container is 'dirtied'during the execution of the test method, and thus must be rebuilt after the test method finishes execution(regardless of whether the test passed or not).

[DirtiesContext]public function testProcessWhichDirtiesAppCtx():void { // some logic that results in the Spring container being dirtied}

Metadata support for:

Page 92: Spring Action Script

Testing

86

• The TestContext Framework: supports all of the common metadata listed abovewhile providing additional TestContext-specific (e.g., [ContextConfiguration],TestExecutionListeners, etc.). Note, however, that some metadata are only supported whenused in conjunction with FlexUnit (e.g., with the SpringFlexUnit4ClassRunner). Refer to thedocumentation in the TestContext Framework section for further details.

Spring ActionScript TestContext Framework

The Spring TestContext Framework (located in theorg.springextensions.actionscript.test.context package) provides generic,metadata driven unit and integration testing support thia is agnostic of the testing framework in use. TheTestContext framework also places a great deal of importance on convention over configuration withreasonable defaults that can overridden via metadata-based configuration.

In addition to generic testing infrastructure, the TestContext framework provides explicit support forFlexUnit 4 in the form abstract support classes. For FlexUnit 4, the framework provides a customIRunner which allows one to write test classes that are not required to extend a particular class hierarchy.

The following section provides and overview of the internals of the TestContext framework. If you areonly interested in using the framework and not necessarily interested in extending it with your own customlisteners, feel free to skip ahead to the configuration (context management, dependency injection), supportclasses, and metadata support sections.

Key abstractions

The core of the framework consists of the TestContext and TestContextManager classes andthe ITestExecutionListener interface. A TestContextManager is created on a per-test basis.The TestContextManager in turn manages a TestContext, which is responsible for holdingthe context of the current test. The TestContextManager is also responsible for updating thestate of the TestContext as the test progresses and delegating to ITestExecutionListeners,which instrument the actual test execution (e.g., providing dependency injection, dirtying context, etc.).Consult the ASDoc and the Spring ActionScript test suite for further information and example of variousconfigurations.

• TestContext: encapsulate the context in which a text is executed, agnostic of the actual testingframework in use.

• TestContextManager: the main entry point into the Spring ActionScript TestContext Framework,which is responsible for managing a single TestContext and signaling event to all registeredITestExecutionListeners at well defined test execution points: test instance preparation, priorto any before methods of a particular testing framework, and after and after methods of a particulartesting framework.

• ITestExecutionListener: defines a listener API for reacting to test execution events publishedby the TestContextManager with which the listener is registered.

Spring provides two ITestExecutionListener implementations which areconfigured by default. (via the [TestExecutionListeners] metadata):DependencyInjectionTestExecutionListener andDirtiesContextTestExecutionListener, which provide support for dependency injection ofthe test instance and handling of the [DirtiesContext] metadata, respectively.

Context management and caching

Each TestContext provides context management and caching support for the test instance forwhich it is responsible. Test instances do not automatically receive access to the configured

Page 93: Spring Action Script

Testing

87

IApplicationContext; however, if a test class implements the IApplicationContextAwareinterface, a reference to the IApplicationContext will be supplied to the test instance(provided the DependencyInjectionTestExecutionListener has been configured, whichis the default). Note that AbstractFlexUnit4SpringContextTests already implementsIApplicationContextAware and therefor provides this functionality out-of-the-box.

Configuration is achieved merely by declaring the [ContextConfiguration] metadata at the classlevel. If your test class does not explicitly declare an application context resource locations, theconfigured IContextLoader will determine how and whether or not to load a context from defaultset of locations. If your class is named com.example.MyTest, GenericXMLContextLoader willload your application context from "/com/example/MyTest-context.xml".

package com.example {

[RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")]// IApplicationContext will be loaded from "/com/example/MyTest-context.xml"[ContextConfiguration]public class MyTest { // class body...}}

If the default location does not suit your needs, you are free to explicitly configure the locationsattribute of [ContextConfiguration] (see code listing below) with a comma delimited list of theresource locations of XML configuration metadata (assuming an XML-capable IContextLoader hasbeen configured) used to configure the application. This will be the same, or nearly the same, as the listof configuration locations specified in deployment configuration. As an alternative you may choose toimplement and configure your own custom IContextLoader.

package com.example { [RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")]// IApplicationContext will be loaded from "/applicationContext.xml" and "/applicationContext-test.xml"// in the root of the deploy directory[ContextConfiguration(locations="/applicationContext.xml,/applicationContext-test.xml")]public class MyTest { // class body...}}

[ContextConfiguration] also supports a boolean inheritLocations key that denoteswhether or not resource locations from superclasses should be inherited. The default value is true,which means that an annotated class will inherit the resource locations defined by an annotated superclass.Specifically, the resource locations for an annotated class will be appended to the list of resourcelocations defined by an annotated superclass. In the following example, the IApplicationContextfor ExtendedTest will be loaded from "/base-context.xml" and "/extended-context.xml", in that order.Objects defined in "/extended-context.xml" may therefore override those defined in "/base-context.xml".

[RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")]// IApplicationContext will be loaded from "/base-context.xml" in the root of the deploy directory[ContextConfiguration(locations="/base-context.xml")]public class BaseTest { // class body...}

Page 94: Spring Action Script

Testing

88

// IApplicationContext will be loaded from "/base-context.xml" and "/extended-context.xml"// in the root of the deploy directory[ContextConfiguration(locations="/extended-context.xml")]public class ExtendedTest extends BaseTest { // class body...}

If inheritLocations is set to false, the resource locations for the annotated class will shadow andeffectively replace and resource locations defined by a superclass.

By default, once loaded, the configured IApplicationContext will be reused for each test. Thusthe setup cost will be incurred only once (per test fixture), and subsequent test execution will be muchfaster. In the unlikely case that a test may dirty the application context, requiring reloading - for example,by changing an object definition or the state of an application object - you may annotate your testmethod with [DirtiesContext] (assuming DirtiesContextTestExecutionListener hasbeen configured, which is the default) to cause the test fixture to reload the configurations and rebuild theapplication context before executing the next test.

Dependency Injection of test fixtures

When you configure the DependencyInjectionTestExecutionListener - which isconfigured by default - via the [TestExecutionListeners] metadata, the dependencies ofyour test instances will be injected from objects in the application context you configured via[ContextConfiguration] by Setter Injection, Field Injection, or both, depending on whichannotations you choose whether you place them on setter methods or fields.

Tip

The TestContext framework does not instrument the manner in which a test instance isinstantiated. Thus the use of [Autowired] for constructors has no effect for test classes.

Alternatively, if your test class implements IApplicationContextAware, you can directly accessthe IApplicationContext supplied to your test and perform an explicit lookup using (for example)a call to applicationContext.getObject("property").

If you don't want dependency injection applied to your test instances, simply don't annotate anyfields or setter methods with [Autowired]. Alternatively, you can disable dependency injectionaltogether by explicitly configuring your class with [TestExecutionListeners] and omittingDependencyInjectionTestExecutionListener from the list of listeners.

TestContext support classes

FlexUnit 4 support classes

The org.springextensions.actionscript.test.context.flexunit4 packageprovides support classes for FlexUnit 4 based test classes.

• AbstractFlexUnit4SpringContextTests:

Abstract base test class that integrates the Spring TestContext Framework with explicitIApplicationContext testing support in a FlexUnit 4 environment. When you extendAbstractFlexUnit4SpringContextTests you will have access to the following publicinstance variables:

• applicationContext: use this to perform explicit object lookups or to test the state of thecontext as a whole.

Page 95: Spring Action Script

Testing

89

Custom Flex Unit 4 Runner

The Spring TestContext Framework offers full integration with FlexUnit4 via a custom runner. By annotating test classes with[RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")],developers can implement standard FlexUnit 4 unit and integration tests and simultaneously reap thebenefits of the TestContext framework such as support for loading application contexts, dependencyinjection of test instances, etc. The following code listing displays the minimal requirement for configuringa test class to run with the custom Spring Runner. Note: that [TestExecutionListeners] has beenconfigured with an empty list in order to disable default listeners, which would otherwise require that anIApplicationContext be configured via [ContextConfiguration].

[RunWith("org.springextensions.actionscript.test.context.flexunit4.SpringFlexUnit4ClassRunner")][TestExecutionListeners("")]public class SimpleTest {

[Test] public function testMethod():void { // execute test logic... }}

TestContext framework annotation support

The Spring TestContext Framework supports all metadata as outlined in the common metadata section.The following metadata, however, are only supported when used in conjunction with FlexUnit (e.g., withthe SpringFlexUnit4ClassRunner or the FlexUnit 4 support classes.

• Not Yet Implemented

The following non-test-specific annotations are supported by the Spring TestContext Framework with theirstandard semantics.

• [Autowired]

• [Required]

The following list includes all annotations specific to the Spring TestContext Framework. Refer to therespective ASDoc for further information, including default key values.

• [ContextConfiguration]

Defines class-level metadata that is used to determine how to load and configure anIApplicationContext. Specifically, [ContextConfiguration] defines the applicationcontext resource locations to load as well as the IContextLoader strategy to use for loadingthe context.

[ContextConfiguration(locations="example/test-context.xml", loader="com.example.CustomContextLoader")]public class CustomConfiguredApplicationContextTests { // class body...}

Note: [ContextConfiguration] provides support for inherited resource locations by default. Seethe Context management and caching section and ASDoc for an example and further details.

• [TestExecutionListeners]

Page 96: Spring Action Script

Testing

90

Defines class-level metadata for configuring which ITestExecutionListeners should beregistered with a TestContextManager. Typically, [TestExecutionListeners] will beused in conjunction with [ContextConfiguration].

[ContextConfiguration][TestExecutionListeners("CustomTestExecutionListener,AnotherTestExecutionListener")]public class CustomTestExecutionListenerTests { // class body...}

Note: [TestExecutionListeners] provides support for inherited listeners by default. See theASDoc for an example and further details.

Page 97: Spring Action Script

91

Chapter 8. Spring Actionscriptextensions

IntroductionIn this section we describe several extensions of Spring Actionscript that will make the integration withother frameworks a little easier.

Cairngorm 2Spring Actionscript offers several extensions to the Cairngorm 2 micro-architecture that will make it easierto configure the various objects by the Spring Actionscript IoC container. And some of them will justmake life a little easier when working with Cairngorm. What follows is a description of how to setup aconfiguration file that will allow you to manage the Cairngorm framework externally.

Note

As you can see, we refer in this section to Cairngorm 2, the micro-architecture. A while agowas released, which isn't a framework anymore but a set of guidelines, best practices andaccompanying tools.

The ModelLocator

One of the main criticisms on Cairngorm you'll read on the internet is its heavy use of the singleton pattern.To obtain a reference to your model instance you need to call the static ApplicationModel.getInstance()method every time you need one. This tightly couples your code to a specific implementation of yourmodel, which in a world of 'High Cohesion and Loose Coupling' is somewhat of a sin.

To circumvent this problem it's a good plan to first create an interface for your model and have yourconcrete model implement this interface. This way it'll be easy to inject your model across various objectinstances in your application. The injection bit we will come to later on. First let's create a very simplemodel interface:

public interface IApplicationModel extends IEventDispatcher { function get productItems():ArrayCollection;

[Bindable(event="productItemsChanged")] function set productItems(value:ArrayCollection):void;

}

And have your actual ModelLocator implement this, like so:

public class ApplicationModel extends EventDispatcher implements IModelLocator, IApplicationModel { private static var _modelInstance : IApplicationModel;

public static function getInstance():IApplicationModel {

Page 98: Spring Action Script

Spring Actionscript extensions

92

if (!_modelInstance) { _modelInstance = new ApplicationModel(); }

return _modelInstance; }

public function ApplicationModel():void { super(); if (_modelInstance) { throw new Error('Only one ApplicationModel instance should be instantiated'); } }

private var _productItems:ArrayCollection; public function get productItems():ArrayCollection { return _productItems; }

[Bindable(event="productItemsChanged")] public function set productItems(value:ArrayCollection):void { if (value !== _productItems) { _productItems = value; dispatchEvent(new Event("productItemsChanged")); } }}

That was easy enough right? Now let's add a bit of XML to our application configuration that will makesure a model instance is created:

<object id="appModelInstance" class="com.myclasses.cairngorm.ApplicationModel" factory-method="getInstance" scope="singleton"/>

When transferring responsibility for creating our model to the IoC container, it is not even necessaryanymore to use the getInstance() factory method. Spring Actionscript will make sure only one instanceof the model is created. (Notice the singleton="true" attribute). So in all fairness, we can just change ourmodel class into this:

public class ApplicationModel extends EventDispatcher implements IModelLocator, IApplicationModel {

public function ApplicationModel():void { super(); }

private var _productItems:ArrayCollection; public function get productItems():ArrayCollection { return _productItems; } [Bindable(event="productItemsChanged")] public function set productItems(value:ArrayCollection):void { if (value !== _productItems) { _productItems = value;

Page 99: Spring Action Script

Spring Actionscript extensions

93

dispatchEvent(new Event("productItemsChanged")); } }}

And change our configuration by getting rid of the factory method call:

<object id="applicationModel" class="com.myclasses.cairngorm.ApplicationModel" scope="singleton"/>

That's it! Next up we are going to configure our FrontController and ServiceLocator.

The FrontController

When using Cairngorm without Spring Actionscript you are used to adding MXML instances of theFrontController and ServiceLocator to your application like this:

<mx:Application xmlns:control="com.cairngormclasses.control.*" xmlns:business="com.cairngormclasses.business.*" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <control:Controller id="frontController"/> <business:Services id="serviceLocator"/></mx:Application>

After that you hook up your events and commands in your FrontController in more or less this fashion:

public class Controller extends FrontController { public static const SOME_ACTION:String = "SomeActionEventID"; //----------------------------------------------------------- public function Controller() { super(); initializeCommands(); }

//-----------------------------------------------------------

public function initializeCommands():void { addCommand( Controller.SOME_ACTION, SomeActionCommand ); }}

And your service locator implementation will probably look something like this (depending on whichserver technology is being used):

<cairngorm:ServiceLocator xmlns:cairngorm="com.adobe.cairngorm.business.*" xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:RemoteObject id="SomethingRemote" endpoint="/flex2gateway/"

Page 100: Spring Action Script

Spring Actionscript extensions

94

destination="ColdFusion" source="com.myremoteobjects.someservice" concurrency="multiple" makeObjectsBindable="true" showBusyCursor="true"/>

</cairngorm:ServiceLocator>

Now this is all fine and dandy, but of course we would really like to keep configuration outside of ourcompiled code. Otherwise every time we'd like to change an event/command combination we'd have to re-compile the application. So, this is where the CairngormFrontController comes in. This class allows youto pass an object as a parameter to its constructor which holds a mapping of event id's and commands.

To configure the instantiation of the CairngormFrontController in Spring Actionscript add this snippet ofXML to your configuration:

<object id="frontController" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton"><constructor-arg> <object> <!-- Add a new property for each event/command mapping: --> <property name="SomeActionEventID" value="SomeActionCommand"/> </object></constructor-arg><!-- The following argument is optional --><constructor-arg value="com.mycommands.command"/></object>

The first argument is the object that contains the mapping between the event names and the commandclasses. The second argument is optional and defines the package where the command classes reside. Byspecifying this argument, you don't need to define the fully qualified class names of the commands.

We can now leave out the FrontController class, but beware: we need to make sure that the commandclasses get compiled in the swf of our application. We can do this by referencing them in our application.We'll also reference the CairngormFrontController class:

private var _cairngormFrontController:CairngormFrontController;private var _commands:Array = [SomeActionCommand];

The MXML declarations of the FrontController and ServiceLocator have become obsolete by now, so let'sget rid of them:

<mx:Application xmlns:control="com.cairngormclasses.control.*" xmlns:business="com.cairngormclasses.business.*" xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <!-- control:Controller id="frontController"/ --> <!-- business:Services id="serviceLocator"/ --></mx:Application>

Batch command support

In some cases its not necessarily convenient to have a separate event for every command that you wantto execute. Especially in bootstrap scenario's it can come in handy if a single event can trigger several

Page 101: Spring Action Script

Spring Actionscript extensions

95

commands. For instance, an event called ExecuteBootstrapEvent triggers a command that retrieves thelocale data, one for default user settings, etc, etc.

The CairngormFrontController supports this behaviour by default. It is determined by theallowCommandBatches property which is set to true by default.

What this does is allow you to associate more than one command with a single event, in the configurationmarkup this is done simply like this:

<object id="frontController" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton"><constructor-arg> <object> <!-- Add a new property for each event/command mapping: --> <property name="SomeActionEventID" value="SomeActionCommand"/> <property name="SomeActionEventID" value="AnotherActionCommand"/> </object></constructor-arg></object>

Now, when a CairngormEvent is dispatched with the id SomeActionEventID, both theSomeActionCommand and AnotherActionCommand classes will be created and executed.

Note

Another way of treating this scenario is to use an EventSequence, as described in the section'Event Sequences'.

Module support in the CairngormFrontController

One big drawback and limiting factor of the regular FrontController is that it doesn't play nice in a multiplemodule scenario. Meaning, in the case where two FrontController instances are created for two differentmodules, yet both instances have associated a command with the same event id, this will actually triggerboth commands when this specified event is dispatched. The reason for this is the dependency that theFrontController has on the CairngormEventDispatcher, which is a singleton. So both controllers will listenfor the same event from one instance of the CairngormEventDispatcher.

An example of this behavior could be an event that retrieves module settings. (Not too uncommon).Imagine that this event has an id called "GetSettingEventId". Now the first module loads, itsFrontController gets instantiated and then some time after this the GetSettings event is dispatched. So farso good, the FrontController detects the event being dispatched and executes its associated GetSettingscommand which in turn calls a delegate, etc. However, when a second module gets loaded which alsoneeds to retrieve its settings both controllers will detect the GetSettings event and both of them will executetheir command. Which will lead to all kinds of interesting results you might imagine.

Naturally it would be desirable to somehow associate a FrontController with a specific module and whenevents are dispatched within this module only the associated controller will be triggered.

Spring Actionscript's CairngormFrontController offers support for multiple module scenario's. Thisfunctionality doesn't rely on a singleton event dispatcher but uses event bubbling instead. This does demanda certain way of setting things up though and this section will show you exactly how.

Registering your module with the CairngormFrontController

After the CairngormFrontController has been created it needs to know in which module's context itsrunning. You can do this by invoking the CairngormFrontController's register() method and passing the

Page 102: Spring Action Script

Spring Actionscript extensions

96

current module instance to it. As an example, imagine a module's CREATION_COMPLETE event handlerto be looking something like this:

public function creationComplete_handler(event:FlexEvent):void { var frontController:CairngormFrontController = _applicationContext.getObject("moduleController") as CairngormFrontController; frontController.register(this);}

After this the CairngormFrontController's instance will only be triggered by events that are dispatchedwithin this module's context.

Bubbling your Cairngorm events up to the CairngormFrontController

One thing you will have to make sure of is that your CairngormEvents are created with event bubbling setto true and dispatched through one of the UI components dispatchEvent() invocations.

For example, if a button click needs to trigger a CairngormEvent, you used to dispatch it like this:

public function click_handler(event:MouseEvent):void { CairngormEventDispatcher.getInstance().dispatchEvent(new MyCairngormEvent());}

Or, you'd use the shorthand version:

public function click_handler(event:MouseEvent):void { new MyCairngormEvent().dispatch();}

The difference now is that you will dispatch the event through a UIComponent that is part of the displayhierarchy of the module, so instead you can dispatch the event like this:

public function click_handler(event:MouseEvent):void { this.dispatchEvent(new MyCairngormEvent());}

By default though, a CairngormEvent is created with its bubbling property set to false. So make sure thatCairngormEvents that are used in combination with the CairngormFrontController that uses a registeredmodule are always created with their bubbling property set to true.

var newEvent:MyCairngormEvent = new MyCairngormEvent("MyCairngormEventID",true);

For your convenience Spring Actionscript has a base class for this particular type of CairngormEvent calledSASCairngormModuleEvent. This CairngormEvent subclass has its bubbling property forced to true andwill throw an Error when the built-in dispatch() method is accidentally invoked.

If you are dispatching your Cairngorm events from a non-visual class, say a mediator or some subcontrolleryou will have to make sure that this class has a reference to an IEventDispatcher instance that is part ofthe UI hierarchy. Here's an example of a very simple mediator class:

public class ExampleMediator extends EventDispatcher implements IExampleMediator {

public function ExampleMediator(target:IEventDispatcher=null) { super(target); }

Page 103: Spring Action Script

Spring Actionscript extensions

97

public function remoteOperation():void { dispatchEvent(new MyCairngormEvent()); }

}

Now to make an instance of this class to bubble its events up the UI hierarchy create it with the module as aconstructor argument, so the module's CREATION_COMPLETE event handler could now look somethinglike this:

public function creationComplete_handler(event:FlexEvent):void { var frontController:CairngormFrontController = _applicationContext.getObject("moduleController") as CairngormFrontController; frontController.register(this);

var exampleMediator:ExampleMediator = _applicationContext.getObject("exampleMediator",this) as ExampleMediator;}}

Injecting the module instance into the CairngormFrontController

Naturally the ideal situation would be where we can determine which module gets registered with whichCairngormFrontController using our beloved Spring Actionscript configuration markup. In this section weshow you one possible way of wiring up your objects using functionality that is already a part of SpringActionscript.

First of all we create a simple class that will be responsible for receiving a module instance and somehowassociate this with a particular CairngormFrontController. Let's say this class looks like this:

public class CairngormFrontControllerWireAgent implements IObjectFactoryAware {

private var _moduleMap:Dictionary; private var _objectFactory:IObjectFactory;

public function ModuleFrontControllerWireAgent(moduleMap:Dictionary){ Assert.notNull(moduleMap,"moduleMap argument must not be null"); _moduleMap = moduleMap; }

public function evaluate(component:Object):void { Assert.notNull(_objectFactory,"_objectFactory must not be null"); var module:Module = (component as Module); if (module != null) { var name:String = module.name; var frontControllerName:String = _moduleMap[name]; if (frontControllerName != null) { var frontController:CairngormFrontController = _objectFactory.getObject(frontControllerName) as CairngormFrontController; if (frontController != null){ frontController.register(module); } } } }

public function set objectFactory(value:IObjectFactory):void { _objectFactory = value; }

Page 104: Spring Action Script

Spring Actionscript extensions

98

}

Note

Notice the use of the Assert.notNull() method, this is part of the as3commons-lang library, formore information about this Spring Actionscript spin off visit

As you see this class receives a dictionary as a constructor argument, this dictionary is a collection ofmodule name / FrontController name key-value pairs. To configure this class using Spring Actionscriptmarkup your configuration might look something like this:

<object id="frontcontrollerWireAgent" class="com.classes.CairngormFrontControllerWireAgent" scope="singleton"> <constructor-arg> <dictionary> <entry key="mymodulename" value="frontcontrollerA"/> </dictionary> </constructor-arg></object>

<object id="frontcontrollerA" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton" lazy-init="true"> <!-- configuration omitted for brevity --></object>

Now only remains the question when and how to let the CairngormFrontControllerWireAgent work itsmagic, for this last task Spring Actionscript already offers the StageComponentInterceptionPostProcessorclass. (See the section 'Injecting stage components into other objects' and 'The stage interception schema'for the complete lowdown on this class).

Let's dive right in and show how to configure this class to leverage a CairngormFrontControllerWireAgentinstance:

<objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:si="http://www.springactionscript.org/schema/stageinterception" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/objects/spring-actionscript-stageinterception-1.0.xsd">

<object id="frontcontrollerWireAgent" class="com.classes.CairngormFrontControllerWireAgent" scope="singleton"> <constructor-arg> <dictionary> <entry key="mymodulename" value="frontcontrollerA"/> </dictionary> </constructor-arg> </object>

<object id="frontcontrollerA" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton" lazy-init="true"> <!-- configuration omitted for brevity --> </object> <si:stageinterceptor target-object="frontcontrollerWireAgent" target-method="evaluate" object-selector="moduleSelector" id="stageInterceptor"/>

Page 105: Spring Action Script

Spring Actionscript extensions

99

<object id="moduleSelector" class="org.springextensions.actionscript.ioc.wire.TypeBasedObjectSelector"> <constructor-arg> <array> <value type="class">mx.modules.Module</value> </array> </constructor-arg> </object>

</objects>

And that's the gist of it, right after your module has been loaded and added to the stage the stage interceptorkicks into gear and makes sure the CairngormFrontControllerWireAgent performs the necessary injectionsand you're good to go.

The ServiceLocator

Now what about that ServiceLocator? Having all that remoting configuration right inside your source codeis also not very convenient. What if the paths are different between staging and production servers? Whatif you'd like to change the remote path later on while already being in production? Right now all of thosechanges would require a re-compile of the application. A re-compile that is unnecessary when you useSpring Actionscript to configure your ServiceLocator.

To be able to configure the services at runtime Spring Actionscript offers a subclass of the normalServiceLocator that allows just this. The class we're talking about is the CairngormServiceLocator. Tohave the container create an instance of this class, add this bit of markup to your application configuration.

<object id="serviceLocator" class="org.springextensions.actionscript.cairngorm.business.CairngormServiceLocator" factory-method="getInstance"> <!-- The CairngormServiceLocator is marked with the dynamic keyword, so new properties can be added at runtime: --> <property name="testService"> <ref>testService</ref> </property></object>

As you'll notice by the <ref/> element used in the testService property, this ServiceLocator already hasone service configured.

The testService (RemoteObject) instance is defined like this:

<object id="testService" class="mx.rpc.remoting.mxml.RemoteObject" scope="singleton"> <property name="id" value="testService"/> <property name="endpoint" value="/flex2gateway/"/> <property name="destination="ColdFusion"/> <property name="source" value="com.myremoteobjects.someservice"/> <property name="showBusyCursor" value="true"/> <property name="makeObjectsBindable" value="true"/></object>

Of course, afterwards make sure the appropriate classes are referenced in your source code, otherwise youwill experience run-time errors because the classes will not have been compiled into your swf:

private var _cairngormFrontController:CairngormFrontController;private var _cairngormServiceLocator:CairngormServiceLocator;private var _remoteObject:mx.rpc.remoting.mxml.RemoteObject;

Page 106: Spring Action Script

Spring Actionscript extensions

100

private var _commands:Array = [SomeActionCommand];

Channel configuration

But wait a minute, that RemoteObject right now makes use of the default configured channel set in Flex,how about we pull that into our configuration as well?

Doing this is quite easy, just add this bit of XML:

<object id="amfChannel" class="mx.messaging.channels.AMFChannel" scope="singleton"> <constructor-arg value="my-amf"/> <constructor-arg value="http://{server.name}:{server.port}/flex2gateway/"/> <property name="id" value="amfChannel"/> <property name="pollingEnabled" value="false"/></object>

<object id="channelset" class="mx.messaging.ChannelSet" scope="singleton"> <method-invocation name="addChannel"> <arg> <ref>amfChannel</ref> </arg> </method-invocation></object>

And add an extra property to your RemoteObject configuration, like this:

<object id="testService" class="mx.rpc.remoting.mxml.RemoteObject"> <property name="id" value="testService"/> <property name="destination="ColdFusion"/> <property name="source" value="com.myremoteobjects.someservice"/> <property name="showBusyCursor" value="true"/> <property name="makeObjectsBindable" value="true"/> <property name="channelSet"> <ref>channelset</ref> </property></object>

Spring Actionscript also offers some convenience markup to make configuring channels a little easier. Seethe section 'The messaging schema' for more information.

RemoteObject template

Now there's a fair chance that this will not be the only RemoteObject that you'll be using in your application,usually there's a multiple of them. Let's add a template to the configuration that will save a bit of typingwhen adding new ones:

<template id="remoteObject"> <object class="mx.rpc.remoting.mxml.RemoteObject" scope="singleton"> <property name="destination" value="ColdFusion"/> <property name="source" value="com.myremoteobjects.${serviceClass}"/> <property name="channelSet"> <ref>channelset</ref> </property> </object>

Page 107: Spring Action Script

Spring Actionscript extensions

101

</template>

Now you can change the configuration for the testService into markup that looks like this:

<object id="testService" template="remoteObject"> <param name="serviceClass" value="someservice"/></object>

Spring Actionscript also offers some convenience markup to make configuring remote objects a littleeasier. See the section 'The RPC schema' for more information.

The Command Factory

The FrontController usually takes care of instantiating the command classes that are mapped to your events.This starts to become inconvenient when a Command instance needs a reference to, for example, themodel instance. (A situation which will occur quite regularly.) Normally you would just add a directreference into your command class through a call to the applicationModel.getInstance() method. This iswhat we call 'tight coupling' and is undesirable since it leaves the command directly dependent on a specificimplementation of the model class. For example, this will make unit testing the class a lot harder sinceyour unit test will be dependent on that same model instance.

So what we'd like to be able to do is inject this model instance into the command after it has been created.Spring Actionscript offers the ICommandFactory interface to solve this problem.

The interface is very simple and requires only to implement two methods:

public function canCreate(clazz:Class):Boolean;public function createCommand(clazz:Class):ICommand;

The result of the canCreate() method determines whether the specific command factory is able to createthe requested command class. In this method you could check if a command implements a certain interfaceor look it up in a list of command classes that was injected at runtime.

If the canCreate() method returns true it will be save to call the createCommand() method which returnsthe actual instance of the requested class.

The CairngormFrontcontroller actually creates an implementation of this interface internally. ThisICommandFactory implementation checks whether the specified class implements the ICommandinterface and creates the command or not accordingly.

Note

When you import both Cairngorm and Spring Actionscript youwill notice there are two definitions for the ICommandinterface, namely org.springextensions.actionscript.core.command.ICommand andcom.adobe.cairngorm.commands.ICommand. In this case you need to import the latter.

Now, to solve your little model injection problem, let's say you define a small interface calledIApplicationModelAware. The definition of which could simply be like this:

public interface IApplicationModelAware { function set applicationModel(value:IApplicationModel):void; }

Page 108: Spring Action Script

Spring Actionscript extensions

102

Where the IApplicationModel is the interface you have created to describe your model.

Now you can go ahead and create a base class for all your commands that require a reference to the model:

public class CommandBase extends AbstractResponderCommand implements IApplicationModelAware { public function CommandBase() { super(); }

private var _applicationModel:IApplicationModel; function get applicationModel():IApplicationModel { return _applicationModel; } function set applicationModel(value:IApplicationModel):void { _applicationModel = value; }

override public function execute(event:CairngormEvent):void { super.execute(event); }

override public function result(data:Object):void { throw new Error("Not implemented in base class"); }

override public function fault(info:Object):void { throw new Error("Not implemented in base class"); } }

To be able to create subclasses of this command and inject them with a model reference we can nowconstruct an implementation of the ICommandFactory interface:

public class ApplicationModelAwareCommandFactory implements ICommandFactory, IApplicationModelAware {

public function CommandFactory() { super(); }

private var _applicationModel:IApplicationModel; function set applicationModel(value:IApplicationModel):void { _applicationModel = value; }

public function canCreate(clazz:Class):Boolean { return (ClassUtils.isSubclassOf(clazz, CommandBase)); }

public function createCommand(clazz:Class):ICommand { var result:CommandBase = new clazz();

Page 109: Spring Action Script

Spring Actionscript extensions

103

result.applicationModel = _applicationModel; return result; }}

Note

You will notice the use of the ClassUtils class in this code example. This is part of theas3commons-lang library, part of the as3commons library, which can be found here:

As you see the ApplicationModelAwareCommandFactory implements the same IApplicationModelAwareinterface as well. Now, to be able to inject the model into our new factory and after that inject it intoour controller we need to add some XML to our application configuration. First let's create the commandfactory:

<object id="appAwareCmdFactory" class="com.myclasses.cairngorm.factories.ApplicationModelAwareCommandFactory" scope="singleton"> <property name="applicationModel" ref="appModelInstance"/></object>

Remember how we already added markup to instantiate our model? We now use the context id of thatobject to inject it into our command factory.

Now we can change the XML markup that configures our controller:

<object id="frontController" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton"> <constructor-arg> <object> <property name="SomeActionEventID" value="SomeActionCommand"/> </object> </constructor-arg> <!-- The followoing argument is optional --> <constructor-arg value="com.mycommands.command"/> <!-- Add a custom command factory instance --> <method-invocation name="addCommandFactory"> <arg><ref>appAwareCmdFactory</ref></arg> </method-invocation></object>

And there we are! From now on every command that is added to our FrontController (and subclasses theCommandBase class) will be automatically injected with the ApplicationModel instance after creation.

Using the application context as a command factory

Its unnecessary to create an ICommandFactory if the injections can be expressed in the XMLconfiguration. In this case, just define the definitions for the commands in the application context and addthem to the front controller like this:

<object id="someActionCommandID" class="com.class.commands.MyCommand"><!-- omitted configuration --></object>

<object id="frontController" class="org.springextensions.actionscript.cairngorm.control.CairngormFrontController" scope="singleton"> <constructor-arg> <object> <property name="SomeActionEventID" value="someActionCommandID"/>

Page 110: Spring Action Script

Spring Actionscript extensions

104

</object> </constructor-arg></object>

The Delegate Factory

Cairngorm commands need delegates, these delegates are responsible for retrieving and sending the datain the application. One way to do this is to create an instance of a specific delegate inside the commandclass. Let's create an example command class that handles the retrieval of products:

public class GetProductItemsCommand extends CommandBase { private var _delegate:GetProductItemsDelegate; public function GetProductItemsCommand() { super(); //create the specific delegate class and pass ourselves as its responder _delegate = new GetProductItemsDelegate(this as IResponder); }

override public function execute(event:CairngormEvent):void { super.execute(event); //execute the delegate logic _delegate.getProductItems(); }

override public function result(data:Object):void { // Business logic to handle the data retrieval }

override public function fault(info:Object):void { // Logic to handle errors } }

Again this tightly couples the command to a specific delegate. For example, what if we want to replacethis delegate with a mock version that simply returns test data? What is needed, again, is an interface, onethat describes the functionality of our delegate. Spring Actionscript already offers an interface that we canuse as a base for this. Its called IBusinessDelegate.

The GetProductItemsDelegate declaration could look a little like this:

public interface IGetProductItemsDelegate extends IBusinessDelegate { function getProductItems():void; }

An implementation of the interface can conveniently inherit from the already availableAbstractBusinessDelegate class:

public class GetProductItemsDelegate extends AbstractBusinessDelegate { public function GetProductItemsDelegate(service:* = null, responder:IResponder = null) { super(service, responder);

Page 111: Spring Action Script

Spring Actionscript extensions

105

} public function getProductItems():void { var token:AsyncToken = service.getProductItems(); token.addResponder(this.responder); }}

Now its time to change the base command class. You can see we were already inheriting fromthe AbstractResponderCommand class provided by Spring Actionscript. This class already exposes aproperty called businessDelegate which expects an instance of IBusinessDelegate. Since we made ourIGetProductItemsDelegate inherit from this interface we can use this property in our command class. Wecan delete the creation of the delegate altogether and simply cast the value of the businessDelegate propertyto our own delegate interface.

We'll make sure an appropriate instance will be injected later on, first let's change our command into this:

public class GetProductItemsCommand extends CommandBase { public function GetProductItemsCommand() { super(); }

override public function execute(event:CairngormEvent):void { super.execute(event); //execute the delegate logic IGetProductItemsDelegate(this.businessDelegate).getProductItems(); }

override public function result(data:Object):void { // Business logic to handle the data retrieval }

override public function fault(info:Object):void { // Logic to handle errors }}

Nothing fancy there either, actually we just made our class smaller which always good, right?

Now we want to be able to create an instance of the GetProductItemsDelegate and inject it intoour GetProductItemsCommand once its created by the command factory. Luckily Spring Actionscriptalready offers a class that performs exactly this task for you. The ResponderCommandFactory classto be precise. This class (an implementation of IResponderCommandFactory) has a method calledaddBusinessDelegateFactory() which expects an instance of IBusinessDelegateFactory and an array ofcommand classes.

Before we forget, first let's change the implementation of our command class so that it inherits fromResponderCommandFactory:

public class ApplicationModelAwareCommandFactory extends ResponderCommandFactory implements IApplicationModelAware {

public function CommandFactory() { super(); }

Page 112: Spring Action Script

Spring Actionscript extensions

106

private var _applicationModel:IApplicationModel;

function set applicationModel(value:IApplicationModel):void { _modelInstance = value; }

override public function canCreate(clazz:Class):Boolean { //First check if we can create the specified class, then ask our super class if he agrees with us: if (ClassUtils.isSubclassOf(clazz, CommandBase)) { return super.canCreate(clazz); } return false; }

override public function createCommand(clazz:Class):ICommand { //First have our super class create and inject an instance, after that we perform our own injection and finaly return the result: var result:CommandBase = super.createCommand(clazz) as CommandBase; result.applicationModel = _applicationModel; return result; }}

Well, then it is finally time to tie everything together and the place to do this of course is the SpringActionscript configuration.

First of all, let's define our BusinessDelegate factory:

<object id="businessDelegateFactory" class="org.springextensions.actionscript.cairngorm.business.BusinessDelegateFactory" scope="singleton"> <property name="service" ref="testService"/> <property name="delegateClass" type="class" value="com.myclasses.delegates.GetProductItemsDelegate"></property></object>

After that we can create the new command factory and add our business delegate factory to it, along withthe name of our command classes. (well, in our case just one command class). To do this we change ourexisting definition we created earlier:

<object id="appAwareCmdFactory" class="com.myclasses.cairngorm.factories.ApplicationModelAwareCommandFactory" scope="singleton"> <property name="applicationModel" ref="appModelInstance"/> <method-invocation name="addBusinessDelegateFactory"> <arg> <ref>businessDelegateFactory</ref> </arg> <arg> <array> <value type="Class">com.myclasses.commands.GetProductItemsCommand</value> </array> <arg> </method-invocation></object>

By passing a reference to our businessDelegateFactory to the addBusinessDelegateFactory() method alongwith the classname of our command, we tell the command factory that each time he creates an instance ofour command he can use the business delegate factory to create a delegate for it. If more command classesuse the same delegate, just add their class to the array of class names. If a different delegate is needed

Page 113: Spring Action Script

Spring Actionscript extensions

107

than add another definition to your application configuration. And if more complex injection needs to beperformed, go right ahead and subclass the existing Spring Actionscript extensions for your convenience.

And there we are, our complete Cairngorm configuration is now loosely coupled and fully managed bythe Spring Actionscript container!

Now go ahead and start coding!

The IDataTranslator interface

When dealing with web services you will typically receive a response that consists of an XML string (butother formats such as JSON, CSV or anything else are possible too of course). This XML is not particularlyuseful within an application so naturally this XML will need to be converted into business or value objects.You can choose to perform this conversion either in your delegate or your command class after a responsehas been received. However, these classes aren't really meant to perform this task, and that's why SpringActionscript offers the IDataTranslator interface.

The interface, as usual, is a very simple one:

public interface IDataTranslator { function translate(data:*):*;}

This enables an IDataTranslator implementation to take a generic input and return a generic output.

Now what we'd like to be able to do is inject an IDataTranslator into a delegate instance when appropriate,since not all delegates will need one naturally. So, what we need is a delegate instance that implementsthe IDataTranslatorAware interface.

This particular interface will not make you scream in terror of its complexity either:

public interface IDataTranslatorAware { function set dataTranslator(value:IDataTranslator):void;}

Spring Actionscript offers a base class for such a delegate calledAbstractDataTranslatorAwareBusinessDelegate. If you want to create a delegate that makes use of anIDataTranslator implementation then simply derive from this class. Here's a simple example of anAbstractDataTranslatorAwareBusinessDelegate subclass:

public class GetProductsDelegate extends AbstractDataTranslatorAwareBusinessDelegate {

public function GetProductsDelegate(service:*=null, responder:IResponder=null, dataTranslator:IDataTranslator=null) { super(service, responder, dataTranslator); }

public function getProducts():void { var token:AsyncToken = service.getProducts(); addResponderToToken(token); }}

Notice the one line in bold, this is where we call a method in the base class that takes care of interceptingthe service call, sending the input to the assigned IDataTranslator and afterwards sending its result backto the delegate's responder.

Page 114: Spring Action Script

Spring Actionscript extensions

108

Now, a simplified implementation of an IDataTranslator that takes an XML response and turns it into anarray of objects is shown below:

public class XMLToProductsDataTranslator implements IDataTranslator {

public function XMLToProductsDataTranslator() { }

public function translate(data:*):* { var productsArray:Array = []; var productsXML:XML = new XML(data);

//Conversion logic omitted for clarity...

return productsArray; }}

To configure the delegate to use this particular IDataTranslator you can add this bit of markup to yourconfiguration file:

<object id="productTranslator" class="com.mytranslators.XMLToProductsDataTranslator"/>

<object id="productsDelegate" class="com.mydelegates.GetProductsDelegate"> <property name="dataTranslator" ref="productTranslator"/></object>

Or you can create your own version of the delegate factory that handles this kind of injection.

Note

Credit where credit is due: This addition to the Spring Actionscript Cairngorm extensions wasinspired by this blog post by Adam Flater:

Event Sequences

Problem

We want to be able to execute commands in a sequence, where each command needs to be executed afterthe previous command has finished. This can be right after a call to execute() in case the command onlyimplements ICommand, or after the invocation of the result() or fault() method, in case the commandimplements the IResponder interface and fetches some remote data.

The way to do this in Cairngorm is to let your command extend SequenceCommand - which acts as anabstract base class for commands that are executed in a sequence. Then you assign a value to the nextEventproperty and call the executeNextCommand() method. This is done in the execute() method, the result()or fault() handler of the command. Each sequence command contains logic that says which command toexecute next.

This has a major drawback though: since the sequence logic is coded in the commands themselves, it isvery hard - not to say impossible without extra conditional logic - to reuse the command outside a sequenceor in another sequence.

Solution

Page 115: Spring Action Script

Spring Actionscript extensions

109

Instead of extending SequenceCommand and coding the sequence logic in the commands themselves,let's define a sequence of events outside of the commands. The commands themselves should not extendSequenceCommand. This will allow to create "standalone" commands that have their specific task andthen chain them into a variety of sequences.

Explanation

The solution Spring Actionscript offers comes in the form of the EventSequence class. As said earlier,we want to have a non-intrusive way of defining sequences of events/commands without the need to codesequence logic in the commands. As an example, let's take an event that causes the user to log in, afterwhich another event is dispatched to fetch the latest private messages for that user. In Cairngorm we wouldhave the following:

public function LoginCommand extends SequenceCommand implements IResponder {

// code left out...

public function result(data:Object):void { var user:UserVO = data.result as UserVO; ModelLocator.getInstance().user = user; // here is the problem, the command knows what command to execute next // we can't reuse this command in another chain nextEvent = new LoadPrivateMessagesEvent(user.id); executeNextCommand(); }

}

In the above code, the sequence logic in the result() handler prevents us from reusing the command outsideof the sequence or in another sequence. This will most often result in duplicate code which makes thecode base hard to maintain.

Looking at the flow of events and commands, we see that in most cases (but not all) a command will updatesome property in the ModelLocator. This is a good practice, because it keeps your commands consistentacross your application: a command executes, proxies a remote call through a business delegate, adds itselfas a responder to the remote call, updates the ModelLocator in the result() or fault() handler.

Example

Let's dive into an example of the EventSequence. The different parts will be explained individually:

var sequence:EventSequence = new EventSequence();

//add a first event to the sequence which let's the user log in

sequence.addSequenceEvent( LoginUserEvent, [username, password]);

//add a second event which fetches the latest private messages

sequence.addSequenceEvent( LoadPrivateMessagesEvent, [new Property(ModelLocator.getInstance, "user", "id")],

Page 116: Spring Action Script

Spring Actionscript extensions

110

[new Property(ModelLocator.getInstance, "user")]);

// start the sequence

sequence.dispatch();

Explanation

First thing we need to do of course is create a sequence. We can do this by creating an instance ofEventSequence.

Next, the sequence expects us to define different events in it so that it knows when to fire which event.We do this by calling addSequenceEvent() on the sequence and passing in the properties of the event wewant the sequence to dispatch.

sequence.addSequenceEvent( LoginUserEvent, [username, password]);

The first argument is the class of the event. In our case this is LoginUserEvent with has 2 constructorparameters: username and password. These parameters are defined in the second argument of theaddSequenceEvent() method as an array.

There are 2 options:

1. we pass in concrete values

2. we pass in an instance of Property which let's us define a lookup of a property (if you are familiar withBindingUtils, you will already know how this works)

The first option, passing in a concrete value, is quite straight forward. In case of the LoginUserEvent wepass in the credentials of the user, which will normally be fetched from the text inputs of the login form.So the definition of this could look as follows:

sequence.addSequenceEvent( LoginUserEvent, [username, password]);

The second option is a property that will be evaluated or looked up at runtime and is defined by a host anda chain. In case of the second event, we want to pass in the user's id, but we can only do this if the useris defined in the ModelLocator and has a valid id (this will be after executing the LoginUserCommand).Doing the following wouldn't work (don't worry about the 3rd argument for now):

sequence.addSequenceEvent( LoadPrivateMessagesEvent, [ModelLocator.getInstance.user.id], [new Property(ModelLocator.getInstance, "user")]);

This will result in a runtime error (null pointer exception) because we want to pass in the concrete value ofthe user's id when we define the sequence. Since the ModelLocator does not contain a valid user instanceat that point, this won't work. Therefor we need to define the value as a property of which the value willbe "looked up" when we really need it (that is when firing the next event in our case).

Page 117: Spring Action Script

Spring Actionscript extensions

111

The property defines a host: that is the variable that contains - or better will contain - the needed parametersfor the event. In our case this is the model locator, so ModelLocator.getInstance(). The remainingarguments of the property instance are a chain of properties of the host defined as strings. So to get theuser's id from the model locator we would define the following:

var p:Property = new Property(ModelLocator.getInstance(), "user", "id");

The third argument of the addSequenceEvent() defines a trigger that will instruct the next event to be fired.In the example above, the next event will get fired when the user property of the model locator has changed.

After we have defined the sequence, all we need to do is call it's dispatch method. Also, the event/commandmapping is still defined in the front controller, just like you would do without sequences. There is no needto specify any custom mapping.

Where to create sequences?

Normally one would create a subclass of EventSequence and define the sequence in the constructor. Onewould then instantiate the sequence in the appropriate view and dispatch it from there.

An alternative approach could be that the front controller has support for defining sequences. We wouldthen have a centralized place for specifying these sequences instead of having them scattered in differentclasses. In this case there should also be a way of launching a sequence from the view. There's no suchfeature yet in the Spring Actionscript extensions but if enough requests are made by the community theycan be implemented in due time.

What if the command does not update the model locator.

There will be times when a command does not update a property in the model locator. So wedon't really have a point in time when we know we should trigger the next event. To solve this,the CairngormFrontController registers every executing command in a central registry called thePendingCommandRegistry. The command then has do decide when its action is finished and unregisteritself:

public function result(data:Object):void { // do some stuff // ... now let the sequence know this command is done // we do this indirectly by unregistering PendingCommandRegistry.getInstance().unregister(this);}

When calling unregister, the event sequence will get notified of this and trigger the next event if any.

PureMVCThe following section documents the functionality and ideas behind the Spring Actionscript PureMVCextensions as written by their main author Damir Murat.

Note

The sample projects for the PuremVC extensions can be found in this .

General notes, intentions, plans and vision

After some learning, investigation and playing with Flex and ActionScript 3, I've headed toward findingways which can simplify implementation of large-scale enterprise applications in Flex. Why is this needed?

Page 118: Spring Action Script

Spring Actionscript extensions

112

Well, I see Flex as a so called "application framework" which can significantly simplify attractive GUIcreation, but it doesn't really help in application structuring. That application structure and architectureare important in big projects for various reasons. Most notably, it provides maintainability and scalabilityof an application code, but it also defines rules and patterns which can serve as a common denominatorfor a development team.

In that area I've found only two prominent candidates at the time: Adobe's Cairngorm and PureMVC. Ifirst tried Cairngorm, but I didn't really like it, so I tried PureMvc next. In my opinion, PureMvc representsa very solid foundation for building Flex applications. It is well structured and designed, created aroundcore interfaces which define main framework rules, and it certainly can provide the structure needed formany non trivial applications. It is also very well documented.

While I was going through the PureMvc documentation and samples, I was a little bit surprised to seethat the PureMvc applications are usually coded to concrete classes instead to interfaces. For example, thetypical PureMVC idiom for using a registered proxy instance is to write something like this in a command:

public class DeleteUserCommand extends SimpleCommand implements ICommand { override public function execute(notification:INotification):void { var user:UserVO = notification.getBody() as UserVO; var userProxy:UserProxy = facade.retrieveProxy(UserProxy.NAME) as UserProxy; var roleProxy:RoleProxy = facade.retrieveProxy(RoleProxy.NAME) as RoleProxy; userProxy.deleteItem(user); roleProxy.deleteItem(user); sendNotification(ApplicationFacade.USER_DELETED); }}

Note

The code is taken from the PureMVC Arch101Demo sample

Here you can find the dependencies to the concrete classes UserProxy and RoleProxy. Of course, thisparticular case can be refactored to the interfaces, but I'm just trying to illustrate the common usage.Further, it will be ideal if you have an ability just to express the dependencies through setters and gettersand that some external entity fulfills them by injecting them automatically at runtime. In such scenario,your command will not be dependent on concrete classes, and at the same time it will not be dependenton framework infrastructure like facade. Then, you will be able to code this command to look somethinglike following:

public class DeleteUserCommand extends SimpleCommand implements ICommand {

private var m_userProxy:IUserProxy; private var m_roleProxy:IRoleProxy;

public function set userProxy(p_userProxy:IUserProxy):void { m_userProxy = p_userProxy; }

public function set roleProxy(p_roleProxy:IRoleProxy):void { m_rolePrxy = p_roleProxy; }

override public function execute(notification:INotification):void { var user:UserVO = notification.getBody() as UserVO;

Page 119: Spring Action Script

Spring Actionscript extensions

113

userProxy.deleteItem(user); roleProxy.deleteItem(user); sendNotification(ApplicationFacade.USER_DELETED); }}

Now, the dependencies on concrete classes and framework infrastructure (i.e. facade) are gone from yourcode, and automatically it is much more maintainable, scalable and testable.

To my knowledge, to achieve something like this with PureMVC is not easy and will require very carefulrefactoring and recoding of the internal concrete PureMVC classes like Model, View and Controller (Ibelieve that the core PureMVC interfaces can be left intact). Probably, it is not bad to put high goals aslong they do not scare you, but to be on a safe route, we can try to achieve something much easier. Letme try to explain with an example.

In my first PureMVC experiment (which was really not so simple I must say), I have to code a proxy classwhich can load some remote data encoded in XML and convert it in an internal domain model which isusually termed as value objects in PureMVC. Actually domain model and value objects are not the same atall, but they do not differ in the context of this discussion. So, I didn't want to complicate my project witha server side, and I ended up with local XML files. I've also used the loading delegate pattern known fromCairngorm. A loading delegate handles all communications and conversion of encoded data in the domainmodel. At the end, I've implemented a method in a proxy class which looks something like following:

public function loadCandlestickCollection(p_stockSymbol:StockSymbol):void {

LOGGER.debug("Loading candlestick collection for stock symbol " + p_stockSymbol.symbol);

LOGGER.debug("Notifying observers with " + LoadDataNotification.NAME + "." + LoadDataNotification.TYPE_START); facade.notifyObservers(new LoadDataNotification(null, LoadDataNotification.TYPE_START));

var delegate:CandlestickLoadDelegate = new CandlestickLoadDelegate(this); delegate.load(p_stockSymbol);}

Here, CandlestickLoadDelegate is the concrete class which I don't like very much. I mean, I was justprototyping, and this local data loading delegate will be changed in the final version with its remotingequivalent. This will require either refactoring of the proxy method (and implementation of another loadingdelegate) or refactoring of the current concrete loading delegate. It will be much better to introduce anappropriate loading delegate interface. This can be done with any variation of the factory pattern, but thistypically only moves the concrete class dependency in the factory. It will be much better if I have somegeneral purpose factory (which can be configured, not coded) from which I can fetch the dependencies asneeded. Something like Spring, but in Flex/AS3 world. For the further reference I will name this type ofusage of an IoC container (which has the role of the general purpose configurable factory in this context)as the "ad hoc IoC container usage". It will be helpful if such ad hoc usage can be enabled in a consistentmanner, for example as a built-in feature of the extended PureMvc framework. I believe that this can bedone fairly easily if I have a good IoC container at disposal.

As it turns out, there is a good IoC container available in Flex world, it is called Spring Actionscript.There are also some others, but Spring Actionscript has several releases, decent documentation, and a verycompetent, friendly and collaborative lead developer. All in all I decided to try it in a general manner, andspecifically, to try to integrate it with PureMVC.

So, I decided to organize my PureMVC/Spring Actionscript integration endeavour in three steps in whichI will try to achieve different levels of integration, from easier to harder, of course. It is important toemphasize that I will try not to change the basic PureMVC programming model. I don't want to create

Page 120: Spring Action Script

Spring Actionscript extensions

114

a new MVC framework, I just want to integrate Spring Actionscript with PureMVC. That said, it is stillexpected that some minor changes in the common PureMVC usage patterns will be required.

In the first level of integration I will just try to bring Spring Actionscript in PureMVC as an additionalproperty of the PureMVC facade. That way a developer can use Spring Actionscript in the consistent ad hocmeaner when he needs it. Typically, the container will not contain any configurations of a PureMVC triad(proxy, mediator, command), but only their external dependencies (this should be easy enough, but younever know). Additionally, I expect that this level of integration will require minor changes in the typicalPureMVC application's startup procedure. This is caused with asynchronous nature of the container'sstartup while it reads configuration files.

If only that first integration level will be all that I can achieve, I will be satisfied enough because I believethat by them self it can significantly help in my future Flex projects.

In the second level of integration I plan to bring Spring Actionscript and PureMVC closer, with somefunctionality which will help to configure the PureMVC elements in Spring Actionscript. Since PureMVCmaintains its own object container (at least for proxies and mediators), at this moment I am planning totake into account only objects configured as prototypes (not singletons). While doing this, I'm hoping tolearn much more about repercussions that singletons will bring to table, since at least, I expect that somesynchronization between Spring Actionscript and PureMVC container will be needed. Hopefully, at thetime you will read this, both prototypes and singletons will be equally supported.

With only prototypes supported, Spring Actionscript will not have to manage the PureMVC elements, butrather it will only create them and hand them over to PureMVC. Naturally, this still will be the ad hocusage of the container and it can be programmed with only "Level 1 integration" available. However, Iplan to add some methods in the PureMVC facade which should be helpful in the process. Support forsingletons is left for the third level of integration, but it can happen sooner, you never know.

During second phase of integration I expect to learn a great deal about Spring Actionscript's andPureMVC's internal workings. I also expect that the "Level 2 integration" will be much harder to implementthan the level one. The typical PureMVC usage patterns will probably stay intact, they just can beimplemented through facade's methods with new names. The original PureMVC API will not change, soif you can't find any benefits in the "Level 2 integration", simply just don't use it.

So we came to the third level of integration. In this phase I plan to fully integrate PureMVC andSpring Actionscript in a way that should be hard to define borders between the Spring Actionscript'sand PureMVC's containers. All PureMVC elements should be freely configurable through SpringActionscript either as prototypes or singletons, depending on application's needs. Framework dependenciesin application should be minimal in a way that you no longer need to retrieve the PureMVC elementsfrom the PureMVC facade. The dependencies will be injected automatically. Of course, there still will beneed to interact with the facade during registration and notification processes. This kind of IoC usage isno longer the ad hoc usage. This is usage of the IoC container at its full potential. We will see if I'm ableto implement something like this. :-)

This whole endeavour is highly experimental, so I decided not to develop it in the typical framework style.This is left for later if and when this experiment can be considered as a success. Instead I will take thereferential PureMVC Arch101Demo sample, and start to modifying it.

Implementation notes and steps

Level 1 integration

• Creation of Spring Actionscript/PureMVC integration packages(org.springextensions.actionscript.puremvc) with subpackage structure corresponding to the internalPureMVC package structure.

Page 121: Spring Action Script

Spring Actionscript extensions

115

• Creation of the IocFacade class which, at the moment, have the same API as the original PureMVCfacade. IocFacade implements the IIocFacade interface which is extended from the original PureMVCIFacade interface. The IocFacade implementation mainly consists of a copied and refactored code fromthe PureMVC Facade class. At this point I didn't extend it because I expect that implementation ofIocFacade can be significantly changed in the future, possibly in a way where inheriting from originalFacade class could prevent adding some functionalities. Of course at this point I can't be sure at this,so it could be changed. Actually, if possible, inheriting original Facade call will be beneficial for manyreasons (less lines of code, improved maintainability, fewer bugs, easier update route etc.), so I willdefinitely look at it, but currently, I guess I will like as much freedom as possible. When reading this,one should check the source to see actual situation. However, no matter which implementation optionsis chosen, client API should stay the same, which means, actual implementation will not have influenceon applications which will try to use Spring Actionscript/PureMVC integration.

Currently, the most notable difference between APIs of original Facade and IocFacade is in constructorbecause IocFacade requires a string parameter for URL of an XML file with the Spring Actionscript(IoC) configuration.

• Consequently, the common startup PureMVC idiom is now changed a little. Instead of writing somethinglike this:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="onCreationComplete(event);"> <mx:Script> <![CDATA[ ... private var m_facade:ApplicationFacade = ApplicationFacade.getInstance(); ... private function onCreationComplete(p_event:Event):void { m_facade.startup(this); } ]]> </mx:Script> ...</mx:Application>

You are now required (because of an asynchronous configuration reading) to write something likefollowing:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="onCreationComplete()" > <mx:Script> <![CDATA[ ... private var m_facade:ApplicationFacade; ... private function onCreationComplete():void { m_facade = ApplicationFacade.getInstance("applicationContext.xml"); m_facade.addEventListener(ObjectDefinitionsLoaderEvent.COMPLETE, startupApp); }

private function startupApp(p_event:ObjectDefinitionsLoaderEvent):void { m_facade.removeEventListener(ObjectDefinitionsLoaderEvent.COMPLETE, startupApp); m_facade.notifyObservers(new Notification(ApplicationFacade.STARTUP, this)); } ]]> </mx:Script> ...

Page 122: Spring Action Script

Spring Actionscript extensions

116

</mx:Application>

• In IocFacade additional getter is added for accessing "container" property.

• Also, additional property "iocFacade" is added in IocProxy, IocMediator, IocSimpleCommandand IocMacroCommand. It enables easy access to the IoC facade (and to the IoC container throughit) from concrete implementation classes. Hopefully, all that will bring some consistency in the ad hocusage of the IoC container in PureMVC applications.

• Few IIoC* interfaces are added. In this phase they are merely a placeholders for the extended APImethods that should appear in the following integration phases.

• Concrete implementation classes IocProxy, IocMediator and Ioc*Command deliberately are notextended from the original PureMVC counterparts at this point, mainly for the same reasons as forIocFacade. Additional problem is in the PureMVC implementation of Notifier class which definesthe protected "facade" member and causes currently unnecessary instantiation of the original IFacadeinstance. Still, authentic contracts defined through PureMVC interfaces are left intact. If possible, atone point IocProxy, IocMediator and Ioc*Command will be extended from their original PureMVCcounterparts. If so, protected "facade" member will no longer be the problem.

• In Arch101Demo.mxml I added "linkageEnforcer" property to simplyfy linking of classes which arementioned only in IoC configuration. This linkage method should not be used for production purposes.It will be much preferable to add these classes to the compiled swf automatically, solely based on IoCconfiguration, without requiring any programming. Creating such a system is one of the pending taskswhich should make Spring Actionscript usage much more comfortable in general.

• To illustrate the "consistent ad hoc usage" of the Spring Actionscript container I've addedUserLoadDelegate class in "puremvcarch101Demo" application. UserLoadDelegate is used byUserProxy to load user data from local XML file. UserLoadDelegate is configured in IoC configurationand is used by proxy through IUserLoadDelegate interface.

Level 2 integration

• Before looking further at the integration, I will try to minimize dependencies on concrete classes in theArch101Demo sample.

• First on a list is the UserLoadDelegate class. Currently it has the "callback" dependency on theUserProxy concrete class. To avoid that, I've refactored UserLoadDelegate to use events. That changealone allows removal of the "userProxy" setter from the IUserLoadDelegate interface. Of course, nowis required that the UserProxy implements some event handling code but that is nothing new to Flexdevelopers. Further, I've also removed "serviceUrl" setter from the IUserLoadDelegate interface. It isnot required in application code and only Spring Actionscript needs it to inject dependency at runtime.But for Spring Actionscript's needs, that setter doesn't have to be declared in the interface. It is enoughjust to be implemented by concrete class which is configured through Spring Actionscript. In summary,above changes left us only with loadUsers() method in the IUserLoadDelegate interface. I've also addeda simulation of the slow data loading in the UserLoadDelegate class to make it somewhat more realistic.

• Next I've created IUserProxy and IRoleProxy interfaces which will be used through the rest of anapplication code instead of corresponding concrete classes. That also required refactoring of proxyname constants in the separate ProxyNames class (constants can not be defined in ActionScript 3interfaces). Now constants from this class will be used for proxy retrievals. The ProxyNames class, andits encapsulated name constants, should be now viewed as a part of public API in the same way as proxyinterfaces are. NAME constants are removed from concrete proxy classes because they are not reallyneeded as we will see.

• To support above refactorings, I've added the registerProxyByConfigName() method in the IIocFacadeinterface and the implementation in the IocFacade class. When you use this method, you must supply

Page 123: Spring Action Script

Spring Actionscript extensions

117

proxy name as the parameter. IocFacade will try to find configuration whose id is equal to that parameter.If it can't be found, an error will be thrown. On the other hand, if it can be found, IocFacade will retrieveit from container and will set its name to the value of supplied parameter (which in this case must be thesame as the value of id attribute in configuration). Of course, you will not use literals for that parameter,rather you will probably use constant defined in the public API as discussed before.

• Described usage of name constants is still a little bit too restrictive. Specifically, if you change theconfiguration id, you must also change the name constant value. This is not so good, I think. It will bebetter if there is no so tight coupling.

Now, what we can do? Well, we can try the old IT trick - introduction of another level of indirection. Forexample, we can introduce a names map whose keys will be equal to values of constants defined in code,and map values will be equal to ids. Then, you will be able to independently change configuration names(which can be pretty often) and constant values (which is not so often, or almost never). To support thisidiom, I've changed implementation of registerProxyByConfigName() method in following way:

• If object with id "proxyNamesMap" can be found in the IoC configuration ("proxyNamesMap" ismagic name as you can observe), IocFacade will try to map supplied parameter (configured as a mapkey) with mapped name (configured as a map value). If mapped name is found, then IoC facade willtry to retrieve configured proxy object whose configuration id attribute is equal to mapped value. Ifconfigured proxy can be retrieved it will be returned. Otherwise, error will be thrown.

• If there is no "proxyNamesMap" object in the configuration, or if supplied parameter value is not usedas a map key, IocFacade will try to find proxy object whose configuration id attribute value is equalto supplied parameter. If proxy can be found, it will be returned. Otherwise, error will be thrown.

• Corresponding retrieveProxyByConfigName() method is added in IIocFacade interface and inIocFacade class. For retrieval it uses equivalent algorithm to the one described above.

Please note that retrieveProxyByConfigName() and removeProxyByConfigName() methods can beremoved from IIocFacade later if IocFacade will be extended from original PureMVC Facade,and if their workflows can be combined with workflows of the original retrieveProxy() andremoveProxy() methods. Please take a look at source code to see what is actual situation atthe time when you are reading this. Described algorithm probably will not change, but it can becombined with original PureMVC implementations. If this happens, only requirement will be removalof "ByConfigName" suffix from these two methods. Name of method registerProxyByConfigName()probably will not change, since its signature is different from the signature of original PureMVC'sregisterProxy() method.

• Let see now what can be done with mediators. There are few roadblocks, but maybe we can do somethingabout them. In typical PureMVC applications mediators are not usually used as dependencies of otherPureMVC components. After registration, mediators only take notifications from other PureMVC parts.Also, in a constructor they usually take a parameter which references a visual component (in flexthis is usually some ancestor of the UIComponent class) which can't be configured through an IoCcontainer (at least I don't know how that can be easily done). Nevertheless, we can still benefit from IoC,since mediators usually have proxies as dependencies. To support that, there are at least three thingsrequired: support for singletons in PureMVC/Spring Actionscript integration, IoC support for supplyingconstructor parameters at runtime (which requires additional IoC feature - the lazy initialization), andIoC support for custom initialization methods.

Speaking about singletons, they are required if you start to mix PureMVC element configurations. Forexample, imagine that we have something like this in a configuration:

<object id="userProxyObject" class="... .UserProxy" scope="prototype"/>

Page 124: Spring Action Script

Spring Actionscript extensions

118

<object id="userListMediatorObject" class="...UserListMediator" scope="prototype"> <property name="userProxy" ref="userProxyObject"/></object>

Now, if you use the IocFacade to retrieve "userProxyObject" and "userListMediatorObject", then"userProxyObject" instance and "userListMediatorObject"'s dependency "userProxy" will be twodifferent instances! This is because every time the IoC container fetches a prototype it always createsa new instance which usually is not what you want. At this point in PureMVC/Spring Actionscriptdevelopment, you can actually use singletons.

Why are dynamic constructor parameters important? Well, as I already said, mediators usually havevisual components as constructor parameters. As visual dependencies can't be configured through SpringActionscript, you have to have a way for supplying them at runtime. Since mediators, as they are usuallyimplemented in typical PureMVC applications, can't be instantiated until the moment when you fetchthem through the IocFacade, the IoC container must support lazy initialization of objects. This meansthat objects marked as lazy will not be instantiated at the container startup, their instantiation will bepostponed until you fetch them from the IoC container for the first time. At that moment you could havean opportunity (if one exists) to supply constructor parameters.

And finally, what about that custom initialization method? Typical PureMVC usage pattern is toinstantiate and use proxy dependencies in the mediator's constructor. If you decide to configure thoseproxy dependencies via IoC (like in above configuration code snippet) you will end up with nullreferences since the IoC container can not inject dependencies before mediator is constructed. Soyou will need to refactor dependencies usage in the separate custom initialization method whichshould be invoked by IoC container after the mediator was constructed and all its dependencies wereinjected. Actually, Spring Actionscript already supports such method by IInitializingObject interface,but implementing it will unnecessarily add dependency on the Spring Actionscript framework in yourcode. It will be much better if you can express in configuration which one of your methods is theinitializing one.

• Lazy initialization is supported with "lazy-init" configuration attribute like in following example:

<object id="userListMediatorObject" class="... .UserListMediator" lazy-init="true"/>

Custom initialization method is supported with "init-method" configuration attribute like in:

<object id="userListMediatorObject" class="... .UserListMediator" lazy-init="true" init-method="initMethod">

Dynamic constructor parameters are supported with "p_viewComponent" parameter in IocFacaderegisterMediatorByConfigName() method which has following signature:

function registerMediatorByConfigName(p_mediatorName:String, p_viewComponent:Object = null):void;

Other IocFacade's features related to mediators mainly have same characteristics as those forproxies. There only should be noted that magic name for configurable mediator names map is"mediatorNameMap".

• It should be noted that you don't have to use "lazy-init" and "init-method" features for configuringMediators. This is because in PureMVC v2.x, setViewComponent() is added, and now is not requiredthat you have to supply a view component at construction time. It can be added later. On the other hand,taking this approach will require some minor changes in implementation of mediators, and its usage inthe context of IoC configured applications.

First, if you want some mediator to be constructed at IoC container startup, its constructor must not bedependent on a view component. You should factor out that initialization code in some other method,like in following example:

Page 125: Spring Action Script

Spring Actionscript extensions

119

public class MyMediator extends IocMediator { public function UserFormMediator(p_mediatorName:String = null, p_viewComponent:Object = null) { super(p_mediatorName, p_viewComponent);

// This code must be factored out in self standing method. // myViewComponent.addEventListener(MyViewComponent.EVENT_ONE, onEventOne); // myViewComponent.addEventListener(MyViewComponent.EVENT_TWO, onEventTwo); // myViewComponent.addEventListener(MyViewComponent.EVENT_THREE, onEventThree); }

public function init():void { myViewComponent.addEventListener(MyViewComponent.EVENT_ONE, onEventOne); myViewComponent.addEventListener(MyViewComponent.EVENT_TWO, onEventTwo); myViewComponent.addEventListener(MyViewComponent.EVENT_THREE, onEventThree); }

...}

Now we have init() method which, when invoked, executes initialization code, previously belonging tothe constructor. Only one question remains, when this init() method will be invoked? Well, you haveat least two options. First one is to execute it manually when appropriate, and second one is to executeit from overridden setViewComponent() method.

If you chose first option you will end up with one more statement during mediator's registration:

public class MyStartupCommand extends IocSimpleCommand { // ... // setters and getters omitted. // ...

override public function execute(p_note:INotification):void { var app:MyApp = p_note.getBody() as MyApp; // ...

myMediator.setViewComponent(app.myViewComponent); myMediator.init(); iocFacade.registerMediatorByConfigName("myMediatorName");

// ... }}

If you opt for second option, you will end up adding something like the following in your mediator class:

override public function setViewComponent(p_viewComponent:Object):void { if (getViewComponent() != null) { myViewComponent.removeEventListener(MyViewComponent.EVENT_ONE, onEventOne); myViewComponent.removeEventListener(MyViewComponent.EVENT_TWO, onEventTwo); myViewComponent.removeEventListener(MyViewComponent.EVENT_THREE, onEventThree); }

Page 126: Spring Action Script

Spring Actionscript extensions

120

super.setViewComponent(p_viewComponent);

init();}

This actually makes sense, since you will typically have to do some preparations every time you changea view component that mediator mediates.

It should also be noted that whatever approach you choose, it is still compatible with "pure" PureMVCapplications. This means that you can use without problems described usage patterns in all PureMVCapplications. As a side effect, your mediators should be now easier to test because constructor doesn'tuse view component any more. In your tests you can add this dependency (probably mocked) throughsetViewComponent() only when needed.

• All mentioned things you can see in action in modified Arch101Demo sample.

• Although I said before that support for singletons will be added in third level of integration, I've decidedto add it right now, so that mediator's story can be completed. So, I've added two additional methodsin IocFacade:

function removeProxyByConfigName(p_proxyName:String):void;function removeMediatorByConfigName(p_mediatorName:String):void;

These allow you to remove cached singleton instances from IoC container. That also required changesin Spring Actionscript implementation, but not very visible one. If you are interested, I've addedclearObjectFromInternalCache() method in AbstractObjectFactory class.

Here same notes about "ByConfigName" suffix in method names apply as before. If they do not existin IIocFacade at the time you are reading this, this only means that you should use standard PureMVCmethod names: removeProxy() and removeMediator(). They will function as described here, but youwill not have to worry about that.

Level 3 integration

• As mentioned before, the theme of Level 3 PureMVC/Spring Actionscript integration is support forPureMVC commands. As it turns out this was very straightforward to implement. But first, let explorea little how commands are used in typical PureMVC applications.

• Contrary to mediators and proxies, commands are not instantiated by the developer, but rather by theframework. You just have to pass a class reference to PureMVC and it will create a command instancewhen appropriate. PureMVC documentation suggests that commands are created, executed and thendestroyed, meaning that the framework doesn't preserve any references to them after its execution.I believe that such usage is good practice when you don't have the IoC container at hand. Further,commands are not used as dependencies of other PureMVC elements, but they usually reference proxiesand sometimes (usually only in a startup command) mediators.

• Now, what can you do with the IoC container? First, if you configure a command as a singleton, theframework will not have to instantiate them on every execution. Instead, commands can be easily fetchedfrom the container when needed which can save some time and memory (not really a big issue butstill...). Further, with IoC you can configure dependencies of your commands which will be injectedwhen the IoC container instantiates them and this is the main point. Additionally, your application'sfacade will not have to reference a concrete command classes during command registration. Instead itcan use command's configuration name which is a plain string (usually coded as constant). That way yourcommands don't need to be dependent on your concrete proxy or mediator classes and your applicationdoesn't need anymore be dependant on the concrete command classes. This is all wired together by theIoC container.

Page 127: Spring Action Script

Spring Actionscript extensions

121

• To support described usage I had to replace original PureMVC implementation of IController interface.This part is not visible to the end programmer. More importantly, the IocFacade got the newregisterCommandByConfigName() method with which you can associate a configuration name used inthe IoC container with a PureMVC notification.

I've also implemented a "magic" command names map with which you can introduce additionalindirection between command configuration names used in code and in IoC configuration. If you decideto configure it, command names map must have id attribute with value "commandNamesMap". If youdecide at some point that some command is not needed any more you can unregister it as usual by usingthe IocFacade's removeCommand() method.

• For working examples of a command usage in combination with the IoC container you should lookat IoC configuration for "commandNamesMap", "startupCommandObject" and "deleteUserCommand"objects. You should also look at a command registration in the ApplicationFacade class and finally howthe userProxy dependency is now implemented in the DeleteUserCommand class. I hope this will beenough for you to understand how to use PureMVC/Spring Actionscript integration with PureMVCcommands.

• At the end I want to emphasize the fact that you don't have to use full "Level 2 & 3" integration. Ifyou find more appropriate, you can just use "consistent ad hoc IoC usage" from "Level 1" integration.I believe only that part can bring significant benefits to typical PureMVC applications. Despite, youshould give a chance to Level 2 and 3 parts. Try it and decide if this brings any benefit to you.

Page 128: Spring Action Script

Part III. Appendixes

Page 129: Spring Action Script

123

Appendix A. XML Schema-basedconfiguration

IntroductionThis appendix details the XML Schema-based configuration introduced in Spring Actionscript version 0.8.

The central motivation for using XML Schema based configuration files was to make Spring XMLconfiguration easier. The 'classic' -based approach is good, but its generic-nature comes with a price interms of configuration overhead.

From the Spring Actionscript IoC containers point-of-view, everything is an object. That's great news forthe Spring Actionscript IoC container, because if everything is an object then everything can be treatedin the exact same fashion. The same, however, is not true from a developer's point-of-view. The objectsdefined in a Spring Actionscript XML configuration file are not all generic, vanilla objects. Usually, eachobject requires some degree of specific configuration.

Spring Actionscript XML Schema-based configuration addresses this issue. The element is still present,and if you wanted to, you could continue to write the exact same style of Spring Actionscript XMLconfiguration using only elements. The XML Schema-based configuration does, however, make SpringActionscript XML configuration files substantially clearer to read. In addition, it allows you to expressthe intent of an object definition.

The key thing to remember is that the new custom tags work best for infrastructure or integration objects:for example, collections, transactions, integration with 3rd-party frameworks, while the existing objecttags are best suited to application-specific objects, such as DAOs, service layer objects, validators, etc.The examples included below will hopefully convince you that XML Schema support is a good idea.Please note the fact that this configuration mechanism is totally customisable and extensible. This meansyou can write your own domain-specific configuration tags that would better represent your application'sdomain; the process involved in doing so is covered in the appendix entitled Appendix B, Extensible XMLauthoring.

XML Schema-based configuration

Referencing the schemas

To use the XML Schema-style, you need to add the following declarations to your XML file.

<?xml version="1.0" encoding="UTF-8"><objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd">

<!-- <object/> definitions here -->

</objects>

Page 130: Spring Action Script

XML Schema-based configuration

124

Note

The 'xsi:schemaLocation' fragment is not actually required, but can be included to reference alocal copy of a schema (which can be useful during development).

The above Spring Actionscript XML configuration fragment is boilerplate that you can copy and paste(!) and then plug definitions into like you have always done. The section entitled, "The util schema"demonstrates how you can start immediately by using some of the more common utility tags. The rest ofthis chapter is devoted to showing examples of the Spring Actionscript XML Schema based configuration,with at least one example for every new tag. The format follows a before and after style, with a beforesnippet of XML showing the old (but still 100% legal and supported) style, followed immediately by anafter example showing the equivalent in the new XML Schema-based style.

The util schemaFirst up is coverage of the util tags. As the name implies, the util tags deal with common, utilityconfiguration issues, such as configuring collections, referencing constants, and suchlike.

To use the tags in the util schema, you need to have the following preamble at the top of your SpringActionscript XML configuration file; the emboldened text in the snippet below references the correctschema so that the tags in the util namespace are available to you.

<?xml version="1.0" encoding="UTF-8"?><objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springactionscript.org/schema/util" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/objects/spring-actionscript-util-1.0.xsd">

<!-- <object/> definitions here -->

</objects>

You also need to register the namespace handler with the application context, like this (invoke this methodbefore you load the configuration):

applicationContext.addNamespaceHandler(new UtilNamespaceHandler());

Not all util functions have been implemented yet in Spring Actionscript, the ones that are already presentare described below.

<util:constant/>Before...

<object id="..." class="..."> <property name="version"> <object class="org.springextensions.actionscript.ioc.factory.config.FieldRetrievingFactoryObject"> <property name="targetClass" value="mx.core.FlexVersion"/> <property name="staticField" value="CURRENT_VERSION"/> </object>

Page 131: Spring Action Script

XML Schema-based configuration

125

</property></object>

The above configuration uses a Spring Actionscript IFactoryObject implementation, theFieldRetrievingFactoryObject, to set the value of the 'test' property on an object to the value of the'mx.core.FlexVersion.CURRENT_VERSION' constant. This is all well and good, but it is a tad verboseand (unnecessarily) exposes Spring Actionscript's internal plumbing to the end user.

The following XML Schema-based version is more concise and clearly expresses the developer's intent('inject this constant value'), and it just reads better.

<object id="..." class="..."> <property name="test"> <util:constant static-field="mx.core.FlexVersion.CURRENT_VERSION"/> </property></object>

<util:invoke/>Before...

<object class="org.springextensions.actionscript.ioc.factory.config.MethodInvokingFactoryObject"> <property name="targetClass" value="mx.resources.ResourceManager"/> <property name="targetMethod" value="getInstance"/></object>

After...

<util:invoke target-class="mx.resources.ResourceManager" target-method="getInstance" id="resourceManager"/>

To pass arguments to the specified method use <arg/> child elements:

<util:invoke target-object="resourceManager" target-method="getString"> <arg value="bundleName"/> <arg value="resourceName"/></util:invoke>

The messaging schemaThe messaging schema, to no great surprise, covers all objects that deals with messaging, such as channels,producers, consumers, etc.

To use the tags in the messaging schema, you need to have the following preamble at the top of your SpringActionscript XML configuration file; the emboldened text in the snippet below references the correctschema so that the tags in the messaging namespace are available to you.

<?xml version="1.0" encoding="UTF-8"><objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:messaging="http://www.springactionscript.org/schema/messaging" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/objects/spring-actionscript-messaging-1.0.xsd">

Page 132: Spring Action Script

XML Schema-based configuration

126

<!-- <object/> definitions here -->

</objects>

You also need to register the namespace handler with the application context, like this (invoke this methodbefore you load the configuration):

applicationContext.addNamespaceHandler(new MessagingNamespaceHandler());

In the following section we will briefly show you what new tags the messaging schema will offer you.

<messaging:channel-set>To declare a channelset using the messaging schema, add this markup to you XML configuration:

<channel-set clustered="false" initial-destination-id="remote-destination" id="myChannelSet">

"remote-destination" is just a generic name in this example, you will need to change this to a destinationid that is suitable for your server environment.

<messaging:channel>Now to add a channel to our previously declared channelset, you can add the following:

<channel id="myChannel" connect-timeout="50" failover-uris="http://myfailoverserver.com/flex,http://localhost/flex" request-timeout="200" uri="http://myserver.com/flex"/>

Then, to add the channel to the channelset, add this attribute to your channelset declaration:

<channel-set clustered="false" initial-destination-id="remote-destination" id="myChannelSet" channels="myChannel"/>

To add more than one channel, just comma delimit the channel names:

<channel-set clustered="false" initial-destination-id="remote-destination" id="myChannelSet" channels="myChannel,myOtherChannel"/>

<messaging:amf-channel>

The amf-channel tag merely adds a few attributes to the regular channel tag that apply to AMF specifically:

<amf-channel id="myChannel" connect-timeout="50" failover-uris="http://myfailoverserver.com/flex,http://localhost/flex" request-timeout="200" uri="http://myserver.com/flex" piggybacking-enabled="false" polling-enabled="true" polling-interval="200"/>

Other than that there is also the <secure-amf-channel/>, <streaming-amf-channel/> and the <secure-streaming-amf-channel/>, who map to the SecureAMFChannel,StreamingAMFChannel and SecureStreamingAMFChannel respectively but who offer no extraattributes as of yet.

<messaging:abstract-consumer>Coming soon...

Page 133: Spring Action Script

XML Schema-based configuration

127

<messaging:consumer>

Coming soon...

<messaging:multi-topic-consumer>

Coming soon...

<messaging:producer>Coming soon...

<messaging:multi-topic-producer>

Coming soon...

The RPC schemaComing soon...

The stage processing schemaThe stage processing schema offers markup directly geared towards the GenericStageProcessor class.

To use the tags in the stage processing schema, you need to have the following preamble at the top ofyour Spring Actionscript XML configuration file; the emboldened text in the snippet below references thecorrect schema so that the tags in the stage processing namespace are available to you.

<?xml version="1.0" encoding="UTF-8"><objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:si="http://www.springactionscript.org/schema/stageprocessing " xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd http://www.springactionscript.org/schema/objects/spring-actionscript-stageprocessing-1.0.xsd">

<!-- <object/> definitions here -->

</objects>

You also need to register the namespace handler with the application context, like this (invoke this methodbefore you load the configuration):

applicationContext.addNamespaceHandler(new StageProcessorNamespaceHandler());

In the following section we will briefly show you what new tags the stage processing schema will offer you.

<si:genericstageprocessor>Currently there is just one tag in the stage processing namespace, to add a GenericStageProcessor to yourapplication simply use this markup:

Page 134: Spring Action Script

XML Schema-based configuration

128

<si:genericstageprocessor target-object="stageRegistry" target-method="register" object-selector="registrySelector" id="genericStageProcessor"/>

Where the target-object and object-selector attributes are references to existing objects in your applicationcontext.

Page 135: Spring Action Script

129

Appendix B. Extensible XML authoringIntroduction

This section is devoted to detailing how you would go about writing your own custom XML objectdefinition parsers and integrating such parsers into the Spring Actionscript IoC container.

To facilitate the authoring of configuration files using a schema-aware XML editor, Spring Actionscript'sextensible XML configuration mechanism is based on XML Schema. If you are not familiar with SpringActionscript's current XML configuration extensions that come with the standard Spring Actionscriptdistribution, please first read the appendix entitled "Appendix A, XML Schema-based configuration."

Creating new XML configuration extensions can be done by following these (relatively) simple steps:

• Authoring an XML schema to describe your custom element(s).

• Coding a custom INamespaceHandler implementation (this is an easy step, don't worry).

• Coding one or more IObjectDefinitionParser implementations (this is where the real work is done).

• Registering the above artifacts with Spring Actionscript (this too is an easy step).

What follows is a description of each of these steps. For the example, we will create an XML extension(a custom XML element) that allows us to configure objects of the type DateFormatter (from the Flexmx.formatters.DateFormatter package) in an easy manner. When we are done, we will be able to defineobject definitions of type DateFormatter like this:

<mydatens:ddateformatter id="dateFormat" format-string="MM/DD/YYYY"/>

(Don't worry about the fact that this example is very simple; much more detailed examples followafterwards. The intent in this first simple example is to walk you through the basic steps involved.)

Authoring the schemaCreating an XML configuration extension for use with Spring Actionscript's IoC container starts withauthoring an XML Schema to describe the extension. What follows is the schema we'll use to configureDate objects.

<xsd:schema xmlns="http://www.springactionscript.org/schema/mydatens" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.springactionscript.org/schema/mydatens" elementFormDefault="qualified">

<xsd:import namespace="http://www.springactionscript.org/schema/objects"/> <xsd:element name="dateformatter"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="objects:objectType"> <xsd:attribute name="format-string" type="xsd:string" use="required"/> </xsd:extension>

Page 136: Spring Action Script

Extensible XML authoring

130

</xsd:complexContent> </xsd:complexType> </xsd:element>

</xsd:schema>

(The emphasized line contains an extension base for all tags that will are an object (meaning they have an idattribute, class attribute, etc). We are able to use this attribute because we imported the Spring Actionscript-provided 'objects' namespace.)

The above schema will be used to configure Date objects, directly in an XML application context fileusing the <mydatens:dateformatter/> element.

<mydatens:dateformatter id="dateFormatter" format-string="MM/DD/YYYY"/>

Note that after we've created the infrastructure classes, the above snippet of XML will essentially be exactlythe same as the following XML snippet. In other words, we're just creating an object in the container,identified by the name 'dateFormat' of type DateFormatter, with a couple of properties set.

<object id="dateFormatter" class="mx.formatters.DateFormatter"> <property name="formatString" value="MM/DD/YYYY"/></object>

Note

The schema-based approach to creating configuration format allows for tight integration withan IDE that has a schema-aware XML editor. Using a properly authored schema, you can useauto completion to have a user choose between several configuration options defined in theenumeration.

Coding an INamespaceHandler implementationIn addition to the schema, we need an INamespaceHandler that will parse all elements of this specificnamespace Spring Actionscript encounters while parsing configuration files. The INamespaceHandlershould in our case take care of the parsing of the mydatens:dateformatter element.

The INamespaceHandler interface is pretty simple in that it features just two methods:

public interface INamespaceHandler {

/** * Return the namespace supported by this namespace handler. */ function getNamespace():Namespace;

/** * Parses the given node and returns the resulting object definition. * * @param node the xml node to parse * @param context the root xml parser */ function parse(node:XML, context:XMLObjectDefinitionsParser):IObjectDefinition;

Page 137: Spring Action Script

Extensible XML authoring

131

}

Although it is perfectly possible to code your own INamespaceHandler for the entire namespace (andhence provide code that parses each and every element in the namespace), it is often the case that each top-level XML element in a Spring Actionscript XML configuration file results in a single object definition(as in our case, where a single <mydatens:dateformatter/> element results in a single DateFormatter objectdefinition). Spring Actionscript features a number of convenience classes that support this scenario. In thisexample, we'll make use of the NamespaceHandlerSupport class:

package org.springextensions.actionscript.ioc.factory.xml {

public class MyNamespaceHandler extends NamespaceHandlerSupport {

public function MyNamespaceHandler() { super(new Namespace("http://www.springactionscript.org/schema/mydatens"));

registerObjectDefinitionParser("dateformatter", new DateFormatterNodeParser()); }

}}

The observant reader will notice that there isn't actually a whole lot of parsing logic in this class.Indeed... the NamespaceHandlerSupport class has a built in notion of delegation. It supports the registrationof any number of IObjectDefinitionParser instances, to which it will delegate to when it needs toparse an element in it's namespace. This clean separation of concerns allows an INamespaceHandlerto handle the orchestration of the parsing of all of the custom elements in it's namespace, whiledelegating to IObjectDefinitionParsers to do the grunt work of the XML parsing; this means that eachIObjectDefinitionParser will contain just the logic for parsing a single custom element, as we can see inthe next step.

Coding an IObjectDefinitionParserimplementation

An IObjectDefinitionParser will be used if the INamespaceHandler encounters an XML element of thetype that has been mapped to the specific object definition parser (which is 'dateformatter' in this case).In other words, the IObjectDefinitionParser is responsible for parsing one distinct top-level XML elementdefined in the schema. In the parser, we'll have access to the XML element (and thus it's sub elements too)so that we can parse our custom XML content, as can be seen in the following example:

package org.springextensions.actionscript.ioc.factory.xml { import mx.formatters.DateFormatter;

import org.springextensions.actionscript.ioc.IObjectDefinition; import org.springextensions.actionscript.ioc.factory.support.ObjectDefinitionBuilder; import org.springextensions.actionscript.ioc.factory.xml.parser.support.ParsingUtils; import org.springextensions.actionscript.ioc.factory.xml.parser.support.XMLObjectDefinitionsParser;

public class DateFormatterNodeParser extends AbstractObjectDefinitionParser {

public function DateFormatterNodeParser() { super(); }

Page 138: Spring Action Script

Extensible XML authoring

132

override protected function parseInternal(node:XML, context:XMLObjectDefinitionsParser):IObjectDefinition { var result:ObjectDefinitionBuilder = ObjectDefinitionBuilder.objectDefinitionForClass(DateFormatter);

ParsingUtils.mapProperties(result.objectDefinition, node, "format-string");

return result.objectDefinition;

}

}}

1. We use the SpringActionscript-provided AbstractObjectDefinitionParser to handle a lot of the basicgrunt work of creating a single IObjectDefinition.

2. We supply the AbstractObjectDefinitionParser superclass with the type that our singleIObjectDefinition will represent.

3. We use the SpringActionscript-provided ParsingUtils to automatically map XML attributes to objectproperties.

In this simple case, this is all that we need to do. The creation of our single IObjectDefinition is handledby the AbstractObjectDefinitionParser superclass, as is the extraction and setting of the object definition'sunique identifier.

Registering the handlerThe coding is finished! All that remains to be done is to somehow make the Spring Actionscript XMLparsing infrastructure aware of our custom element. For this particular task you can simply call theaddNamespaceHandler() method on the application context instance, passing it an instance of your newlycreated INamespaceHandler.

applicationContext.addNamespaceHandler(new MyNamespaceHandler());

And that's it, if you make sure you've declared your own namespace properly in the XML configuration,from now on the Spring Actionscript container will be able to parse and create your object definitions.

Note

Obviously you must invoke the addNameSpaceHandler() method before you invoke the load()method.

Code generatorSpring Actionscript offers a small AIR application (whose source can also be found in the 'samples'section of the SVN repository). This application can load and analyze a .swc file, extract classinformation and based on this generate a namespace, a NamespaceHandlerSupport subclass, a list ofIObjectDefinitionsParsers and a schema file.

Obviously this code generator will not be suitable for more complex implementations, but it can at leastprovide you with some boiler plate code and give you a better insight in the workings and dependenciesof the different classes.

Page 139: Spring Action Script

Extensible XML authoring

133

You can download the AIR installer by .

Page 140: Spring Action Script

134

Appendix C. Forcing Actionscript classinclusionIntroduction

Once you move the configuration of your objects out of your source code you will notice a very commonproblem. Because there is not always a direct reference to certain classes inside your source code theseclasses will not end up being compiled into the resulting .swf file. Then, while running your application,you will encounter the dreaded "Error: A class with the name 'XXXXX' could not be found." message.

There is a variety of ways to force the compiler to include certain classes, in this section we will look atmost of them.

Adding an anonymous code blockPlace this anywhere in your code, at the top of your application source for instance:

{ Myclass1, Myclass2}

Declaring a list of variablesAnother way is to just declare a whole list of dummy variables with the required types:

private var _dummy1:Myclass1;private var _dummy2:Myclass2;

or just one array of class declarations:

private var _includeClass:Array = [Myclass1,Myclass2];

Using the Frame metadataThere is an undocumented piece of metadata that will force the compiler to include a second or third classto an existing class source.

package com.myclasses{ [Frame(extraClass="com.myclasses.Myclass1")] [Frame(extraClass="com.myclasses.Myclass2")] public class MyMainClass { }}

After that you only need to declare one variable of type MyMainClass in your source code.

Using a resource bundleIts possible to create a .properties file that contains all the class references you. Create a file in your projectcalled classreferences.properties and add your classes like this:

Page 141: Spring Action Script

Forcing Actionscript class inclusion

135

Class1 = ClassReference("com.myclasses.Myclass1")Class2 = ClassReference("com.myclasses.Myclass2")

Then in your application source code add a reference to the resource like this:

[ResourceBundle("classreferences")]private var _classReferences:ResourceBundle;

Using an ANT task as a prebuilder to generate acompiler config file

The last solution is a little more involved but can eventually automate the whole task of class inclusion, inthis section we will explain step-by-step how to configure Flexbuilder to run a prebuilder.

Step 1 - Add a compiler switch to your project

Right click on your project in Eclipse/Flexbuilder and choose the menu item 'Properties', in the followingpopup add the compiler switch like this:

Step 2 – Create an XSLT ANT Task

Step 2 – Create an XSLT ANT Task In your project root (NOT your 'src' directory) create an XML file,call it 'springasprebuild.xml' (the same filename you used in the compiler switch), and in this file add thefollowing code:

<!--======================================================================Nov 17, 2008 4:33:15 PMproject SpringAS Pre builddescription Extracts all the class paths from a Spring Actionscriptconfiguration file and dumps them intoa config file that can be added with a compilerswitch (i.e. -load-config+=custom.config)Roland Zwaga====================================================================== --><project name="project" default="default"><description>Extracts all the class paths from a Spring Actionscript configuration file anddumps them in a config file that can be added with a compiler switch(i.e. -load-config+=custom.config)</description><!--=================================target: default=================================--><target name="default" description="description"><xslt in="src/application-context.xml" out="src/springas.config"style="xslt/springasconfig.xsl" reloadstylesheet="false"></xslt></target></project>

Page 142: Spring Action Script

Forcing Actionscript class inclusion

136

Take notice of XSLT element in the code, it has4 attributes:

• in – this is the path to your Spring Actionscript configuration file

• out – this is the path to the output file for the XSLT task, this is the file that was added as a compilerswitch in the previous step.

• style – This is the actual stylesheet that contains the necessary code to generate the output.

• reloadstylesheet – only set this to true when you have made changes to the XSLT, otherwise leave itset to false.

Step 3 – Add the XSLT to your project

Create a new directory in your project root and call it 'xslt', create a new file in this directory called'springasconfig.xsl'. Add the following code to the file:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:springas="http://www.springactionscript.org/schema/objects"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd "exclude-result-prefixes="xsi springas"> <xsl:output method="xml" indent="yes"/> <xsl:key name="restriction" match="//springas:object" use="@class" /> <xsl:key name="proprestriction" match="//springas:property" use="@value" /> <xsl:key name="valrestriction" match="//springas:value" use="." /> <xsl:template match="/"> <flex-config> <includes append="true"> <xsl:for-each select="//springas:object[count(.|key('restriction',@class)[1]) = 1]"> <xsl:sort select="@class"/> <xsl:if test="@class!=''"> <symbol> <xsl:value-of select="@class"/> </symbol> </xsl:if> </xsl:for-each> <xsl:for-each select="//springas:property[count(.|key('proprestriction',@value)[1]) = 1]"> <xsl:sort select="@value"/> <xsl:if test="@type='Class'"> <symbol> <xsl:value-of select="@value"/> </symbol> </xsl:if> </xsl:for-each> <xsl:for-each select="//springas:value[count(.|key('valrestriction',.)[1]) = 1]"> <xsl:sort select="."/> <xsl:if test="@type='Class'">

Page 143: Spring Action Script

Forcing Actionscript class inclusion

137

<symbol> <xsl:value-of select="."/> </symbol> </xsl:if> </xsl:for-each> </includes> </flex-config> </xsl:template></xsl:stylesheet>

Step 4 – Add the ANT task as a builder

In the last step you add the ANT task as a builder to your project, do this by right clicking on your project,Choose 'Properties' and select the tab called 'Builders':

Click on 'New' and choose 'ANT Builder' and click 'OK', this dialog should appear:

Give the builder a logical name, something like 'Spring AS Prebuilder', afterwards click 'Browseworkspace' beneath the 'Buildfile' input field, in the following dialog choose the Buildfile from the root ofyour current project. In case of this example its called 'springasprebuild.xml':

Then click 'OK' to return to the builder list. The builder you just added is in the wrong order still though.We want it to be the first builder to be executed in the build process, so select the ‘Spring AS Prebuilder’in the list and click on 'Up', after this the list will look like this:

Click 'OK' and your project is configured!. To test whether everything is in working order, build yourproject. If all went according to plan then in the root of your source folder a new file has been createdcalled 'springas.config'. The contents of this file will look something like this:

<?xml version="1.0" encoding="UTF-8"?><flex-config> <includes append="true"> <symbol>mx.messaging.channels.AMFChannel</symbol> <symbol>mx.messaging.ChannelSet</symbol> <symbol>mx.rpc.remoting.mxml.RemoteObject</symbol> </includes></flex-config>

And that's it, once in place this will take care of filtering out the classes from your Spring Actionscriptconfiguration file.

Well, at least in most cases :)

Using MavenIf you use Maven as a build system for your application, Spring Actionscript also offers a mojo that willgenerate a flex compiler config file based on an application context. You can download the mojo .

Page 144: Spring Action Script

Forcing Actionscript class inclusion

138

Download the zip file and open the directory it is contained in and run "mvn install" on the mojo to getit into your local repository.

Then use it your build like this:

...<!-- set up properties to make it easy for both plugins (the prebuild and the maven-mojo) to use the same file locations --> <properties> <generatedCompilerConfigName>spring-as-includes.config</generatedCompilerConfigName> <generatedCompilerConfigDir>${project.build.sourceDirectory}</generatedCompilerConfigDir> </properties> <build> ... <plugins> <plugin> <groupId>org.springextensions.actionscript</groupId> <artifactId>prebuild-mojo</artifactId> <version>0.1-SNAPSHOT</version> <executions> <execution> <phase>generate-resources</phase> <goals> <goal>generate-compiler-config</goal> </goals> </execution> </executions> <configuration> <springActionscriptContextFiles> <param>${basedir}/src/main/flex/YOUR-CONTEXT-FILE.xml</param> </springActionscriptContextFiles> <outputDirectory>${generatedCompilerConfigDir}</outputDirectory> <generatedConfigFileName>${generatedCompilerConfigName}</generatedConfigFileName> </configuration> </plugin> <plugin> <groupId>org.sonatype.flexmojos</groupId> <artifactId>flexmojos-maven-plugin</artifactId> <version>3.6-SNAPSHOT</version> <configuration> ... <configFiles> <file>${generatedCompilerConfigDir}/${generatedCompilerConfigName}</file> </configFiles> ... </configuration>

</plugin> </plugins> </build>...

And that's all there is to it!

Page 145: Spring Action Script

Part IV. Reference

Page 146: Spring Action Script

140

Chapter 9. Configuration referenceThis section has been generated from the schema file 'spring-actionscript-objects-1.0.xsd'

General description<literallayout> Spring ActionScript Framework 1.0 Schema Schema Authors: Ryan Gardner,Erik Westra, Christophe Herreman, Roland Zwaga This defines a simple and consistent wayof creating a namespace of ActionScript objects, managed by a Spring ActionScript IoCContainer, read by XmlObjectDefinitionParser. Every attempt has been made to make this schemecomprehensive and correct. Configuring your XML context-configuration like this: <?xml version="1.0"encoding="UTF-8" standalone="no"?> <objects xmlns="http://www.springactionscript.org/schema/objects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springactionscript.org/schema/objects http://www.springactionscript.org/schema/objects/spring-actionscript-objects-1.0.xsd"> <!-- object and template definitions --> </objects> Will enable mostschema-aware tools to automatically retrieve the schema and provide on-the-fly validation and code-completion as you create your context definition. The main goal of this schema is to provide easy assistancein creating the file, and basic validation of the syntax. Please feel free to provide updates to the SpringActionScript team if you see any areas to improve. </literallayout>

Overview

• arg

• array

• array-collection

• constructor-arg

• dictionary

• entry

• import

• interface

• key

• method-invocation

• object

• objects

• param

• property

• property

Page 147: Spring Action Script

Configuration reference

141

• ref

• template

• value

• vector

<section><title><programlisting><arg/></programlisting></title><literallayout>Defines a method argument.</literallayout><itemizedlist><title>Attributes</title><listitem>value<remark><literallayout>A literal value for the argument.</literallayout></remark></listitem><listitem>ref<remark><literallayout>A reference to another object defined in the container.</literallayout></remark></listitem><listitem>template<remark><literallayout>The name of a template which should be used as the value of the specified argument. Whendefined as an attribute no parameters can be passed to the template, so no placeholder substitution willoccur. Use a child template element instead if parameters are needed.</literallayout></remark></listitem></itemizedlist></section><section><title><programlisting><array/></programlisting></title><literallayout>The array contains a list of the following possible values, these types can be mixed.</literallayout></section><section><title><programlisting><array-collection/></programlisting></title><literallayout>The array-collection contains a list of the following possible values, these types can bemixed</literallayout></section><section><title><programlisting><constructor-arg/></programlisting></title><literallayout>Constructor arguments. You can pass in a comma-delimited set of values, or a morecomplex value.</literallayout><itemizedlist>

Page 148: Spring Action Script

Configuration reference

142

<title>Attributes</title><listitem>value<remark><literallayout>A literal value for this particular argument. This can be a comma-delimited set of values</literallayout></remark></listitem><listitem>ref<remark><literallayout>A reference to an object defined in the container.</literallayout></remark></listitem><listitem>template<remark><literallayout>The name of a template which should be used to instantiate this specific argument. Whendefined as an attribute no parameters can be passed to the template, so no placeholder substitution willoccur. Use a child template elementinstead if parameters are needed.</literallayout></remark></listitem><listitem>type<remark><literallayout> Defines an optional type for the constructor argument, the value of the value attribute willbe cast to this type at runtime. </literallayout></remark></listitem></itemizedlist></section><section><title><programlisting><dictionary/></programlisting></title><literallayout>A dictionary contains a list properties specified like this: <property name="level"><dictionary> <entry> <key>a key</key> <value>a</value> </entry> <entry> <key>another key</key><value>1</value> </entry> <entry> <key>true</key> <value> <array> <value>b</value> <value>c</value> </array> </value> </entry> </dictionary> </property> </literallayout><para> The following elements occur in dictionary: </para><simplelist><member><link>entry</link></member></simplelist></section><section><title><programlisting><entry/></programlisting></title><literallayout>Defines an entry that will be added to a dictionary instance.</literallayout><itemizedlist><title>Attributes</title><listitem>key<remark><literallayout>A literal key name for the specified entry.</literallayout></remark></listitem>

Page 149: Spring Action Script

Configuration reference

143

<listitem>value<remark><literallayout>A literal value for the specified entry.</literallayout></remark></listitem></itemizedlist><para> The following elements occur in entry: </para><simplelist><member><link>key</link></member><member><link>value</link></member></simplelist></section><section><title><programlisting><import/></programlisting></title><literallayout>Imports an external configuration file, this way its possible to split up a configuration intomultiple files to keep a better overview or to keep different version of the configuration across differentservers.</literallayout><itemizedlist><title>Attributes</title><listitem>file (required)<remark><literallayout>A valid URI for the specified file. For a flex project this can be a relative URI, whenused in an AIR application make sure to add a fully qualified local URI such as file:///subconfig.xml</literallayout></remark></listitem></itemizedlist></section><section><title><programlisting><interface/></programlisting></title><literallayout>The Interface type defines properties and methods for objects that implement the specifiedinterface.</literallayout><itemizedlist><title>Attributes</title><listitem>class<remark><literallayout>The fully qualified classname for the specified interface. This class needs to be known atcompile-time otherwise a runtime error will occur.</literallayout></remark></listitem><listitem>init-method<remark><literallayout>The name of a generic initialization method which will be called directly after instantiationand property injection.</literallayout></remark></listitem>

Page 150: Spring Action Script

Configuration reference

144

</itemizedlist><para> The following elements occur in interface: </para><simplelist></simplelist></section><section><title><programlisting><key/></programlisting></title><literallayout>Defines a key that will be used for a dictionary entry.</literallayout><itemizedlist><title>Attributes</title><listitem>type<remark></remark></listitem></itemizedlist><para> The following elements occur in key: </para><simplelist><member><link>object</link></member><member><link>array</link></member><member><link>array-collection</link></member><member><link>dictionary</link></member><member><link>ref</link></member></simplelist></section><section><title><programlisting><method-invocation/></programlisting></title><literallayout>Defines a method and optional method arguments. After instantiation of the object thespecified method will be invoked with the specified arguments. No compile checks are possible for thisdefinition, so if the method does not exist on the object this will result in a runtime error.</literallayout><itemizedlist><title>Attributes</title><listitem>name (required)<remark><literallayout>The name of the method.</literallayout></remark></listitem></itemizedlist><para> The following elements occur in method-invocation: </para><simplelist><member><link>arg</link></member>

Page 151: Spring Action Script

Configuration reference

145

</simplelist></section><section><title><programlisting><object/></programlisting></title><literallayout>The Object type defines the basic Object that is configured by the IoC container.</literallayout><itemizedlist><title>Attributes</title><listitem>class<remark><literallayout>The fully qualified classname for the specified object. This class needs to be known atcompile-time otherwise a runtime error will occur.</literallayout></remark></listitem><listitem>id<remark><literallayout>A unique id. This id can be used to retrieve an object by calling the getObject method onthe applicationcontext.</literallayout></remark></listitem><listitem>factory-method<remark><literallayout>Optional method that will be called instead of the constructor.</literallayout></remark></listitem><listitem>factory-object<remark><literallayout>Optional name of a factory object responsible for the creation of the object.</literallayout></remark></listitem><listitem>scope =enumeration(prototype,singleton)<remark><literallayout>When an object is a singleton, only one shared instance of the object will be managed, andall requests for objects with an id or ids matching that object definition will result in that one specific beaninstance being returned by the Spring container. The non-singleton, prototype scope of object deploymentresults in the creation of a new object instance every time a request for that specific object is made (thatis, it is injected into another object or it is requested via a programmatic getObject() method call on thecontainer). As a rule of thumb, you should use the prototype scope for all objects that are stateful, whilethe singleton scope should be used for stateless objects.</literallayout></remark></listitem><listitem>lazy-init<remark><literallayout>By default objects marked as a singleton will be constructed immediately after the containerhas finished initializing. When lazy-init is set to true though, instantation will be deferred until the firsttime that the getObject method is called for the specified singleton.</literallayout></remark></listitem><listitem>init-method<remark><literallayout>The name of a generic initialization method which will be called directly after instantationand property injection.</literallayout>

Page 152: Spring Action Script

Configuration reference

146

</remark></listitem><listitem>destroy-method<remark><literallayout>The name of a generic destroy method which will be called when the application contextis disposed.</literallayout></remark></listitem><listitem>singleton<remark><literallayout>When set to true, this property determines that the getObject method will always return areference to the same instance of the specified object. When set to false, the getObject method will alwaysreturn a new instance.</literallayout></remark></listitem><listitem>template<remark><literallayout>The id of a template defined in the current container.</literallayout></remark></listitem><listitem>abstract<remark><literallayout>When set to true this property determines that the specified object cannot be directlyinstantiated on its own since it is incomplete. When a definition is considered abstract like this (explicitly orimplicitly), it's usable just as a pure template or abstract object definition that will serve as parent definitionfor child definitions.</literallayout></remark></listitem><listitem>parent<remark><literallayout>The id of another object defined in the current container. A child object definition will usethe object class from the parent definition if none is specified, but can also override it. In the latter case,the child object class must be compatible with the parent, i.e. it must accept the parent's property values. Achild object definition will inherit constructor argument values, property values and method overrides fromthe parent, with the option to add new values. If init method, destroy method and/or static factory methodare specified, they will override the corresponding parent settings. The remaining settings will always betaken from the child definition: depends-on, dependency check, singleton, lazy-init.</literallayout></remark></listitem><listitem>depends-on<remark><literallayout>For the relatively infrequent situations where dependencies between objects are less direct(for example, when a static initializer in a class needs to be triggered), the depends-on element may be usedto explicitly force one or more objects to be initialized before the object using this element is initialized.</literallayout></remark></listitem><listitem>autowire-candidate<remark><literallayout>True if this object may be used as an autowiring candidate when another object is autowiredbyType</literallayout></remark></listitem><listitem>primary

Page 153: Spring Action Script

Configuration reference

147

<remark><literallayout>True if more than one object of the same type exists in the configuration and the currentobject needs to be the autowire candidate.</literallayout></remark></listitem><listitem>skip-postprocessors<remark><literallayout>Determines whether the object factory will send the created object through its list ofIObjectProcessors.</literallayout></remark></listitem><listitem>skip-metadata<remark><literallayout>Determines whether the autowire processor will examine the class metadata.</literallayout></remark></listitem><listitem>autowire =enumeration(autodetect,byName,byType,constructor,no)<remark><literallayout>Defines the autowiring strategy to be used for the current object, default is 'no'.</literallayout></remark></listitem><listitem>dependency-check =enumeration(all,none,objects,simple)<remark><literallayout>Defines the dependency check strategy to be used after autowired properties are set for thecurrent object, default is 'none'.</literallayout></remark></listitem></itemizedlist><para> The following elements occur in object: </para><simplelist></simplelist></section><section><title><programlisting><param/></programlisting></title><literallayout>Template parameters have a name and a value. Currently only string replacement forparameter values is allowed.</literallayout></section><section><title><programlisting><property/></programlisting></title><literallayout>Can be used to load external properties from a file. This is similar to how Ant loads externalproperties. <property file="strings.properties" /> the property file looks like: s1=First string s2=Secondstring Note: the path to the property file is relative to the path of the application context xml file. Note:on some servers, the "properties" extension might be blocked. You can either allow the extension inthe server configuration or add an extra "txt" (or other) prefix that is allowed to be served: <propertyfile="strings.properties.txt" /> The properties loader will prevent caching of the properties by default,to turn this behavior off set the prevent-cache attribute to false: <property file="strings.properties.txt"prevent-cache="false"/> By default the properties loader will throw an error if a properties file couldnot be loaded, to ignore the error and resume loading set the required attribute to false: <propertyfile="strings.properties.txt" required="false"/> it is also possible to directly define properties using this

Page 154: Spring Action Script

Configuration reference

148

element. In this case omit the file attribute and add the name and value as attributes, like this: <propertyname="s1" value="First string"/> <property name="s2" value="Second string"/> The file attribute willtake precedence over the name and value attributes. </literallayout><itemizedlist><title>Attributes</title><listitem>file<remark><literallayout>A valid URI for the specified properties file. For a flex project this can be a relativeURI, when used in an AIR application make sure to add a fully qualified local URI such as file:///subconfig.xml</literallayout></remark></listitem><listitem>prevent-cache<remark><literallayout>If true the properties loader will make sure no cached copy of the file will be loaded</literallayout></remark></listitem><listitem>required<remark><literallayout>If true the properties loader will throw an error when the file could not be loaded</literallayout></remark></listitem><listitem>name<remark><literallayout>The name of the property</literallayout></remark></listitem><listitem>value<remark><literallayout>The value of the property</literallayout></remark></listitem></itemizedlist></section><section><title><programlisting><property/></programlisting></title><literallayout>Defines the value of a property on an object.</literallayout><itemizedlist><title>Attributes</title><listitem>name<remark><literallayout>The name of the specified property.</literallayout></remark></listitem><listitem>value<remark><literallayout>A literal value for the property.</literallayout></remark></listitem><listitem>type

Page 155: Spring Action Script

Configuration reference

149

<remark><literallayout>Defines an optional type for the property, the value of the value attribute will be cast to thistype at runtime.</literallayout></remark></listitem><listitem>ref<remark><literallayout>A reference to another object defined in the container.</literallayout></remark></listitem><listitem>template<remark><literallayout>The name of a template which should be used to instantiate this specific property. Whendefined as an attribute no parameters can be passed to the template, so no placeholder substitution willoccur. Use a child template element instead if parameters are needed.</literallayout></remark></listitem></itemizedlist></section><section><title><programlisting><template/></programlisting></title><literallayout>A template is used to assist in creation of other objects. It can define a numberof properties that will be injected by the same values and instances for every object based onthis template. To use a template, you can specify variables in braces (placeholders). Here isan example: <template id="remoteObject"> <object class="mx.rpc.remoting.mxml.RemoteObject"><property name="destination" value="GenericDestination"/> <property name="endpoint"ref="remoteGateway"/> <property name="source" value="ApplicationDomain.Services.${serviceClass}"/> </object> </template> and used like: <object id="serviceLocator"class="org.springextensions.actionscript.cairngorm.CairngormServiceLocator" factory-method="getInstance"> <property name="assetService" template="remoteObject"> <paramname="serviceClass" value="AssetService"/> </property> <property name="packageService"template="remoteObject"> <param name="serviceClass" value="PackageService"/> </property><property name="userService" template="remoteObject"> <param name="serviceClass"value="UserService"/> </property> </object> </literallayout><itemizedlist><title>Attributes</title><listitem>id<remark><literallayout>A unique identifier for the specified template.</literallayout></remark></listitem></itemizedlist><para> The following elements occur in template: </para><simplelist><member><link>object</link></member></simplelist></section><section><title><programlisting><value/></programlisting>

Page 156: Spring Action Script

Configuration reference

150

</title><literallayout>Defines a value that will be used for a dictionary entry.</literallayout><itemizedlist><title>Attributes</title><listitem>type<remark></remark></listitem></itemizedlist><para> The following elements occur in value: </para><simplelist><member><link>object</link></member><member><link>array</link></member><member><link>array-collection</link></member><member><link>dictionary</link></member><member><link>ref</link></member></simplelist></section><section><title><programlisting><vector/></programlisting></title><literallayout>The vector contains a list of the following possible values, these types can be mixed. Theeventual resolved objects need to be of the same Class as the type attribute indicates.</literallayout><itemizedlist><title>Attributes</title><listitem>type (required)<remark></remark></listitem></itemizedlist><para> The following elements occur in vector: </para><simplelist><member><link>value</link></member><member><link>ref</link></member><member><link>object</link></member></simplelist></section>

Page 157: Spring Action Script

151

Spring actionscript GlossaryThis is a list of terms used throughout the Spring Actionscript documentation.

CCairngorm Cairngorm is the lightweight micro-architecture for Rich Internet

Applications built in Flex or AIR. A collaboration of recognizeddesign patterns, Cairngorm exemplifies and encourages best-practicesfor RIA development advocated by Adobe Consulting, encouragesbest-practice leverage of the underlying Flex framework, whilemaking it easier for medium to large teams of software engineersdeliver medium to large scale, mission-critical Rich InternetApplications.

DDI See Dependency injection.

Dependency injection Dependency Injection (DI) in computer programming refers to theprocess of supplying an external dependency to a software component.It is a specific form of inversion of control where the concern beinginverted is the process of obtaining the needed dependency. Theterm was first coined by Martin Fowler to more clearly describe themechanism.See Also Inversion of Control.

EExtensible Markup Language XML (Extensible Markup Language) is a general-purpose

specification for creating custom markup languages.See Also Extensible Markup Language.

IIoC See Inversion of Control.

Inversion of Control Inversion of Control, or IoC, is an abstract principle describingan aspect of some software architecture designs in which the flowof control of a system is inverted in comparison to the traditionalarchitecture of software libraries.See Also Dependency injection.

Integrated developmentenvironment

An integrated development environment (IDE) also known asintegrated design environment or integrated debugging environmentis a software application that provides comprehensive facilities tocomputer programmers for software development.

Page 158: Spring Action Script

152

PPureMVC PureMVC is a lightweight framework for creating applications based

upon the classic Model, View and Controller concept. Based uponproven design patterns, this free, open source framework whichwas originally implemented in the ActionScript 3 language for usewith Adobe Flex, Flash and AIR, is now being ported to all majordevelopment platforms.

XXML See Extensible Markup Language.