Anda di halaman 1dari 47

1. _sidebar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. Home . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Quick Start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 User Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.2 IoC Container . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.

3 Dependency Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.4 View Mediator and ViewNavigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.5 Bean Life Cycle Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.6 Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.7 Service Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.8 Client Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.9 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Advanced Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 AutowiredTestCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Chaining API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.3 Custom Metadata Processors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.4 Module Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.5 Support for the Command pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Best Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Presentation Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Release Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7 IDE Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8 External Community Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9 Migration Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9.1 Updating a Swiz 0.6.4 application to Swiz 1.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.10 How To Contribute to Swiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.11 Presentations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.12 FAQ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 2 3 9 10 11 13 15 16 20 22 23 24 25 25 27 33 33 34 35 35 37 37 41 43 43 43 44 45 45

_sidebar

Note About Comments Feel free to give feedback on the documentation with a comment. But for technical questions, please use the Swiz mailing list.

Save as HTML or PDF You can export this entire Wiki in HTML or PDF format.

Home
What is Swiz?
Swiz is a framework for Adobe Flex, AIR, and Flash that aims to bring complete simplicity to RIA development. Swiz provides: Inversion of Control / Dependency Injection Event handling A simple life cycle for asynchronous remote method invocations A framework that is decoupled from your application code Compatibility with both Flex and non-Flex AS3 projects In contrast to other major frameworks for Flex, Swiz: Imposes no JEE patterns on your code No repetitive folder layouts No boilerplate code on your development Does not require you to extend framework-specific classes Swiz represents best practices learned from the top RIA developers at some of the best consulting firms in the industry, enabling Swiz to be simple, lightweight, and extremely productive.

How Do I Get It?


The latest released version is 1.3.1. A zip file containing the SWC, source and ASDocs is here: Swiz 1.3.1 Download and release notes can be found here: Swiz Release Notes The latest code can always be found on GitHub at http://github.com/swiz/swiz-framework/. You can also try out the Swiz 2.0.0 Beta, which includes AOP support. More details can be found on the Swiz blog.

Looking for an earlier version of Swiz?


Swiz 1.2.0 Download Swiz 1.1.0 Download Swiz 1.0.0 Download

Visualizing Swiz
Sometimes pictures can help solidify an idea better than words can. With that in mind, here are basic representations of two core Swiz features: dependency injection and event handling. Dependency Injection Event Handling

A Little Help Here?


If you have any questions please join the mailing list. You can also find Swiz on Twitter and Swiz on Facebook. Swiz is provided under the Apache License 2.0

Quick Start
Page Contents:
A Lightning Look at Configuration The "Big Three": Dependency Injection, Event Handling, and Server Interaction Adding Dependency Injection Dispatching and Handling Events Talking to the Server There's More Where That Came From

You can download this Quick Start as a Flash Builder FXP or Zip file. It's also available in the Swiz Examples repository on GitHub, along with more examples.

A Lightning Look at Configuration


Configuring Swiz in your Flex or AIR application is very straightforward: declare Swiz, define the beanProviders and config properties, and optionally define one or more loggingTargets to view debugging messages. Here is an example:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:view="org.swizframework.quickswiz.view.*" xmlns:config="org.swizframework.quickswiz.config.*" xmlns:swiz="http://swiz.swizframework.org"> <fx:Declarations> <swiz:Swiz> <!-- BeanProviders simply contain the non-display objects that Swiz should process. --> <swiz:beanProviders> <config:Beans /> </swiz:beanProviders> <swiz:loggingTargets> <swiz:SwizTraceTarget id="myTraceTarget" /> </swiz:loggingTargets> <swiz:config> <!-- The eventPackages value tells Swiz the path to your Event classes, and viewPackages is an optional value that speeds up the processing of display classes. --> <swiz:SwizConfig eventPackages="org.swizframework.quickswiz.event.*" viewPackages="org.swizframework.quickswiz.view.*" /> </swiz:config> </swiz:Swiz> </fx:Declarations> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingTop="20" /> </s:layout> <view:UserForm id="userForm" /> </s:Application>

Non-visual components that you want Swiz to manage are defined in a BeanProvider tag. Any beans that you define within the BeanProvider are processed by Swiz for dependency injection and the creation of event handlers. In the following example, a UserService and a UserController are created:

<swiz:BeanProvider xmlns:swiz="http://swiz.swizframework.org" xmlns:service="org.swizframework.quickswiz.service.*" xmlns:controller="org.swizframework.quickswiz.controller.*"> <service:UserService id="userService"/> <controller:UserController id="userController"/> <!-- We'll use the Swiz ServiceHelper to help simulate a server-side call. --> <swiz:ServiceHelper id="serviceHelper" /> </swiz:BeanProvider>

The "Big Three": Dependency Injection, Event Handling, and Server Interaction
The three most commonly used features of Swiz are its dependency injection capabilities, its event handling features, and its server interaction utilities. Let's look at how each of these work.

Adding Dependency Injection


Dependencies are injected by using [Inject] metadata. In this example, the UserService is injected into the UserController:

package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.model.User; import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [Bindable] public var currentUser : User; } }

In addition to injecting a bean, you can inject individual bean properties. In this example, the currentUser property of the UserController is injected into a UserForm visual component. Note that it is not necessary for the UserForm to be declared as a bean in the BeanProviders tag. When visual components are added to the display list, Swiz automatically inspects them and processes any metadata tags that are found.
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import org.swizframework.quickswiz.event.UserEvent; import org.swizframework.quickswiz.model.User; [Bindable] [Inject( source="userController.currentUser", bind="true" )] /** * We could inject the whole controller instance, but we only need * one property from the controller, the current user, so we just * inject that property. */ public var user : User; ]]> </fx:Script> <mx:Form> <mx:Text id="userId" text="{isNaN( user.id ) ? 'N/A' : user.id}" /> <s:TextInput id="firstName" text="{user.firstName}" /> <s:TextInput id="lastName" text="{user.lastName}" /> <s:TextInput id="email" text="{user.email}" /> <s:Button label="Save" /> </mx:Form> </s:Panel>

Dispatching and Handling Events


When using Swiz, you dispatch standard Flex events. In this example, we've expanded the UserForm to create and dispatch an event when the form button is clicked. Swiz listens for events being dispatched within the display list and handles them automatically.

<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx"> <fx:Script> <![CDATA[ import org.swizframework.quickswiz.event.UserEvent; import org.swizframework.quickswiz.model.User; [Bindable] [Inject( source="userController.currentUser", bind="true" )] /** * We could inject the whole controller instance, but we only need * one property from the controller, the current user, so we just * inject that property. */ public var user : User; /** * Handle the user hitting the save button. We capture the form data * and dispatch a standard Flex event. No Swiz-specific events or * special central dispatcher needed! */ private function saveUser() : void { user.firstName = firstName.text; user.lastName = lastName.text; user.email = email.text; var event : UserEvent = new UserEvent( UserEvent.SAVE_USER_REQUESTED ); event.user = user; dispatchEvent( event ); } ]]> </fx:Script> <mx:Form> <mx:Text id="userId" text="{isNaN( user.id ) ? 'N/A' : user.id}" /> <s:TextInput id="firstName" text="{user.firstName}" /> <s:TextInput id="lastName" text="{user.lastName}" /> <s:TextInput id="email" text="{user.email}" /> <s:Button label="Save" click="saveUser()" /> </mx:Form> </s:Panel>

A look at the UserEvent confirms that this is just a simple, standard event. The only thing to note here is that the event has bubbles set to true. This allows the event to bubble up the display list so that it can be handled by Swiz:

package org.swizframework.quickswiz.event { import org.swizframework.quickswiz.model.User; import flash.events.Event; public class UserEvent extends Event { public static const SAVE_USER_REQUESTED : String = "saveUser"; public var user : User; /** * This is just a normal Flex event. The only thing to note is that we set 'bubbles' to true, * so that the event will bubble up the display list, allowing Swiz to listen for your events. */ public function UserEvent( type:String ) { super( type, true ); } } }

We've seen how to dispatch events from the display list, but how do we handle the events? Swiz provides a [EventHandler] metadata tag to do this. In the example below, we have expanded the UserController to add an event handler method. In this case, when Swiz encounters an event of type UserEvent.SAVE_USER_REQUESTED, it will automatically invoke the saveUser method in the UserController. By specifying a value of "user" for the properties attribute, Swiz will locate the user property in the UserEvent and pass this as a parameter to the handler method:
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.model.User; import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [Bindable] public var currentUser : User; [PostConstruct] /** * [PostConstruct] methods are invoked after all dependencies are injected. * In this example, we set up a default user after the bean is created. */ public function createDefaultUser() : void { currentUser = new User(); } [EventHandler( event="UserEvent.SAVE_USER_REQUESTED", properties="user" )] /** * Perform a server request to save the user */ public function saveUser( user : User ) : void { // TODO: Add server interaction } } }

One last feature to note regarding event dispatching. We've seen how an event dispatched from the display list will bubble up until it is processed

by Swiz. But what about dispatching events from non-visual components like controllers and services? Swiz offers the [Dispatcher] metadata tag to meet this need. In the UserService shown below, Swiz will automatically inject an event dispatcher into the dispatcher property. Any events dispatched though this dispatcher will also be processed by Swiz and trigger any event handler methods associated with the event:
package { import import import org.swizframework.quickswiz.service org.swizframework.quickswiz.model.User; flash.events.IEventDispatcher; mx.rpc.AsyncToken;

import org.swizframework.utils.services.MockDelegateHelper; public class UserService { [Dispatcher] /** * The [Dispatcher] metadata tag instructs Swiz to inject an event dispatcher. * Events dispatched via this dispatcher can trigger methods annotated with [EventHandler]. */ public var dispatcher : IEventDispatcher; /** * To avoid a live server dependency, we use a Swiz * helper class to let us create fake AsyncTokens */ private var mockHelper : MockDelegateHelper; public function UserService() { mockHelper = new MockDelegateHelper(); } /** * In a real app, we'd invoke a RemoteObject, HTTPService, etc. * For this simple example, we'll set a random ID on the User * to simulate the process of saving a User. */ public function saveUser( user : User ) : AsyncToken { user.id = Math.round( Math.random() * 100 ); return mockHelper.createMockResult( user ); } } }

Talking to the Server


Our UserController can now respond when a save user event is dispatched. The final piece of the puzzle is having the application make a call to the server to actually save the user in a database. Typically, Flex requries you to manually create Responder objects to attach to AsyncTokens that will handle ResultEvent and FaultEvent. Swiz offers some helpful features to sidestep these manual processes. Below, you see the final version of our UserController. Because it has the Swiz helper object ServiceHelper injected, we can use its executeServiceCall() method. This method will automatically obtain the AsyncToken for the RPC call and create Responder objects. In this case, we call userService.saveUser(), and specify handleSaveUserResult to handle the successful response from the server. Although it is not shown here, we can also specify a method to use as the fault handler.

package { import import import import import

org.swizframework.quickswiz.controller org.swizframework.quickswiz.model.User; org.swizframework.quickswiz.service.UserService; mx.controls.Alert; mx.rpc.events.ResultEvent; org.swizframework.utils.services.ServiceHelper;

public class UserController { [Inject] public var userService : UserService; [Inject] public var serviceHelper : ServiceHelper; [Bindable] public var currentUser : User; [PostConstruct] /** * [PostConstruct] methods are invoked after all dependencies are injected. * In this example, we set up a default user after the bean is created. */ public function createDefaultUser() : void { currentUser = new User(); } [EventHandler( event="UserEvent.SAVE_USER_REQUESTED", properties="user" )] /** * Perform a server request to save the user */ public function saveUser( user : User ) : void { serviceHelper.executeServiceCall( userService.saveUser( user ), handleSaveUserResult ); } /** * Handle the server call result */ private function handleSaveUserResult( event : ResultEvent ) : void { // Show an Alert just to make it obvious that the save was successful. Alert.show( 'User saved successfully!' ); } } }

There's More Where That Came From


This quick tour has shown how easy it is to configure Swiz and use its core features. But Swiz offers much more than this! Please read the User Guide, Best Practices, and Advanced Topics to learn more.

User Guide
Welcome to the Swiz User Guide!
Please select a subsection from the menu to view more details about how Swiz works.

Configuration
Page Contents:
Configuration Overview Logging setUpEventType, setUpEventPhase and setUpEventPriority tearDownEventType, tearDownEventPhase and tearDownEventPriority Default Dispatcher

Configuration Overview
You configure each Swiz instance using the SwizConfig class. It allows you to modify common settings, and to provide values that allow your tags and code elsewhere to be more concise. Below is an example with all properties shown. Where applicable, they have been set to their default values. However, in most cases, the default values should work fine (see the note below on Configuration Defaults).
<swiz:Swiz> <swiz:beanProviders> <local:MyBeans /> </swiz:beanProviders> <swiz:loggingTargets> <swiz:SwizTraceTarget id="myTraceTarget" /> </swiz:loggingTargets> <swiz:config> <swiz:SwizConfig setUpEventType="{ Event.ADDED_TO_STAGE }" setUpEventPhase="{ EventPhase.CAPTURING_PHASE }" setUpEventPriority="50" tearDownEventType="{ Event.REMOVED_FROM_STAGE }" tearDownEventPhase="{ EventPhase.CAPTURING_PHASE }" tearDownEventPriority="50" eventPackages="com.foo.event.*, org.bar.event.*" viewPackages="com.foo.view.*, org.bar.view.*" defaultFaultHandler="handleUnhandledFaults" defaultDispatcher="global" /> </swiz:config> </swiz:Swiz>

Configuration Defaults Unless you are specifying your own set up and tear down values, the only configuration values that commonly need to be set are eventPackages and viewPackages. If you are using Swiz's support for server communication, you may also set defaultFaultHandler.

Specifying Packages Note that due to limitations in the AS3 reflection API, when you define eventPackages, you must specify each package individually. Children of your specified packages cannot be resolved and must be explicitly set. This limitation does not apply to viewPackages because they are handled differently, but for consistency it may be useful to use the same rules to define both sets of packages.

Logging
As you can see above, Swiz includes a basic logging target called SwizTraceTarget to trace debugging information to the console. Due to the way the MXMLC compiler works, it was not possible to use the built-in Flex logging target(s), because it increases the size of the Swiz swc by an unacceptable amount. If necessary, you can extend the AbstractSwizLoggingTarget to customize the output.

setUpEventType, setUpEventPhase and setUpEventPriority


These properties configure the listener that Swiz will use to trigger the set up of views (assuming they are eligible) to inject dependencies, create event handlers, etc. The default is a capture phase listener (to catch all views regardless of their place in the display list hierarchy) for the

Event.ADDED_TO_STAGE event, with a priority of 50.

tearDownEventType, tearDownEventPhase and tearDownEventPriority


These properties configure the listener that Swiz will use to trigger the tearing down of views to clean up injected dependencies, remove event handlers, etc. The default is a capture phase listener for the Event.REMOVED_FROM_STAGE event, with a priority of 50.

Default Dispatcher
The default dispatcher value is "global". This means that in the case where a Swiz instance is the child of another Swiz instance, the child will use the parent dispatcher. This allows for easy communication between Swiz instances, since they all share the same event dispatcher. However, if you want to force a child Swiz to use it's own dispatcher, you can set this value to "local". In most cases, developers should not need to change the default value ("global"). More information on parent-child Swiz instances can be found in the section on Module support.

IoC Container
Page Contents:
The BeanProvider Class Prototype Beans Externalizing Configuration Values

The BeanProvider Class


The IoC (Inversion of control) container of Swiz is the BeanProvider class. In the BeanProvider you typically define non-view classes that you want registered with the framework and available as injection sources or targets. This generally means models, controllers, delegates and services. Beans are defined using regular MXML tags:
<?xml version="1.0" encoding="utf-8"?> <swiz:BeanProvider xmlns:swiz="http://swiz.swizframework.org" xmlns:model="com.example.model.*" xmlns:control="com.example.control.*"> <model:ApplicationModel id="applicationModel" /> <control:UserController id="userController" /> </swiz:BeanProvider>

Most applications define at least one Beans.mxml in the root package and pass it to the Swiz tag's beanProviders property in the applications main MXML file. For clarity and simplicity, it is recommended that you define your beans in a separate file, using BeanProvider as the root tag, as shown above. However, if for some reason you choose to define your beans inline in the Swiz tag, you'll need to wrap your objects with the Bean tag to ensure they are processed correctly:
<swiz:Swiz> <swiz:beanProviders> <swiz:BeanProvider> <swiz:Bean name="applicationModel"> <model:ApplicationModel /> </swiz:Bean> <swiz:Bean name="userController"> <control:UserController /> </swiz:Bean> </swiz:BeanProvider> </swiz:beanProviders> <swiz:config> <swiz:SwizConfig eventPackages="com.foo.events, org.bar.events" viewPackages="com.foo.views, org.bar.events" /> </swiz:config> </swiz:Swiz>

Prototype Beans
Similar to Springs prototype scope, Swiz provides a Prototype tag. Prototype enables a few different things: Constructor injection you can pass up to 8 arguments to your beans constructor Unique copy for each injection target (like prototype scope behavior in Spring) Deferred instantiation Prototype beans will not be created until they are needed for injection
<swiz:Prototype id="editViewPresoModel" type="{ EditViewPresentationModel }" constructorArguments="{ someOtherBean }" />

If you want deferred instantiation and/or constructor injection but not a unique copy for each injection you can set Prototypes singleton property to true.

A Prototype bean created and injected into a view is not destroyed when the view is removed. Swiz cannot know what else you may have done with the Prototype. If you wish to tear down a Prototype bean when a view is removed, implement a [PreDestroy] method and dispatch a TEAR_DOWN_BEAN event for the Prototype bean.

Externalizing Configuration Values


Bean property values can also be defined in external XML files. The SwizConfigValueLoader Swiz extension provides one way to handle this. For example, an XML file with this structure:
<config> <value1>This is value 1.</value1> <value2>This is value 2.</value2> </config>

Can be loaded and used in a BeanProvider by doing:

<externalconfig:SwizConfigValueLoader id="configLoader" source="config.xml" /> <controller:MyController id="myController" value1="{configLoader.configData.config.value1}" value2="{configLoader.configData.config.value2}" />

The SwizConfigValueLoader can be injected just like any other bean:

[Inject] public var configLoader : SwizConfigValueLoader;

Finally, you can create an event handler to execute after the external data is loaded (remember to add "org.swizframework.externalconfig.event" to your eventPackages):

[EventHandler( event = "ConfigLoaderEvent.CONFIG_LOAD_COMPLETE", properties = "configData" )] public function onConfigLoadComplete( configData : Object ) : void { // You can now reference the value with syntax such as: // configData.config.value1, configData.config.value2, etc. }

Dependency Injection
Page Contents:
Dependency Injection Overview Inject by type Inject by name Inject bean property Two way bindings Setter injection Injection destination

Dependency Injection Overview


The IoC Container of Swiz is the BeanProvider class. Any beans defined in a registered BeanProvider can be injected into other registered beans or into views added to the display list. Defining an injection target is done using the [Inject] metadata tag. Common injection scenarios include the following: Inject Model into View Inject Model into Controller Inject Delegate into Controller Inject Service into Delegate

Due to restrictions imposed by the AVM, Swiz cannot inject into private, protected or internal members.

By default, injections in view components happen during the ADDED_TO_STAGE event. This behavior can be modified by changing the Swiz configuration. It is important to understand that this means that injections occur after the CREATION_COMPLETE event. If you need to trigger logic during creation that depends on injections, use a [PostConstruct] method.

Inject by type
If you define exactly one bean of a given type you can inject it into a matching destination with a plain [Inject] tag. Note this also supports injecting a concrete implementation of an interface to which the destination is typed. In other words, if a property decorated with [Inject] is of type IUserService, Swiz will correctly inject a bean implementing that interface, such as UserService or MockUserService.

[Inject] public var model:IUserModel;

Best Practice You should inject by type whenever possible. It avoids reliance on string based names, which can lead to run time errors caused by misspellings.

Automatic Creation and Injection of Built-In Helper Classes If Swiz encounters an [Inject] tag for a property typed to ServiceHelper, IServiceHelper, URLRequestHelper, IURLRequestHelper, or MockDelegateHelper, and there is no matching Bean defined in a BeanProvider, Swiz will automatically create a bean of the correct type and inject it for you.

Inject by name
If you have more than one bean of a given type defined you can request that a bean with a specific name be injected. This bean name must match the id attribute of the bean's tag as defined in your BeanProvider.
[Inject( source="userService" )] public var service:RemoteObject; ... // will inject this from BeanProvider <mx:RemoteObject id="userService" />

Quick Tip "source" is the default attribute of [Inject], so the above tag could also be written as [Inject( "userService" )]

Inject bean property


Swiz can also inject public bean properties, rather than just the beans themselves using dot notation. In the following example "userModel" is the name of a bean, and we are injecting its currentUser property. As of version 1.3, you can use property chains as the source as well, i.e. userModel.currentUser.permissions.

[Inject( source="userModel.currentUser" )] public var currentUser:User;

Quick Tip If the bean property is bindable and the decorated property is public, you can have Swiz create a binding to the source property by adding bind="true" to the [Inject] tag. Note that due to bugs in the underlying Flex SDK, it is impossible to confirm that a nested property is bindable. As a result, Swiz can only bind to properties of the target object.

Two way bindings


To set up a reverse binding, so the bean property will receive updates made to the injection target, you can set the twoWay attribute of the [Inject] tag to true. This of course requires that the injection target is bindable as well.
[Bindable] [Inject( source="userModel.currentUser", twoWay="true" )] public var currentUser:User;

Setter injection
Swiz can also inject values into single argument methods. All of the attributes and policies mentioned above apply to setter injection as well, with

the exception of twoWay.


[Inject] public function setModel( model:UserModel ):void { this.model = model; }

Injection destination
Sometimes it's useful to define an injection someplace other than directly on a property/method. This is especially true in MXML views, where decorating a child component's property is not possible. Rather than creating a local variable and binding your component property to it, you can simply use the destination attribute of [Inject]. If this were defined in an MXML file, it would be wrapped in a Metadata tag.
[Inject( source="userModel.currentMode", destination="modeViewStack.selectedIndex" )]

Take care to ensure that the injection destination will be created and available by the time your injections are processed. The injection processing trigger can be configured in SwizConfig, but defaults to the ADDED_TO_STAGE event.

View Mediator and ViewNavigator


Page Contents:
View Mediator Support ViewNavigator Metadata Tag

View Mediator Support


Swiz includes two metadata tags which support the view mediator pattern. This allows references to views to be supplied to other beans. These two tags are [ViewAdded] and [ViewRemoved]. The tags have no attributes, so using them is very straightforward. [ViewAdded] and [ViewRemoved] can be specified on properties, setters or methods in beans. Swiz will pass in any instances of the type specified that it detects have been added to or removed from stage. The events that trigger these actions are those specified in your SwizConfig's setUpEventType and tearDownEventType properties. For example:

[ViewAdded] public function userListViewAdded( view : UserListView ) : void { this.view = view; } [ViewRemoved] public function userListViewRemoved( view : UserListView ) : void { this.view = null; }

The existence of these tags in a Prototype bean will not trigger the creation of that bean just because a matching view is added/removed. The bean instance containing these tags must already exist when the view event occurs.

ViewNavigator Metadata Tag


In Flex mobile projects, you can now use the [ViewNavigator] tag to get a reference to the ViewNavigator instance in non-view classes. This works in a manner similar to [ViewAdded]:

[ViewNavigator] public var viewNavigator : ViewNavigator;

Note that a ViewNavigator injection is not guaranteed to be populated by the time [PostConstruct] methods run, due to the timing around the creation of the ViewNavigator by the Flex mobile SDK.

Bean Life Cycle Management


Page Contents:
Manually Creating and Destroying Beans [PostConstruct] and [PreDestroy] SwizConfig Options Swiz and Flex Life Cycle Steps

Manually Creating and Destroying Beans


Swiz provides an event-based mechanism to create or destroy beans. To create a new bean, you can dispatch the BeanEvent.SET_UP_BEAN or BeanEvent.ADD_BEAN events:

[Dispatcher] public var dispatcher : IEventDispatcher; private function createNewBean() : void { userModel : UserModel = new UserModel(); // Swiz will create a bean for the userModel, and process any metadata in it. dispatcher.dispatchEvent( new BeanEvent( BeanEvent.SET_UP_BEAN, userModel ) ); }

Both SET_UP_BEAN and ADD_BEAN will process the target object as a bean. The difference between these events is that ADD_BEAN will also add the bean as a singleton to the BeanFactory cache, while SET_UP_BEAN does not add the new bean to the cache.

Similarly, to destroy a bean, you dispach the BeanEvent.TEAR_DOWN_BEAN or BeanEvent.REMOVE_BEAN events:

private function destroyBean() : void { // Swiz will destroy the userModel bean, clean up any injected objects, and delete any injection bindings. dispatcher.dispatchEvent( new BeanEvent( BeanEvent.TEAR_DOWN_BEAN, userModel ) ); }

The tear down events mirror the set up events discussed previously: TEAR_DOWN_BEAN cleans up the target by removing injections, event handlers, etc., while REMOVE_BEAN cleans up the bean as well as removing it from the singleton cache in the BeanFactory.

Since BeanEvent is a bubbling event, you can dispatch it from a view. If you dispatch them from non-view beans, be sure you use an injected dispatcher so that Swiz can handle the event.

If necessary, you can directly call the setUpBean() and tearDownBean() methods on the BeanFactory. Since these methods both take a Bean instance as an argument, you can use the createBeanForSource() method on the BeanFactory to generate a Bean instance that you can then pass into the set up and tear down methods. However, in general the event-based approach to creating and tearing down beans should be the preferred approach.

[PostConstruct] and [PreDestroy]


Swiz provides two metadata tags which allow you to trigger methods when any bean is set up or torn down. You can decorate a public method with [PostConstruct] and that method will be invoked by the framework after the bean has been set up, had dependencies injected, and had mediators created. For example:
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [PostConstruct] /** * [PostConstruct] methods are invoked after all dependencies are injected. */ public function createDefaultUser() : void { userService.loadDefaultUser(); } } }

Similarly, a public method decorated with [PreDestroy] will be called when a bean is destroyed by Swiz. This would happen if a UI component is removed from the stage, or a module is unloaded.
package org.swizframework.quickswiz.controller { import org.swizframework.quickswiz.service.UserService; public class UserController { [Inject] public var userService : UserService; [PreDestroy] /** * [PreDestroy] methods are invoked when a bean is destroyed. */ public function clearPollingTimer() : void { userService.stopPolling(); } } }

SwizConfig Options

Six configuration options are available in the SwizConfig object to specify how UI components are handled by the framework. These are setUpEventType, setUpEventPhase, setUpEventPriority, and the corresponding tearDownEventType, tearDownEventPhase, and tearDownEventPriority. Normally, you can leave these at their default values. But if you need to, you can modify these to alter how Swiz creates and destroys beans that are UI components. The default setUpEventType is "addedToStage". This means that whenever a UI component is added to the stage, Swiz will inspect the component and process any metadata it finds. Any dependency injections and event mediators will happen at this time. As mentioned, you may change this value if "addedToStage" is not ideal for your situation. "creationComplete" is another commonly used setUpEventType.

Be careful if you use an event type that occurs early in the Flex component life cycle, such as "preinitialize", since child components have not been created yet.

At the other end of the bean life cycle, the default tearDownEventType is "removedFromStage". This means that when a UI component is removed from the stage, Swiz will perform clean up activities such as removing event mediators. If you require even more fine-grained control, you can specify alternative values for the phase and priority used for the set up and tear down of beans. Typically, these won't need to be changed, but the options are there in case they are needed.

You can also use the ISetUpValidator and ITearDownValidator interfaces with UI components to control whether set up or tear down are allowed.

Swiz and Flex Life Cycle Steps


Note that the Flex component lifecycle events shown in all of these tables outline the most common order, but that it is not universal. For example, when a Module is loaded, it will dispatch addedToStage before dispatching creationComplete. These inconsistencies are simply how the Flex SDK operates.

The following table shows the steps that Flex and Swiz will go through on application startup: Type Flex Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Swiz Flex Flex Step Preinitialize event dispatcher set Swiz created event domain set Global dispatcher set Processors initialized Bean factory initialized setUpEvent and tearDownEvent values set from SwizConfig Beans defined in the BeanProvider(s) are processed (per bean) beanFactory.setUpBean() (per bean) [Inject] processed (per bean) [EventHandler] processed (per bean) [Dispatcher] processed (per bean) Default custom metadata processed (per bean) [PostConstruct] processed Initialize event Creation complete event

Flex Flex Flex Flex

Added to stage event Display objects in the display list are processed (see table below) Application complete event Update complete event

The following table shows the steps that Flex and Swiz will go through when a new display object is set up: Type Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Flex Swiz Swiz Swiz Swiz Swiz Swiz Swiz Flex Step Invalidation Property bindings Preinitialize Create children Initialize event Commit properties Resize Render Measure Set actual size Update display list Creation complete event Added event Added to stage event beanFactory.setUpBean() [Inject] processed [EventHandler] processed [Dispatcher] processed Default custom metadata processed [PostConstruct] processed [ViewAdded] processed Update complete event

The following table shows the steps that Flex and Swiz will go through when a display object is torn down: Type Flex Flex Swiz Swiz Swiz Swiz Step Removed event Removed from stage event [PreDestroy] processed [Inject] tear down [EventHandler] tear down [Dispatcher] tear down

Swiz Swiz

Default custom metadata tear down [ViewRemoved] processed

Event Handling
Page Contents:
Dispatching Events Handling Events with [EventHandler] Event Handling Using Class and Constant Names Event Handling Using Event Type Value [EventHandler] tag options properties attribute Other attributes Handling Multiple Events from a Single Method

Swiz offers features to assist with both the dispatching and handling of events within an application. The following sections explain these features in detail.

Dispatching Events
Application events typically fall into two categories: those dispatched from children of DisplayObject, and those dispatched from non-UI objects. Swiz makes it easy to handle both kinds of events in a standard way. Dispatching events from UI components is done using the standard dispatchEvent() method that DisplayObject provides. If you dispatch events that bubble, Swiz can listen for these events in the root container and invoke event handlers to handle these events. Dispatching events from non-UI component beans is done using an event dispatcher provided by Swiz. There are two ways to instruct Swiz to inject a dispatcher. The most common way is to use the [Dispatcher] metadata tag. Swiz will automatically inject the dispatcher into a public property decorated with this metadata.
[Dispatcher] public var dispatcher:IEventDispatcher;

The other option is to implement the Swiz IDispatcherAware interface. Since implementing this interface creates a direct dependency on the Swiz framework, it should be avoided if possible. Once the dispatcher is injected, you can use it to dispatch events that can be handled using metadata-based event handlers. Event handlers are described in the next section.

In situations where you have two or more Swiz instances in a parent/child relationship, you can exercise some additional control over how events are dispatched and handled. See the section on Module Support for more information.

Handling Events with [EventHandler]


Swiz handles application events using the [EventHandler] metadata tag (previously called [Mediate]). [EventHandler] provides several benefits: You no longer need to manually declare event listeners in your code. Swiz will transparently create an event listener for the specified event when the bean is created, and will invoke the target method whenever that event is captured. Further, Swiz will automatically remove the event listener when the bean is destroyed or removed from the display list. You no longer need event-specific handler methods to respond to events. [EventHandler] methods can be declared without specifying an Event object as a method argument (see below). As a result, you can easily invoke these methods yourself, outside the context of responding to an event, in addition to having Swiz invoke them automatically. A single method can easily respond to multiple event types. Because the methods are annotated with metadata, it is possible to introspect a class to determine what events it will respond to. This is not possible when the code manually creates event listeners. In order for an event to be handled, it must be dispatched from the Swiz dispatcher (as shown above) or be a bubbling event. [EventHandler]

tags are defined on methods and must specify the event to be handled. The event can be specified using the string value of the event's type property, or by using the class and constant names of the event.

Methods decorated with [EventHandler] must be public, since the AVM provides no mechanism for invoking non-public methods directly.

Event Handling Using Class and Constant Names

If you wish to use event constants in your [EventHandler] metadata, this is the required approach. There are two two reasons Swiz requires this. First, it allows Swiz can verify the event class exists and has a constant with the provided name. Second, it allows Swiz to process different events that have the same string literal type by matching on the class and constant name instead of the value. This syntax assumes you have a subclass of Event named UserEvent, and that you have added "com.foo.events" to the eventPackages property of SwizConfig.

[EventHandler( event="UserEvent.ADD_USER" )] public function handleAddUserEvent( event:UserEvent ):void { // do stuff }

If you do not specify any eventPackages, you can provide the fully qualified path in the [EventHandler] tag:

[EventHandler( event="com.foo.events.UserEvent.ADD_USER" )] public function handleAddUserEvent( event:UserEvent ):void { // do stuff }

Event Handling Using Event Type Value

Good for quick prototyping but lacks error checking and could suffer from collisions. Not recommended.
[EventHandler( event="addUser" )] public function handleAddUserEvent( event:UserEvent ):void { // do stuff }

[EventHandler] tag options


The examples above show methods that take the target event as an argument, but in some cases you don't need the event passed to your method. Swiz will intelligently examine the signature of your method and call it without parameters if that is how it's defined.
[EventHandler( event="UserEvent.ADD_USER" )] public function handleAddUserEvent():void { // do stuff }

properties attribute

You can also specify a comma delimited list of property names in the tag to have the matching properties pulled off of the event and passed into your method. This can be useful for allowing methods to be defined in a more semantic manner to mask the fact that they are event listeners. As

of version 1.3, you can use property chains as well, i.e. user.permissions.

[EventHandler( event="UserEvent.ADD_USER", properties="user" )] public function addUser( user:User ):void { // do stuff }

Other attributes

Since [EventHandler] causes Swiz to create an event listener behind the scenes, it also supports some related attributes. useCapture, priority, stopPropagation and stopImmediatePropagation are all supported, and Swiz will handle their implementation for you. useCapture and priority map directly to the useCapture and priority parameters of the resulting listener. Setting stopPropagation or stopImmediatePropagation to "true" will cause Swiz to automatically call the corresponding methods on the event after your method executes.

Handling Multiple Events from a Single Method


It is possible to handle multiple events using a single method:
[EventHandler( event="UserEvent.ADD_USER", properties="user" )] [EventHandler( event="UserEvent.EDIT_USER", properties="user" )] [EventHandler( event="UserEvent.DELETE_USER", properties="user" )] public function handleUserEvents( user:User ):void { // do stuff }

Additionally, you can handle any event type of a given event using a wildcard:
[EventHandler( event="UserEvent.*", properties="user" )] public function handleUserEvents( user:User ):void { // do stuff }

Service Layer
Interacting with remote services is a feature found in almost every RIA created. Because of this, Swiz has made it a priority to streamline and enhance this aspect of development. There are four primary classes you will interact with in the service layer of your Swiz application.
ServiceHelper

The ServiceHelper class is probably the most common class you will use in the service layer of your Swiz application. ServiceHelper is a class that simplifies and improves your interactions with service classes that return an AsyncToken. This includes RemoteObject, HTTPService and WebService. These services will typically be defined as beans and injected into one of your own classes. ServiceHelper's executeServiceCall() method is a concise way to call a service, define handlers for the call and specify objects to be passed to your result handler. The following example shows a simple service call as it looks when using ServiceHelper. In this example the ServiceHelper has been defined as a bean and injected, but you can instantiate your own instance if you prefer. Also notice that you are able to define an array of parameters that will be passed to the result handler when the service returns. This can be very useful for maintaining context between calls and simplifying your result handler code. The first parameter of executeServiceCall() is an AsyncToken so we simply perform the RemoteObject method call, which returns an AsyncToken, inline.

[Inject( "userService" )] public var ro:RemoteObject; [Inject] public var sh:ServiceHelper; public function fetchUserRoles( user:User ):void { sh.executeServiceCall( ro.fetchUserRoles( user.id ), fetchUserRoles_result, fetchUserRoles_fault, [ user ] ); } protected function fetchUserRoles_result( data:Object, user:User ):void { user.roles = data.result; } protected function fetchUserRoles_fault( info:Object ):void { // handle service fault }

URLRequestHelper

Remote calls that do not return an AsyncToken are generally implemented using the URLRequest and URLLoader classes. Swiz therefore provides the URLRequestHelper class, whose executeURLRequest() method works much like executeServiceCall(). The slight differences can be seen below, but can be summed up in that you do not directly create a URLLoader instance or call load() because Swiz handles those aspects for you, and there are extra (optional) handlers that can be defined.
[Inject] public var urh:URLRequestHelper; public function loadConfig( user:User ):void { urh.executeURLRequest( new URLRequest( "config.xml" ), loadConfig_result, loadConfig_fault, loadConfig_progress, loadConfig_httpStatus, [ user ] ); } protected function loadConfig_result( event:Event, user:User ):void { user.config = XML( URLLoader( event.target ).data ); } protected function loadConfig_fault( event:Event ):void { // will be called in response to an IOErrorEvent.IO_ERROR or SecurityErrorEvent.SECURITY_ERROR } protected function loadConfig_progress( event:Event ):void { // will be called in response to ProgressEvent.PROGRESS } protected function loadConfig_httpStatus( event:Event ):void { // will be called in response to HTTPStatusEvent.HTTP_STATUS }

Client Persistence

Swiz provides two ways to help with client persistence. In both Flex and AIR projects you can use the SharedObjectBean. In AIR projects, you can also use the EncryptedLocalStorageBean, which can be found in the Swiz Desktop Extensions project on GitHub. (The EncryptedLocalStorageBean is kept in a separate project to avoid having a framework dependency on the AIR libraries.)

SharedObjectBean
To use the SharedObjectBean, you simply declare it in a BeanProvider:
<swiz:BeanProvider xmlns:swiz="http://swiz.swizframework.org" xmlns:storage="org.swizframework.storage.*"> <storage:SharedObjectBean id="soBean" /> </swiz:BeanProvider>

Inject the instance into your model and declare a bindable getter/setter:
[Inject] public var so:ISharedObjectBean; [Bindable] public function get appIndex():int { // the second parameter is the initial value return so.getInt("appIndex", 0); } public function set appIndex(index:int):void { so.setInt("appIndex", index); }

Interfaces
Swiz provides several interfaces to enable manual control over certain features, or as an alternative to using certain metadata tags.

ISetUpValidator
Implementing this interface will instruct Swiz to invoke the allowSetUp() method of the bean before the bean is set up. If this method returns true, set up will proceed. If it returns false, Swiz will not set up the bean.

ITearDownValidator
Implementing this interface will instruct Swiz to invoke the allowTearDown() method of the bean before the bean is torn down. If this method returns true, tear down will proceed. If it returns false, Swiz will not tear down the bean.

ISetUpValidator and ITearDownValidator are primarily meant for use in view components, to allow specific views to opt out of set up or tear down. In these cases, the developer can manually control set up or tear down of the views.

IInitializing
Implementing this interface will instruct Swiz to invoke the afterPropertiesSet() method of the bean after the bean is set up.

IDisposable
Implementing this interface will instruct Swiz to invoke the destroy() method of the bean when the bean is destroyed

IDispatcherAware
Implementing this interface will instruct Swiz to inject an IEventDispatcher into the bean's dispatcher property when it is set up.

Best Practice In order to minimize coupling to the Swiz framework, using the [PostConstruct], [PreDestroy] and [Dispatcher] metadata tags should be favored over use of IInitializing, IDisposable and IDispatcherAware.

IBeanFactoryAware
Implementing this interface will instruct Swiz to inject the Swiz IBeanFactory into the bean's beanFactory property when it is set up.

ISwizAware
Implementing this interface will instruct Swiz to inject itself into the bean's swiz property when it is set up.

Advanced Topics
This section covers more advanced Swiz topics, such as the Chaining API and custom metadata.

AutowiredTestCase
One of the utility classes that is part of the Swiz library is AutowiredTestCase. As the name implies, you can use this class to help test your Swiz applications. Let's look at a sample FlexUnit 4 test that uses AutowiredTestCase. First, the class under test:

package org.swizframework.testapp.control { import org.swizframework.testapp.event.MyEvent; import flash.events.IEventDispatcher; public class MyController { [Dispatcher] public var dispatcher : IEventDispatcher; public var didSomething : Boolean = false; [EventHandler( event="MyEvent.CONTROLLER_ACTION_REQUESTED" )] public function handleAction() : void { didSomething = true; dispatcher.dispatchEvent( new MyEvent( MyEvent.CONTROLLER_ACTION_COMPLETE ) ); } } }

You can see this is a simple controller, which responds to the CONTROLLER_ACTION_REQUESTED event, updates a property, and then dispatches CONTROLLER_ACTION_COMPLETE. We want to test that the controller is responding to the correct event, property updating the property, and finally dispatching the completion event. The event itself is a simple event class:

package org.swizframework.testapp.event { import flash.events.Event; public class MyEvent extends Event { public static const CONTROLLER_ACTION_REQUESTED : String = "controllerActionRequested"; public static const CONTROLLER_ACTION_COMPLETE : String = "controllerActionComplete"; public function MyEvent(type:String) { super(type, true, false); } } }

Finally, the test case itself:

package { import import import import import import

org.swizframework.testapp.control org.swizframework.testapp.MyController; org.swizframework.testapp.event.MyEvent; org.flexunit.Assert; org.flexunit.async.Async; org.swizframework.core.*; org.swizframework.utils.test.AutowiredTestCase;

public class MyControllerTestCase extends AutowiredTestCase { private var myController : MyController; [Before] /** * Create the object under test, create Swiz configuration, and build the Swiz context * so that it can process the test objects as beans. */ override public function constructSwizContext() : void { myController = new MyController(); swizConfig = new SwizConfig(); swizConfig.eventPackages = "org.swizframework.testapp.event.*"; beanProviders = [new BeanProvider( [myController] )]; super.constructSwizContext(); } [After] public function cleanUp():void { myController = null; } [Test(async)] public function testControllerActionRequested() : void { Assert.assertTrue( "Controller property is already true.", myController.didSomething == false ); Async.handleEvent( this, swiz.dispatcher, MyEvent.CONTROLLER_ACTION_COMPLETE, checkEvent ); swiz.dispatcher.dispatchEvent( new MyEvent( MyEvent.CONTROLLER_ACTION_REQUESTED ) ); } private function checkEvent( event : Event, passThroughData : Object ) : void { Assert.assertTrue( "Controller property was not updated.", myController.didSomething == true ); } } }

We start off setting up an instance of Swiz that the test can use. AutowiredTestCase has a method marked with [Before] metadata, so that FlexUnit runs it before each test. Next, create an instance of the class under test (MyController), then set the event packages on the SwizConfig. Finally, we place the MyController instance into a BeanProvider, so that Swiz will process it as a bean. This way, any Swiz metadata in MyController is processed. The test method dispatches a CONTROLLER_ACTION_REQUESTED event. If all goes well, the event handler in the controller should run, update the property, and then the controller will dispatch the completion event. Running the test produces a passing result. Note that because Swiz actually processes your test case itself as a bean, you can use Swiz metadata in your test if you want or need to. So injecting a dispatcher, handling an event, or testing custom metadata processors are all possible as well.

Chaining API

Page Contents:
Chaining API Overview Provided implementations Custom implementations Automatic Asynchronous Handling in Chains Go forth and chain stuff!

Chaining API Overview


Swiz provides a simple, yet powerful and extensible API for chaining actions together. At the heart of this API are the IChain and IChainStep interfaces. Let's look at them here, starting with IChain.

public interface IChain extends IEventDispatcher { function get position():int; function set position( value:int ):void; function get isComplete():Boolean; function get stopOnError():Boolean; function set stopOnError( value:Boolean ):void; function hasNext():Boolean; function stepComplete():void; function stepError():void; function addStep( step:IChainStep ):IChain; function start():void; function doProceed():void; }

Most of the methods are self explanatory, so we'll only discuss the most important one directly. The doProceed() method is where a chain does its work. It's where EventChain dispatches events, and where CommandChain executes commands. If you clicked either of those links, you may have noticed that both chain types contain very little code other than their doProceed() implementations. This is because they both extend AbstractChain, which implements the entire IChain interface besides doProceed(). It does not actually implement IChain, however, which forces custom chain types to do so and to implement doProceed(). AbstractChain does implement IChainStep though, which means chains can be nested. Also note that chains can be run in either sequence or parallel mode, with constants defined for each in the ChainType class

public interface IChainStep { function get chain():IChain; function set chain( value:IChain ):void; function get isComplete():Boolean; function complete():void; function error():void; }

IChainStep is the base interface for objects that can be part of a chain. The methods are again pretty self explanatory, but do notice the complete() and error() methods, which correspond to the stepComplete() and stepError() methods of IChain. The last interface of the Swiz chaining API is IAutonomousChainStep.

public interface IAutonomousChainStep extends IChainStep { function doProceed():void; }

While chains will often have specific logic for executing their constituent steps, sometimes it is beneficial for a step to control its own execution. This is especially useful for constructing chains with steps of varying types.

Provided implementations
Swiz provides some useful implementations of the chaining API for you. We previously mentioned EventChain, which is exactly what it sounds like. It allows you to string together EventChainStep instances, and also supports IAutonomousChainStep instances. EventChains can be extremely useful for things like application boot strapping and making multiple remote service calls. CommandChain provides a mechanism for assembling CommandChainStep instances, as well as AsyncCommandChainStep instances (they extend CommandChainStep and implement IResponder) and implementations of IAutonomousChainStep. Here is an example of a simple EventChain that dispatches a series of events as a single unit:

public function doEventChain() : void { var eventChain : EventChain = new EventChain( dispatcher ); eventChain.addEventListener( ChainEvent.CHAIN_COMPLETE, handleChainComplete, false, 0, true ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.USER_SCREEN_ACTIVE ) ) ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.USER_PROCESSING_COMPLETE ) ) ); eventChain.start(); } [EventHandler( event="UserEvent.USER_SCREEN_ACTIVE" )] public function logUserScreenActive() : void { // perform logic or dispatch events when the user screen is active } [EventHandler( event="UserEvent.USER_PROCESSING_COMPLETE" )] public function logUserProcessingComplete() : void { // perform logic or dispatch events when the processing finishes } public function handleChainComplete( event : Event ) : void { // perform logic or dispatch events when the chain is complete }

EventChainSteps may optionally specify a dispatcher. If none is specified, the EventChain will assign its dispatcher to the EventChainStep before executing that step. FunctionChainStep is another useful class that implements IAutonomousChainStep and allows for deferred function invocation. Finally, note that BaseChainStep provides a base implementation of IChainStep, making your custom implementations that much easier to write.

Custom implementations
It is extremely easy to extend the chaining API to meet your specific needs. As mentioned above, creating a custom chain type essentially boils down to extending AbstractChain, adding "implements IChain" and then implementing the doProceed() method. Your doProceed() method could execute custom chain step types, log or otherwise audit chain progress or perform any other custom behavior you desire. A simple chain that relies on autonomous steps is shown below.

package { import import import

chains org.swizframework.utils.chain.AbstractChain; org.swizframework.utils.chain.IAutonomousChainStep; org.swizframework.utils.chain.IChain;

public class CompositeChain extends AbstractChain implements IChain { public function doProceed():void { IAutonomousChainStep( steps[ position ] ).doProceed(); } } }

Custom chain steps can be made to perform virtually any action. They will need to implement IChainStep, which is most easily done by extending BaseChainStep. If they implement IAutonomousChainStep they can be virtually self contained, and can easily be combined with other chain step types. An example of a custom chain step which sets a property on an object is shown below.

package steps { import org.swizframework.utils.chain.BaseChainStep; import org.swizframework.utils.chain.IAutonomousChainStep; public class PropertySetterStep extends BaseChainStep implements IAutonomousChainStep { public var target:Object; public var props:Object; public function PropertySetterStep( target:Object, props:Object ) { this.target = target; this.props = props; } public function doProceed():void { for( var prop:String in props ) { target[ prop ] = props[ prop ]; } complete(); } } }

Automatic Asynchronous Handling in Chains


The Event Chaining API also supports automatic asynchronous handling of chain steps. If an [EventHandler] method is called as part of an event chain, it can return an AsyncToken or IAsynchronousOperation to participate in automatic asynchronous handling. In that case, the chain that is executing will wait until the operation is complete before proceeding to the next chain step. Further, if there are multiple [EventHandler] 's for a given Event, the chain will wait until all associated asynchronous operations are complete before proceeding to the next chain step. Not all asynchronous Flash or Flex API operations return AsyncToken. Consequently, the internal logic related to asynchronous handling is based upon IAsynchronousOperation. Swiz provides three concrete implementations that adapt typical Flash / Flex asynchronous operations into IAsynchronousOperations. 1. AsyncTokenOperation - which adapts an AsyncToken. 2. AsynchronousChainOperation - which adapts an asynchronous IChain. 3. AsynchronousIOOperation - which adapts Flash or Flex API operations that signal success or failure by dispatching Event.COMPLETE / Event.CANCEL / IOEvent.IO_ERROR / SecurityErrorEvent.SECURITY_ERROR events (ex. FileReference). AsynchronousIOOperation

3. extends AbstractAsynchronousDispatcherOperation, so you can extend this abstract base class to adapt other asynchronous operations that signal their success or failure via Events if necessary.

As noted earlier, [EventHandler] methods can simply return an AsyncToken. The [EventHandler] metadata processor will automatically adapt the AsyncToken via AsyncTokenOperation.

For example, here is an event chain that will automatically wait for a service call to complete before moving on to the next step. First, we'll see the event that will be used for the asynchronous events in the chain. Note that it extends AsynchronousEvent, which is necessary to allow the event to keep track of the chain step it is associated with:

import org.swizframework.utils.async.AsynchronousEvent; /** * By extending AsynchronousEvent (or implementing IAsynchronousEvent), the event can keep track * of the chain step it is associated with. This allows the event to participate in asynchronous * event chains. */ public class UserEvent extends AsynchronousEvent { public static const LOAD_USER : String = "UserEvent.LOAD_USER"; public static const LOAD_USER_IMAGE : String = "UserEvent.LOAD_USER_IMAGE"; public static const USER_PROCESSING_COMPLETE : String = "UserEvent.USER_PROCESSING_COMPLETE"; public function UserEvent( type : String ) { super( type, true, false ); } }

And then the code that actually builds up the chain and starts the processing:

public function doAsyncChain() : void { var eventChain : EventChain = new EventChain( dispatcher ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.LOAD_USER ) ) ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.USER_PROCESSING_COMPLETE ) ) ); eventChain.start(); } [EventHandler( event="UserEvent.LOAD_USER" )] /** * Since this event handler method returns an AsyncToken, Swiz automatically knows that * if the method runs as part of an event chain, it should wait until the asyncronous call * completes before proceeding to the next chain step. */ public function loadUser() : AsyncToken { return serviceHelper.executeServiceCall( service.loadUser(), handleUserLoadResult ); } private function handleUserLoadResult( event : ResultEvent ) : void { // process the result } [EventHandler( event="UserEvent.USER_PROCESSING_COMPLETE " ) public function userProcessingComplete() : void { // perform logic or dispatch events when the processing finishes }

As another example, a URL request is adapted via AsynchronousIOOperation to allow Swiz to wait for completion before the chain proceeds:

public function doURLRequestChain() : void { var eventChain : EventChain = new EventChain( dispatcher ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.LOAD_USER_IMAGE ) ) ); eventChain.addStep( new EventChainStep( new UserEvent( UserEvent.USER_PROCESSING_COMPLETE ) ) ); eventChain.start(); } [EventHandler( event="UserEvent.LOAD_USER_IMAGE" )] /** * Load an image. Since this event handler method returns an IAsynchronousOperation, * Swiz automatically knows that if the method runs as part of an event chain, it should wait * until the operation completes before proceeding to the next chain step. */ public function loadUserImage( event : UserEvent ) : IAsynchronousOperation { var request : URLRequest = new URLRequest( targetImagePath ); var loader : URLLoader = urlRequestHelper.executeURLRequest( request, handleUserImageResult ); return new AsynchronousIOOperation( loader ); } private function handleUserImageResult( event : Event ) : void { // process the result } [EventHandler( event="UserEvent.USER_PROCESSING_COMPLETE " ) public function userProcessingComplete() : void { // perform logic or dispatch events when the processing finishes }

An [EventHandler] method can also construct an asynchronous chain and return that chain as an operation (adapting it via AsynchronousChainOperation). In that case, the original EventChainStep will not proceed until the entire child chain is complete.

Go forth and chain stuff!


Hopefully this page has shown you the ease, power and extensibility of the Swiz chaining API. If you have questions or comments about the API or any of the built in implementations, or even just ideas you'd like to discuss, please head over to the mailing list and we'll be happy to help!

Custom Metadata Processors


Custom metadata processors are one of the most powerful and interesting features Swiz has to offer. This page contains links to custom processors created by the community, as well as instructions on how to create your own custom metadata processor.

Created by the community


[URLMapping] - Deep linking made crazy easy [MediateSignal] - Mediate AS3 Signals like you would events [Resource] - Simplified localization coding [Logger] - Simplified logging [Bind] - Binding for the Flight framework via metadata [MediateView] - Passes view components into beans by type or ID. Note that Swiz now supports view mediation with [the {{\[ViewAdded\]}} and {{\[ViewRemoved\]}} metadata tags]. However, this custom processor may still be useful for learning to create your own custom processors.

Creating your own


Coming soon

Module Support
Parent and Child Swiz Instances
Swiz supports the concept of parent and child instances. Typically, this capability is used in conjunction with Modules. When you load a module that contains a Swiz instance as a child of another Swiz-based application, the framework will create a parent-child relationship between these two instances of Swiz. This happens automatically, meaning that the developer should not have to do any manual setup or configuration to use this feature. There is a sample application that demonstrates how Swiz can work with Modules at the Github repository. Here is a graphical representation of how the module support works and what capabilities it offers:

The one main issue that developers encounter related to module support has to do with Swiz metadata-based event handling. The [EventHandler] metadata tag only contains a string value representing the event class and constant name. As a result, when Swiz attempts to validate the event, you will receive an error if that event class was not compiled into the Module. This is because Swiz cannot locate the event class in the ApplicationDomain. The developer must ensure that event classes defined outside of the module are included in the compiled module. In practice, this simply means adding a variable declaration somewhere that is typed to that event. As long as an actual reference to the event type exists somewhere within the module, that class will be compiled into the module. This allows Swiz to locate the class reference and validate the event constants. Note that this is not actually a Swiz-specific issue. The compiler only includes classes that are actually referenced in an application; all others are discarded for optimization purposes.

The Local and Global Scopes

Swiz offers some additional control over how events are dispatched and handled between parent and child Swiz instances. Most developers will probably never need to concern themselves with this fine-grained control, but it is described here for the cases where it is desired. The [Dispatcher] and [EventHandler] metadata tags allow for an optional attribute called scope, which can be set to "local" or "global". The default value for both of these attributes is "global". If a [Dispatcher] metadata tag specifies scope="local", the dispatcher for that Swiz instance is injected. When scope="global" is specified, the dispatcher for the top-level Swiz instance is injected. Similarly, if an [EventHandler] metadata tag specifies scope="local", only events dispatched through the local dispatcher are handled by the decorated method. When scope="global" is specified, events dispatched through the global dispatcher are handled. Since this may make more sense when visualized, here is a graphic depicting the local and global scopes:

Support for the Command pattern


Swiz supports the use of the Command pattern with the CommandMap class, which you then register as a bean. The first step is to extend CommandMap and override the mapCommands() method. Inside the method you make individual calls to mapCommand(), which maps an event to a command class. In the example below, the first two arguments are pretty self explanatory. They are the event type and the command you want to be triggered by that type. The third and fourth arguments are optional, but can be very useful. The third argument is the event class associated with the event type, and when provided allows Swiz to prevent event type collisions. What this means is that if MyEvent.OPEN and YourEvent.OPEN both evaluate to "open", providing MyEvent as the third argument will instruct Swiz to only execute MyCommand in response to MyEvent.OPEN. This argument is optional but recommended. The fourth argument is oneTime:Boolean = false. If you set this argument to true, Swiz will remove the mapping after the first time the command is executed. This can be useful for activities you know will only happen once, like configuration loading or other bootstrapping activities.
public class MyCommandMap extends CommandMap { override protected function mapCommands() : void { mapCommand( MyEvent.OPEN, MyCommand, MyEvent, false ); } }

Finally, add your CommandMap to one of your BeanProviders. It is not necessary to register your Command classes as beans. Their presence in the mappings is all the information Swiz needs.
<swiz:BeanProvider> <command:MyCommandMap id="myCommandMap" /> </swiz:BeanProvider>

The commands you register must implement one of two interfaces provided by Swiz. ICommand is the base interface, simply defining an execute() method.

public interface ICommand { function execute():void; }

If your Command needs access to the event that triggered it, simply implement IEventAwareCommand. Notice IEventAwareCommand extends ICommand.

public interface IEventAwareCommand extends ICommand { function set event( value:Event ):void; }

As always, make sure you've added the correct event package containing your event to the Swiz eventPackages array and that's all there is to it. Any time Swiz handles an event, the associated command(s) will be executed.

Best Practices
This section will contain a collection of Swiz best practices that will be updated on an ongoing basis.

Presentation Model
The presentation model (PM) approach is the recommended view layer architecture for Swiz. The goal is to remove any logic from the view and let the PM handle the view logic. The PM has to be declared in the BeanProvider and the recommended way is to declare it as a Prototype so the PM will only be created (instantiated) when the corresponding view is added to the stage.
<?xml version="1.0" encoding="utf-8"?> <swiz:BeanProvider xmlns:swiz="http://swiz.swizframework.org" xmlns:fx="http://ns.adobe.com/mxml/2009"> <fx:Script> <![CDATA[ import example.model.presentation.MyPresentationModel; ]]> </fx:Script> <swiz:Prototype type="{MyPresentationModel}" /> </swiz:BeanProvider>

The view gets the PM injected and binds data from it and delegates all interactions (events) to the PM.

<?xml version="1.0" encoding="utf-8"?> <s:SkinnableContainer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" currentState="{model.currentState}"> <fx:Script> <![CDATA[ import example.model.presentation.MyPresentationModel; [Bindable] [Inject] public var model:MyPresentationModel; [PreDestroy] public function cleanUp():void { model.destroy(); } ]]> </fx:Script> <s:layout> <s:VerticalLayout /> </s:layout> <s:states> <s:State name="default" /> <s:State name="detail" /> </s:states> <s:List labelField="{model.listLabelField}" dataProvider="{model.dataProvider}" change="model.changeListIndex(event.newIndex)" /> <s:Label includeIn="detail" text="{model.selectedItem.title}" /> <s:Button includeIn="detail" label="Edit" click="model.edit()" /> </s:SkinnableContainer>

The PM is a independent unit and only gets data injected from the application layer.

package example.model.presentation { import flash.events.IEventDispatcher; import org.swizframework.events.BeanEvent; public class MyPresentationModel { [Dispatcher] public var dispatcher:IEventDispatcher; [Bindable] public var currentState:String; [Bindable] [Inject("appModel.list")] public var dataProvider:IList; [Bindable] public var selectedItem:Object; public function MyPresentationModel() { } public function changeListIndex(index:int):void { if(index != -1){ currentState = "edit"; selectedItem = dataProvider.getItemAt(index); }else{ currentState = "default"; selectedItem = null; } } public function edit():void { dispatcher.dispatchEvent(new MyEvent(MyEvent.EDIT, selectedItem)); } public function destroy():void { dispatcher.dispatchEvent( new BeanEvent( BeanEvent.TEAR_DOWN_BEAN, this ) ); } } }

Having no logic in the view itself also means that you only have to unit test your PM.

Examples
The swiz-examples repository on Github contains a number of examples. These include the Quick Start app, examples of Module integration, the Chaining API, and more. We'll keep adding more over time, too!

Release Notes
v1.3.1 Release Notes
Fixed [ViewNavigator] metadata missing from swc - The new [ViewNavigator] metadata tag was missing from the library's

-keep-as3-metadata. This has been added.

v1.3.0 Release Notes


Fixed namespace prefix for MXML declarations - Added design.xml and cleaned up manifest.xml to ensure newer versions of Flash Builder create the swiz namespace prefix correctly. Enabled binding to deeply nested bean properties - The [Inject] tag now supports binding to nested properties using syntax like [Inject( "myModel.someObject.someProperty", bind="true" )]. It is the developer's responsibility to ensure that the chain of properties is in fact bindable. Added support for nested properties in [EventHandler]'s properties attribute - You can now have Swiz pass nested properties into a method decorated with [EventHandler]. Syntax uses dot notation as expected. Added new [ViewNavigator] tag - In Flex mobile projects, you can now use the [ViewNavigator] tag to get a reference to the ViewNavigator instance in non-view classes. Note this is not guaranteed to be populated by the time [PostConstruct] methods run. Various bug fixes and improvements - CommandMap, module teardown and other aspects have all been improved. For a complete list of changes made for this release see this compare view.

v1.2.0 Release Notes


Mobile, Spark only and Flex 3 support - After sorting out some issues with which SDKs support which versions of modules, we have a new set of SWCs. The primary SWC, swiz-framework-{VERSION_NUMBER}.swc, is intended for use in Flex 4 (or plain AS3 using mxmlc 4+) and beyond, including mobile projects. swiz-framework-{VERSION_NUMBER}-flex3.swc is for use with Flex 3 (or plain AS3 projects compiled with mxmlc 3). The need to produce multiple SWCs is unfortunate, and is caused by the fact that Adobe botched the compatibility interface intended to bridge the gap between Flex 3 modules and Flex 4 modules. If you'd like them to fix this, please vote for this bug. https://bugs.adobe.com/jira/browse/SDK-29336 [ViewAdded] and [ViewRemoved] - Support for these tags has been added as an official and more performant way to implement the view mediator pattern. They can be added to properties, setters or methods in beans, and Swiz will pass in any instances of the type specified that it detects have been added to or removed from stage. The events that trigger these actions are those specified in your SwizConfig's setUpEventType and tearDownEventType properties. Note that the existence of these tags in a Prototype bean will not trigger the creation of that bean just because a matching view is added/removed. The bean instance containing these tags must already exist when the view event occurs. Bug fixes - SWIZ-55, a regression introduced in the v1.1.0 release was fixed, allowing the tear down of non-singleton Prototype beans, and SWIZ-56 (compile error in 4.5 SDK projects due to the MX Module class not implementing IModule, see Flex SDK bug referenced above). Build script tweak - The build script has been updated to compile against the Flex SDK specified in build.properties by default. If you are compiling Swiz yourself and want to compile against the SDK specified in your FLEX_HOME environment variable, simply uncomment the appropriate line in build.xml. For a complete list of changes made for this release see this compare view.

v1.1.0 Release Notes


Mobile support - Now also producing a SWC for use in Flex mobile projects! It's the same Swiz you know and love, we've just removed any references to Module, since it doesn't exist in the mobile SDK. Bug fixes - SWIZ-39, SWIZ-46, SWIZ-47, SWIZ-50 and SWIZ-53, as well as various unreported bugs were fixed. CommandMap improvement - Multiple commands can now be mapped to a single event type. Metadata auto completion - Added a metadata.xml file for Flash Builder 4.5's metadata auto completion feature. Various improvements - API refinement, code cleanup and other minor improvements. For a complete list of changes made for this release see this compare view.

v1.0.0 Release Notes


[Mediate] is now [EventHandler] - To better communicate the intention of the tag and in an effort to standardize AS3 DI metadata, [Mediate] has been deprecated in favor of [EventHandler]. The syntax and supported attributes are identical, and [Mediate] is still supported for backwards compatibility, but [EventHandler] is now preferred. Spring ActionScript has always used [EventHandler] for this purpose. Smart view tear down - Some actions in an application, like state changes or a container's addition or removal of scrollbars, can cause a view to be temporarily removed from the display list. Swiz now waits a single frame before tearing down views to avoid incidental tear downs caused by the events described previously.

ISetUpValidator and ITearDownValidator - These interfaces declare allowSetUp():Boolean and allowTearDown():Boolean methods, respectively. Implementing one or both will allow your class to opt out of the automatic set up and/or tear down (by returning false) that is configured for the rest of your application. If you want to opt back in, simply have your class return true for the appropriate method. Implicit helper class injections - If an [Inject] tag is declared requesting an IServiceHelper, ServiceHelper, IURLRequestHelper, URLRequestHelper, or MockDelegateHelper by type, Swiz will automatically create beans for the helper classes. As a user you do not need to declare the helper classes as beans. ServiceHelper::executeServiceCall() now returns the AsyncToken - Behind the scenes, executeServiceCall() creates and uses an instance of AsyncToken to wire up your result and fault handlers. This AsyncToken is now returned from the method in order to allow additional usage as needed. URLRequestHelper::executeURLRequest() now returns the URLLoader it creates - Similar to the executeServiceCall() change, Swiz now returns the URLLoader instance it uses in case you need to interact with it. URLRequestHelper now supports extra handlerArgs - All handler methods specified will receive the same handlerArgs provided to executeURLRequest(). BeanEvent refinements - BeanEvent now has four distinct types: ADD_BEAN, REMOVE_BEAN, SET_UP_BEAN and TEAR_DOWN_BEAN. ADD_BEAN will not only set up the attached object (as SET_UP_BEAN does), it will also make it available as a bean to be injected elsewhere. REMOVE_BEAN is the corresponding type, causing the attached object to be both torn down and removed from the list of available beans. Smarter [EventHandler] - The Flash Player's event listening system is, at its core, based on strings. This means that event listeners can sometimes collide if the event types they are listening for have the same string value. However, if you use the class based syntax for [EventHandler] (or [Mediate]), Swiz will now prevent these collisions. So if you have [EventHandler( "FooEvent.FOO" )] on one method and [EventHandler( "BarEvent.FOO" )] on another, Swiz will call the correct one based on the actual type of the event instance, even if both evaluate to "foo". Sweet! Better workflow for overriding processors - Needing to override the default processors for tags like [Inject], [PostConstruct] and the others is extremely rare. At the same time, we weren't happy with the cumbersome workflow for doing so. The process has been improved to simply use processor priorities as a unique list. If you provide a custom processor whose priority matches a built-in processor's, Swiz will replace the built-in processor with your own. Chaining API enhancements - This is perhaps the most significant and exciting change since the RC2 release. See the wiki for more info. http://swizframework.jira.com/wiki/display/SWIZ/Chaining+API Miscellaneous optimizations and bug fixes - There have also been countless refinements, optimizations and bug fixes in order to ensure this is a fast, solid framework. Check it out and let us know what you think! For a complete list of changes made for this release see this compare view.

v1.0.0-RC2 Release Notes


Automatic Swiz tear down - When the dispatcher for a Swiz instance is torn down, the Swiz instance itself will automatically be torn down as well, performing all necessary cleanup for the objects it manages. Practically speaking, this means that when you define a Swiz instance within a module or child view, simply removing it from the display list will cause Swiz to clean up the instance for you. Performance and Memory improvements - We made it so Swiz's reflection system only captures and stores the metadata references it cares about. In many cases this has the effect of reducing the memory footprint of the reflection system by as much as 90%! IServiceHelper and IURLRequestHelper - We took some good advice from the community and created IServiceHelper and IURLRequestHelper interfaces. Aside from just being good form, this will increase the testability of classes that use these helpers by allowing stub implementations to be provided under test. ServiceHelper improvements - We also improved ServiceHelper by extending the ability to have extra arguments passed to your handler to include fault handlers. Result handlers have always had this ability and it can be extremely useful. Just like with result handlers, Swiz detects this automatically based on your method signature. Lastly, ServiceHelper::executeServiceCall() now returns the ASyncToken that is passed into the method. Chaining API refinements - The Chaining API has been cleaned up to be more consistent and better support chain nesting. This is a very powerful API with near limitless possibilities. For a great (brief) introduction, see http://www.riaspace.com/2010/08/swiz-1-0-chaining-api-explained/ Miscellaneous bug fixes - We fixed some minor issues with the tear down of pop ups and two way bindings, as well as other small improvements. Metadata processor ordering - Metadata processors (both built-in and custom) are now sorted in descending order by their priority to more closely match the way event listener priorities work. We also tweaked the order of our built-in processors so that [PreDestroy] methods will actually run before an object's injections have been cleared. CommandMap - Swiz now provides official, built-in support for the Command pattern! CommandMap is a new class that can be extended and dropped right into a BeanProvider. From the commit message: "Added CommandMap functionality to ease migration from frameworks like Cairngorm, and to accommodate developers/teams that may prefer the Command pattern. Our implementation borrows

heavily from Robotlegs (robotlegs.org), because their implementation was clean and in line with our goals." Look for a blog post soon showing how to use this new feature! IBeanFactory cleaned up - BeanFactory is really the heart of Swiz. It is responsible for boot strapping Swiz instances and generally managing the IoC container. We have cleaned up its IBeanFactory interface to be more consistent and predictable. BeanEvent additions - Related to the IBeanFactory upgrades, we have improved BeanEvent as well. BeanEvent has been around for a while, with constants for SET_UP_BEAN and REMOVE_BEAN. Dispatching a BeanEvent with one of these types and an object instance attached would, respectively, set up (provide the dependencies and process the metadata declared by the object) or tear down (clear out the injected dependencies) the object. Part of the IBeanFactory improvements, however, were the distinctions between bean set up and tear down, and bean addition and removal. Adding a bean makes it available for injection into other objects, removing it makes it unavailable for injection. In order to allow all of these actions to be triggered by an event, we've added ADD_BEAN and REMOVE_BEAN to BeanEvent. One last note is that adding a bean will also set up that bean, but the opposite is not true; you can set up an object without making it available for others to inject. On the other end of the lifecycle, removing a bean will always tear the bean down, but tearing down does not imply removal. Among other reasons, this is because views may be removed from the stage and re-added, causing them to be torn down and then set up again. For a complete list of changes made for this release see this compare view.

v1.0.0-RC1 Release Notes


[Dispatcher], IDispatcherAware - You get a reference to the Swiz dispatcher either by decorating a property of type IEventDispatcher with [Dispatcher] or by implementing the IDispatcherAware interface. When using [Dispatcher] you can provide a scope attribute and give it a value of either "global" or "local". Global is the default and will provide you the shared dispatcher from the root Swiz instance. Local will give you the shared dispatcher from the Swiz instance that directly contains your object. Using the local dispatcher allows you to confine events to a child Swiz instance, such as within a module. scope attribute on [Mediate] - Directly corresponds to the dispatchers discussed in the point above. This allows you to mediate events dispatched either by the local shared dispatcher or by the root dispatcher. SourceMate config file - SourceMate is a great plug-in for FlashBuilder, and one of its features is metadata code completion. We have provided a config file you can import to automatically get this feature for all supported Swiz tags. It can be found at http://github.com/swiz/swiz-framework/blob/master/misc/SwizMetadataSourceMateConfig.xml injectionEvent -> setUpEventType, etc. - The event handlers that Swiz uses to set up and tear down your views is now completely configurable. setUpEventType, setUpEventPhase, setUpEventPriority, tearDownEventType, tearDownEventPhase and tearDownEventPriority directly correspond to the values used in the listener creation by Swiz. [PreDestroy] and IDisposable - You can use these to define code that should be run when tearing down your views such as cleaning up listeners or setting references to null. Note that this is called in response to the event specified by tearDownEventType, so when using the default of removedFromStage, your view will already be off of the display list by the time these methods are called. IInitializing.init -> IInitializing.afterPropertiesSet() - To avoid conflict with UIComponent's method of the same name and to stay more consistent with Spring, the init() method of IInitializing has been changed to afterPropertiesSet(). Ant build - Full Ant build support! Custom namespaces - This is pretty sweet. Swiz can now address code defined in custom namespaces automatically. If you cringe at having to make properties and methods public this feature is for you. Note that due to Flash Player restrictions we still cannot reach protected or private members, but we feel this is a really good compromise. Also note that Flex is not able to bind to non-public members. Module and child Swiz support - You can now define child Swiz instances. This is very useful for modules, or potentially even deep dark views that users may never open in your application. When a Swiz instance is created it will dispatch a bubbling event from its host view component that will be caught by a parent Swiz instance further up the display list. A parent/child relationship is then established, allowing the child to inherit beans and configuration settings from its parent. AIR window support - Support for separate native windows in AIR has been restored. To make this work you call swizInstance.registerWindow( myNewWindow ) before opening the window via myNewWindow.open(). This will allow Swiz to manage the window and its descendant views, and works by creating a Swiz instance inside the window and making swizInstance its parent. View injection changes - Mediate now supports useCapture, which can be useful when using the mediator or passive view pattern. See http://www.webappsolution.com/wordpress/2010/04/20/swiz-10-rc1-removes-autowire-viewtrue-requires-new-abstractviewmediator/ for more info. Removed Outject - This turned out to be a bad idea so we yanked it. Util classes renamed to helpers - ServiceRequestUtil and URLRequestUtil have been renamed to ServiceHelper and URLRequestHelper, respectively. Chain API changes/updates - The chaining API has been cleaned up and made more consistent. IAutonomousChainStep has been added, which is an interface you can use to define steps that can execute themselves. The built in CommandChain and EventChain classes include support for these kinds of steps. BeanEvent - BeanEvents can be used to manually control the injection and tear down phases for views and objects you attach to the

event. Dispatching BeanEvent.SET_UP_BEAN will trigger Swiz to pass an object through it's injection and mediator processors. Dispatching BeanEvent.TEAR_DOWN_BEAN will trigger Swiz to remove any mediators and injection bindings it has created. Removed setUpMarkerFunction - We briefly provided a way for users to determine whether or not a view should be wired up. This has been removed so that a proper, more robust API can be implemented in the future. [Inject( bind="false" )] - Previously, when injecting bean properties with a tag like [Inject( "myModel.someProp" )], Swiz would create a binding if the source property was bindable. We have changed the default behavior so to make you choose to create bindings if you need them. To make Swiz to create a binding for you, you must set bind to true in the metadata tag. [Inject( "myModel.someProp", bind="true" )]. In general, using Inject with bindings should be treated carefully. We would like to discourage it's overuse, particularly in situations where users are creating global variables for their applications through the Inject tag. For a complete list of changes made for this release see this compare view.

IDE Support
The SourceMate 3.0 plugin for Flash Builder adds a large number of extremely useful capabilities to Flash Builder. One of these is excellent IDE integration for the Swiz framework. Here are a few of the great features that SourceMate offers when building Swiz applications in Flash Builder.

Configuration
To start with, it provides a Swiz-specific menu for doing common things like configuring Swiz projects and creating new Beans: Swiz Menu

Swiz project configuration can usually be automatically detected. For cases where a project has an unusual setup, information can be specified manually as well: Swiz Configuration

Content Assist for Injections and Event Handlers


Once a Swiz project is configured, code-hinting is available to create injections and event handlers. For example, if you type "bean" and trigger content assist (Control-Space or Command-Space), you will be presented with a list of all of the Beans in your BeanProviders: Bean Content Assist

Choosing a bean and hitting enter will automatically generate a public property with the relevant [Inject] tag. Similarly, if you type "handle" and trigger content assist, you are presented with a list of the events declared in your event packages: EventHandler Content Assist

Selecting an event and hitting enter will prompt you to decide whether you want to pass the event itself to the event handler method, or pass specific event properties: EventHandler Content Assist (Properties)

Finally, the [EventHandler] tag and handler method are generated automatically, including any selected event properties that you wish to pass: EventHandler Content Assist Code

Beans View
The Beans in use by a project can be quickly shown via the Swiz Beans view: Bean List with Injections

Notice that in addition to listing the Beans, this view also shows you exactly where each of the Beans is injected into other classes.

Events View
A similar view is available to view the events in use by your Swiz application: Event List with EventHandlers

Again, notice that in addition to showing the events, it lists each event type along with the location of all [EventHandler] metadata which references that event type. This is extremely handy for tracing event flow through an application.

Wrapping Up
The SourceMate team has done a great job with this support for Swiz, and has been very receptive to feedback. We hope that as more people use the tool and take advantage of its Swiz support, even more cool features will be added in the future. They have a free trial, so kick the tires and test out the Swiz support yourself (along with the impressive list of non-Swiz enhancements that SourceMate brings to Flash Builder).

External Community Resources


Blog Posts and Tutorials
Swiz blog category at briankotek.com Swiz blog category at flex-blog.com A look at a URLMapping custom metadata processor

Example Applications or Extensions


The Swiz Debug Console provides runtime introspection of a Swiz application, including logging, Beans, event flow, wired views, and more. foomonger's metadata processors, inlcuding MediateSignal and Logger

Migration Guide
Tips for migrating from earlier versions

Updating a Swiz 0.6.4 application to Swiz 1.0


Updating a Swiz 0.6.4 application to Swiz 1.0 will require the following changes:

Update configuration and creation of Swiz


Prior to 1.0, there was only one instance of Swiz. 1.0 now allows for multiple versions of Swiz, primarily to support modules and separate AIR windows. As a result, the creation of Swiz within the application will need to be modified. In a 0.6.4 application, Swiz was created like this:

<swiz:SwizConfig strict="true" mediateBubbledEvents="true" eventPackages="myapp.event" viewPackages="myapp.view" beanLoaders="{[Beans]}" />

In Swiz 1.0, this would look like:


<swiz:Swiz beanProviders="{[Beans]}"> <swiz:config> <swiz:SwizConfig eventPackages="myapp.event" viewPackages="myapp.view" /> </swiz:config> </swiz:Swiz>

You might also note that several of the properties on Swiz have changed: the strict property has been renamed validateEventTypes, and now defaults to true so in most cases it can be removed mediateBubbledEvents has been removed since Swiz 1.0 mediates bubbled events automatically the beanLoaders property has been renamed to beanProviders, and has been moved to the Swiz class the eventPackages and viewPackages now accept package paths in both the format myapp.events and myapp.events.*. Note that you still need to specify child packages separately even if you use the .* syntax. the injectionEvent property has been renamed setUpEventType, and now defaults to Event.ADDED_TO_STAGE instead of Event.PREINITIALIZE Full details on configuration and the default values for 1.0 can be found in the Configuration section. The BeanLoader class has been deprecated in favor of BeanProvider. BeanLoader will still work in 1.0, but it is recommended that you update your code to BeanProvider. In addition, a central dispatcher property was available within BeanLoader in 0.6.4. This property has been removed in 1.0. If a bean or prototype bean requires a dispatcher from Swiz, this is now accomplished using the [Dispatcher] metadata tag:

[Dispatcher] public var dispatcher:IEventDispatcher;

Removal of static methods


Since an application can now contain multiple instances of Swiz, the static methods on the Swiz class had to be removed. This means that code relying on static methods such as Swiz.dispatchEvent() must be modified. In 1.0, event dispatching typically uses a dispatcher injected using the [Dispatcher] metadata tag. This approach causes much less coupling to Swiz and results in a more flexible application. Full details on the event handling capabilities can be found in the Event Handling section.

Other changes
the [Autowire] metadata tag has been deprecated in favor of [Inject]. [Autowire] will still function in 1.0 but it is recommended that you update your code to use [Inject].

How To Contribute to Swiz


How to contribute bug fixes and new features
If you are updating the current version:
The easiest way to contribute to Swiz is to commit your changes via Git. Just create your own fork of the develop branch. Alternatively, you can

create individual patches in Git to target specific bugs. If you've gone the route of updating a fork (recommended), all you need to do is submit a pull request via GitHub. The next step is to let us know by sending the following information to the Swiz team: URL for your forked repository / or Git patch Detailed description of your intent What did you do? Why did you do it? Test Cases / Unit Tests - While test cases are optional but they will assist in getting your changes committed. If you provide unit tests, you're awesome.

If you are updating a version prior to 1.0:


Please don't. But if you must, you should use Subversion (SVN) to create a patch. Unfortunately, we can't guarantee patches for pre-1.0 versions will be accepted.

How to contribute documentation


If you've written a blog entry or recorded a presentation that you think would be helpful for the Swiz community, let us know. We can add the content to the wiki, merge it into the official Swiz documentation or just promote it.

Presentations
Space to house slide decks and notes from any Swiz presentations given at conferences, user groups, etc. BFlex - October 25, 2009 - Ben Clinkinbeard 360Flex BOF - March 8, 2010 - Snke Rohde & John Yanarella cf.Objective() - April 23, 2010 - Brian Kotek

FAQ
Is there a mailing list where I can get help from the Swiz community? If I am exporting a release build for a Swiz project, what compiler arguments do I need to retain the custom metadata? If I am building the Swiz framework from the source code, what compiler arguments do I need? I try to access my injected property during creationComplete but the reference is still null? What versions of Flex are supported for Swiz? Does Swiz work with Adobe AIR? I have dispatched an event from a view but the [EventHandler] is not invoked? How can I cause a Prototype bean to be destroyed when a view is destroyed? Why aren't new PopUp or AIR windows processed by Swiz (especially if created from within a Module)? Why aren't bubbling events dispatched from a PopUp handled by Swiz? Where is my application logic starting point? How should I dispatch events from bean classes? Why did my view not get injections processed? I defined a WebService object in my Beans.mxml, but my web service calls don't seem to work. What's wrong? Why do I get an error when using Swiz in a Flash Builder project when I use Design View?

Is there a mailing list where I can get help from the Swiz community?
Absolutely, you can find the Swiz group at http://groups.google.com/group/swiz-framework.

If I am exporting a release build for a Swiz project, what compiler arguments do I need to retain the custom metadata?
Because the Swiz swc is built with arguments to instruct the compiler to retain the Swiz metadata, you shouldn't normally need to do this yourself. However, if the metadata isn't retained for some reason, you can add this to the compiler arguments for your project:

-keep-as3-metadata+=Inject,Autowire,EventHandler,Mediate,Dispatcher,PostConstruct,PreDestroy,ViewAdded,ViewRemoved,View

If I am building the Swiz framework from the source code, what compiler arguments do I need?

-keep-as3-metadata+=Inject,Autowire,EventHandler,Mediate,Dispatcher,PostConstruct,PreDestroy,ViewAdded,ViewRemoved,View http://swiz.swizframework.org manifest.xml -include-namespaces http://swiz.swizframework.org -define+=CONFIG::flex4,true -define+=CONFIG::flex3,false

When compiling for the Flex 3.x SDK, use -define+=CONFIG::flex4,false -define+=CONFIG::flex3,true. Be sure you only compile the /src directory into the library. Trying to compile the other packages, such as /tests, will result in library compile errors. You will also want to mark the metadata.xml and manifest.xml files as Assets in your Build Path panel. Lastly, using the Ant build script will take care of all of these things for you, so that is the easiest way to build Swiz from source.

I try to access my injected property during creationComplete but the reference is still null?
Swiz injects dependencies when the view's addedToStage event is dispatched, which is after creationComplete. Inject to a setter function to have direct access to the injected reference, or move your logic into a method decorated with [PostConstruct].

What versions of Flex are supported for Swiz?


Swiz works with Flex SDK 2, 3, 4 and 4.5. Flash Builder 4.5 added code completion for Swiz metadata!

Does Swiz work with Adobe AIR?


Yes, there is in general no difference between Web or AIR development. An additional Desktop Extensions library is available to add desktop-specific features.

I have dispatched an event from a view but the [EventHandler] is not invoked?
Ensure that the event handler method is public, and that the bubbles property of the event is true.

How can I cause a Prototype bean to be destroyed when a view is destroyed?


Swiz can't know what else you may have done with the Prototype, so it is not automatically torn down. If you wish to tear down a Prototype bean when a view is removed, implement a [PreDestroy] method and dispatch a TEAR_DOWN_BEAN event for the Prototype bean.

Why aren't new PopUp or AIR windows processed by Swiz (especially if created from within a Module)?
Because PopUps and NativeWindows are not part of the standard display list, Swiz has no way to know which Swiz instance is the owner of the window. To deal with this, you can have the class that creates the window implement ISwizAware. Once you have the correct Swiz instance injected, you can call the registerWindow() method on that Swiz instance to associate that window with the specified instance of Swiz. The window can then be processed correctly.

Why aren't bubbling events dispatched from a PopUp handled by Swiz?


Swiz uses the display object where it was created as its "root event dispatcher", and it listens for events on that event dispatcher. However, PopUps are not added to this display list, they are added as direct children of the SystemManager object, since they must appear above everything else in the application. As a result, events dispatched from PopUps don't bubble up to the Swiz dispatcher. However, the solution to this is simple: just use [Dispatcher] to inject the Swiz dispatcher into your PopUp, and dispatch events through it. This way, Swiz can process them.

Where is my application logic starting point?


If your startup logic only involves one bean, let that bean (probably a "main controller") implement IInitializingBean, or decorate a method with [PostConstruct], and start with your application logic in that method. Swiz calls these methods on beans when the injection process is complete. If your startup logic depends on events that must be handled by other beans, you need to be sure that all of your beans have been properly set

up. In this case, you can use an event handler method such as [EventHandler( "mx.events.FlexEvent.APPLICATION_COMPLETE" )]. This will mediate the applicationComplete event, and only kick off processing once all of the beans have been set up.

How should I dispatch events from bean classes?


You should inject a dispatcher using the [Dispatcher] metadata, and dispatch application events through this dispatcher.

Why did my view not get injections processed?


Be sure that the viewPackages in the SwizConfig tag are set correctly.

I defined a WebService object in my Beans.mxml, but my web service calls don't seem to work. What's wrong?
The Flex WebService class actually has two implementations, one for MXML and one for AS3. If you define a WebService within a UIComponent, the Flex framework automatically triggers a load of the web service's WSDL in the UIComponent's creationComplete() handler. However, the AS3 version does not (it has no creationComplete() handler). Because the BeanProvider is not a UIComponent, this automatic loading of the WSDL is not done by the Flex framework. As a result, you must call loadWSDL() on your web service before you can use it, because you are actually using the WebService's AS3 implementation.

Why do I get an error when using Swiz in a Flash Builder project when I use Design View?
Researching this seems to indicate that it can happen with any .swc where the .swc was compiled using a version of the SDK other than the version used by the project. Since there are so many possible SDK versions, creating separate versions of Swiz for all of them is not possible. If you need to use Design View, and you're using an SDK other than the one the framework was compiled with, we recommend that you download the source code, set up the framework as a library project, and add the library project to your application project. This should resolve the Design View error.

Anda mungkin juga menyukai