There have been a lot of discussions around Flex Frameworks lately. Tony Hillerson has an interesting series here: 1 2 3 4 5 6
A relative newcomer on the list is Swiz, the work of Chris Scott. I figured I would give it a try, and create a Swiz version of the inSync application that I often use to try out and demonstrate different features and techniques in Flex and Adobe AIR. This is not an endorsement of Swiz over other frameworks. I simply wanted to share the sample application I built as part of my own research as a (neutral like a Swiss) Evangelist.
Application Highlights:
At his core, Swiz is a simple inversion of control framework. Using an IoC framework, the components of your application (for example, Views) don’t instantiate or even look up their dependencies (the objects they work with). The framework injects those dependencies when the components are created (hence the term “Dependency Injection” also used to describe this approach). The result is looser coupling and more reusable components. The components managed by the Swiz IoC framework are called beans.
1. Defining your beans
The beans of the inSync applications are defined in Beans.mxml:
<BeanLoader xmlns="org.swizframework.util.*" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:controllers="insync.controllers.*"> <DynamicChannelSet id="myAmfChannel"> <serverPort>8400</serverPort> <contextRoot>/lcds-samples</contextRoot> </DynamicChannelSet> <mx:RemoteObject id="contactService" destination="contacts" channelSet="{myAmfChannel}"/> <controllers:ContactController id="contactController"/> </BeanLoader>
2. Bootstrapping Swiz
You bootstrap Swiz in the preinitialize event of the application. You can have multiple Beans configuration classes. You pass your configuration classes in an array as an argument of the loadBeans function. In inSync, we have only one configuration class (Beans.mxml).
Swiz.loadBeans( [Beans] );
3. Injecting dependencies
Swiz uses the [Autowire] custom metadata to inject beans into other beans and views.
In inSync, the contactService RemoteObject is injected into ContactController.as as follows:
[Autowire(bean="contactService")] public var contactService:RemoteObject;
… and contactController is injected in the Views. For example, in ContactForm.mxml:
[Autowire(bean="contactController")] public var controller:IContactController;
Because we use an interface, the View is not coupled to a specific implementation of the controller. If you don’t like to have a reference to the controller in your view, keep reading…
4. Dynamic Mediators
Swiz is an IoC framework. Beyond that, it doesn’t force you to use any specific design pattern. So, if you don’t like to have a controller in your view, you can, for example, set up the view to dispatch events instead. For example, in the save() function of ContactForm.mxml, you would replace:
controller.save(contact);
with:
Swiz.dispatchEvent(ContactEvent.SAVE, contact);
You could then listen to this event in some “mediator” class using Swiz.addEventListener(ContactEvent.UPDATE, someHandler), but the dynamic mediator feature of Swiz allows you to automate this process. For example, you could annotate the save() function of the ContactController class as follows:
[Mediate(event="ContactEvent.SAVE", properties="contact")] public function save(contact:Contact):void { executeServiceCall(contactService.save(contact), save_result, null, [contact]); }
Swiz will automatically set up an event listener, invoke the annotated method when the event is dispatched, and pass the specified event properties (in this case: “contact”) as the function parameters.
5. Prototypes
By default, components defined in your Beans configuration classes are singletons. In other words, the same instance of a Bean gets injected everytime it is autowired. In some situations, you may want to inject a new instance of a Bean everytime it is autowired. For example, if you open multiple instances of the same View, you may decide you need one controller per view. Prototypes allow you to define non-singleton Beans in your Beans configuration class using the following syntax:
More on prototypes here.
<factory:Prototype xmlns:factory="org.swizframework.factory.*" id="contactController" className="insync.controllers.ContactController"/>
Installation instructions:
- Install the BlazeDS turnkey server. (To be clear: you don’t have to use BlazeDS to use Swiz… That’s just the sample I wanted to build.)
- Download insync-swiz.zip, and unzip it on your local file system.
- Copy insync-swiz/java/classes/insync to blazeds/tomcat/webapps/samples/WEB-INF/classes/insync.
- Add the following destination to blazeds/tomcat/webapps/samples/WEB-INF/flex/remoting-config.xml:
- Copy insync-swiz/sampledb/insync to blazeds/sampledb/insync
- Edit server.properties in blazeds/sampledb, and modify the file as follows to add the insync database to the startup procedure.
server.database.0=file:flexdemodb/flexdemodb server.dbname.0=flexdemodb server.database.1=file:insync/insync server.dbname.1=insync server.port=9002 server.silent=true server.trace=false
- Start the database (startdb.bat or startdb.sh)
- Start BlazeDS
- In Flex Builder, create a new Flex project called insync-swiz. You don’t have to select any “Application server type”.
- Copy the Swiz swc and the flexlib swc (used for the SuperTabNavigator) from insync-swiz/flex/lib to the lib directory of your project
- Copy the files and folders from insync-swiz/flex/src to the src directory of your project
- Open Beans.mxml and make sure the serverPort and contextRoot properties in DynamicChannelSet match your server setup.
- Run the application
<destination id="contacts"> <properties> <source>insync.dao.ContactDAO</source> <scope>application</scope> </properties> </destination>
Summary
Swiz was easy and enjoyable to work with. It is also non intrusive and definitely introduces some interesting ideas. A few lingering questions I didn’t have time to investigate…
- Swiz relies on introspection (describeType) to find its custom metadata in the objects added to the display list (with the exception of classes in the flash.* and mx.* packages). This has a performance impact. I’m not exactly sure how much of an impact it would have in real life apps yet…
- How well does Swiz work with Modules or Marshall Plan subapplications?
If you are looking for more information, check out the following resources:
Pingback: Shared Items - March 1, 2009 | hufkens.net()
Pingback: Christophe Coenraets » Blog Archive » The “Spring ActionScript” Framework – Part 2: Autowiring()
Pingback: Christophe Coenraets » Blog Archive » Building a Flex Application with the Parsley Framework()
Pingback: [Flex & AIR] Swiz Framework – meus primeiros passos | Erko Bridee()
Pingback: Felipe Borella » Swiz Framework()
Pingback: Mxml samples | Eyesoftheeast()