-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial
#Getting Started
This chapter gives a very quick introduction on how to build a simple application with Parsley, linking to other parts of the manual for more detailed descriptions. Most of the explanations apply in the same way to building Flex or Flash Applications. Examples that only apply for Flex development will be pointed out accordingly.
##Hello World Sample Application
If you prefer to examine a simple sample application before reading the manual, you can find a Hello World sample here
This chapter does not reflect the sample application though.
##Adding the Framework SWCs
To start working with Parsley you need to add several of its SWCs to your classpath first. Which ones you'll need depends on the feature set you'll be using and whether you'll be building a Flex or Flash Application. See Dependencies for details.
To get started take the Parsley Core download and add the required SWCs from the
release and dependencies folders to your classpath.
You'll find them in the release
folder of the download Zip.
#####Minimum Set of Required SWCs
You always need:
parsley-core-${version}.swc
spicelib-commands-${version}.swc
spicelib-reflect-${version}.swc
spicelib-util-${version}.swc
#####Additional SWC for Flex
For Flex you'd also need:
parsley-flex-${version}.swc
#####Additional SWCs for XML Configuration
Only when using XML configuration you'd also need to add:
parsley-xml-${version}.swc
spicelib-xml-mapper-${version}.swc
##Defining Object Dependencies
This is probably the most frequently used feature of Parsley. Dependencies can be configured with Metadata, MXML, XML or programmatically.
#####Using the #cdi [Inject] #cdi metadata tag
You can use the tag on properties:
[Inject]
public var loginService:LoginService;
[Inject]
public function set loginService (service:LoginService) : void {
Or you can use it on methods to declare multiple dependencies at once:
[Inject]
public function init (loginService:LoginService, cartService:CartService = null) : void {
The nice thing in the example above is that Parsley will also reflect on the parameter types
and treat optional parameters as optional dependencies. So in this example the container will throw an
Error if the LoginService
is missing, but silently skip the CartService
if it is
not present in the container.
Finally you can also use a similar tag ([InjectConstructor]
) on the class declaration
for constructor injection (as the Flex compiler ignores metadata on constructors):
[InjectConstructor]
public class LoginAction {
function LoginAction (loginService:LoginService, cartService:CartService = null) : void {
Again the second (optional) parameter will treated as an optional dependency accordingly
#####Best Practices
In all the examples we showed in this section the dependencies will be selected by type, since Parsley will reflect on the property and method parameter types. To benefit from the decoupling that an IOC Container offers you should prefer to declare interface types at injection points. This way you can switch implementations in the configuration without touching the injection points of classes that need these services.
Of course this only works when you add only a single object matching the type at the injection point to the container. If you have several implementation of the same interface you'd need to switch to injection by id instead which is only available for properties:
[Inject(id="mainLoginService")]
public var loginService:LoginService;
The choice between property, method or constructor injection is up to you. Some prefer constructor injection as it enables better encapsulation, allowing you to create immutable classes. But constructor injection is only recommended if you target Flash Player 10.1 or newer as earlier players had reflection bugs on constructors.
See Dependency Injection for more details on injection in general.
##Sending and Receiving Messages
While Dependency Injection already allows some level of decoupling if you declare injection points with interface types, for some parts of the application you'll prefer even looser coupling, letting the parts of your application communicate through messages, without the sender and receiving objects having to know each other.
For example you might transform low-level view events into calls to a presentation model which dispatches application messages, so that any action/controller can register for all message types it is interested in.
For more details on this topic see Messaging and Building MVC Architectures.
With Parsley you can configure the sending as well as the receiving side with metadata tags.
The sending part may simply contain a [MessageDispatcher]
tag on a public function
property:
#hlt [MessageDispatcher] #hlt
public var dispatcher: Function;
public class LoginServiceImpl implements LoginService {
[...]
private function handleLoginResult (user:User) : void {
#hlt dispatcher(new LoginMessage(user)); #hlt
}
}
Here we use the injected dispatcher function to send an instance of LoginMessage
.
With Parsley messages do not need to extend the Event class (although they could if they'd need to).
For the receiving side you can use the [MessageHandler]
tag to signal interest in a particular
message type, determined by the parameter type of the method:
[MessageHandler]
public function login (event:LoginEvent) : void {
Like with Dependency Injection selecting the message receivers by type improves the robustness of the system as you don't have to take care of unique event type String constants for the whole system.
There are more tags for the receiving side like the [MessageBinding]
tag.
Those will be explained in Messaging.
##Assembling the Objects
There are a lot more configuration options in addition to the tags for Dependency Injection and Messaging. But since those are the most common ones we'll now show you how you assemble these objects for the IOC Container. After you added metadata tags to the classes you have to tell the container which objects it should manage.
#####Flex Applications
In Flex you might want to prefer MXML configuration. You can create a simple MXML class (using
from the Parsley namespace as the root tag) and add all the classes you want to be managed by Parsley:
<Objects
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns="http://www.spicefactory.org/parsley"
xmlns:services="com.bookstore.services.*"
xmlns:actions="com.bookstore.actions.*">
<fx:Declarations>
<services:LoginServiceImpl timeout="3000"/>
<services:CartServiceImpl timeout="3000"/>
<actions:LoginAction/>
<actions:AddToCartAction/>
<actions:DeleteCartAction/>
</fx:Declarations>
</Objects>
Of course you can also use this configuration file for setting additional property values. They will be combined with the processing of the metadata tags for all classes added to the container.
In this example we didn't specify any id attributes. If you just use injection by type you don't need them. In case you use ids at injection points like in the last example of the section on injection you have to specify them here:
<services:AdminLoginServiceImpl id="adminLogin" timeout="3000"/>
<services:UserLoginServiceImpl id="userService" timeout="3000"/>
You can then use those ids at injection points:
[Inject(id="adminLogin")]
public var adminLogin:LoginService;
[Inject(id="userLogin")]
public var userLogin:LoginService;
But in general you should try to avoid injection by id and only use it where you work with multiple instances of the same type.
#####Flash Applications
In this case MXML is not available. So the preferred configuration mechanism is probably the use of XML files. Of course you can also use external XML files in Flex Applications if you don't want to compile the configuration into your application.
An example XML configuration corresponding to the MXML example above would look like this:
<objects
xmlns="http://www.spicefactory.org/parsley"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.spicefactory.org/parsley
http://www.spicefactory.org/parsley/schema/3.0/parsley-core.xsd"
>
<object type="com.bookstore.services.LoginServiceImpl">
<property name="timeout" value="3000"/>
</object>
<object type="com.bookstore.services.CartServiceImpl">
<property name="timeout" value="3000"/>
</object>
<object type="com.bookstore.actions.LoginAction"/>
<object type="com.bookstore.actions.AddToCartAction"/>
<object type="com.bookstore.actions.DeleteCartAction"/>
</objects>
Like with the MXML example we don't specify an id for the object definitions. You can add it if required for injection by id.
These are the most common options for assembling the objects. You'll find many more examples in Configuration and Initialization.
##Initializing the Framework
Now that you configured your classes with metadata tags and assembled them in MXML or XML, it's finally time to intialize the whole thing. Fortunately in most cases this is a one liner or a simple tag.
For the MXML configuration file we created, assuming that we called it BookStoreConfig.mxml
,
the tag would look like this:
<parsley:ContextBuilder config="{BookStoreConfig}"/>
That's all there is to it.
For the XML example we have to initialize the Context programmatically in a Flash application:
XmlContextBuilder.build("config.xml");
We covered the most common use cases here. There are a lot more options like splitting the configuration into multiple files or even using different configuration mechanisms like MXML and XML in the same application and merging them to a single context. This will be demonstrated in Combining multiple Configuration mechanisms.
For modular applications you wouldn't want to lump everything together into a single monolithic context and load all this stuff on application start. For building modular applications and loading and unloading configurations on demand see Building Modular Applications.
##Adding more Services
Since this is the Getting Started section we only covered the most common use cases. But hopefully for simple applications it is sufficient to get you going. As you may have noticed already the manual is quite extensive and if you think you need a lot more options than covered in this chapter you should browse the remaining chapters.
If you just want to get an idea of the feature set Parsley offers you may want to start with Features List.
The most interesting options not covered in this chapter are probably:
-
Configuration DSL and ActionScript Configuration: You are not limited to configuration with Metadata, MXML or XML, there are two more options, which give you additional flexibility.
-
Intercepting Messages: A
MessageHandlers
as covered in this chapter even allows you to interfere with the message dispatching process (e.g. suspending and resuming or cancelling the message processing). -
Managed Commands: You can execute Commands in a way that they are managed by the container for the time they execute.
-
Using Factories: Instead of assembling the target objects itself you can also add factories to the IOC Container which create objects, which gives you additional flexibility on how objects are instantiated.
-
Asynchronous Object Initialization: Configuration option for asynchronously initializing objects (e.g. objects that need to load data before they can operate). In this case the container will defer the initialization of other objects until those configured to be asynchronous are ready.
-
Dynamic View Wiring: We already mentioned this one briefly. Allows you to wire Flex Components defined in MXML to objects declared in the IOC Container.
-
Building Modular Applications: Associate configured services, actions, presentation models and so on with a configuration Context that can be loaded and unloaded on demand.
-
ResourceBindings: For binding properties of managed objects to localized resources, updating them automatically when the localeChain changes.
-
Extending the Framework: If you want to add your own Metadata, MXML or XML configuration tags or use some of the other available extension points. Useful for simplifying recurring configuration tasks or for creating frameworks on top of Parsley.
- Features List
- What's New in Parsley 3.0
- Migrating from Parsley 2 to Parsley 3
- Building the Framework from Source
- Dependencies
- Hello World Sample Application
- Adding the Framework SWCs
- Defining Object Dependencies
- Sending and Receiving Messages
- Assembling the Objects
- Initializing the Framework
- Adding more Services
Configuration and Initialization
- Configuration with AS3 Metadata
- MXML Configuration
- XML Configuration Files
- Runtime Configuration
- Configuration DSL
- ActionScript Configuration
- Combining multiple Configuration mechanisms
- Configuration Properties
- Constructor Injection
- Method Injection
- Property Injection by Type
- Property Injection by Id
- Declaring Dependencies in MXML or XML
- Overriding Dependencies in Child Contexts
- Comparing Dependency Injection and Decoupled Bindings
- Basic Usage
- Avoiding Conflicts
- Using Scopes
- Publishing Managed Objects
- Persistent Properties
- Bindings in Flash
- Dispatching Messages
- Receiving Messages
- Managed Events
- Injected MessageDispatchers
- MessageHandlers
- MessageBindings
- Intercepting Messages
- Error Handlers
- Using Selectors
- Using Scopes
- Using the Messaging API
- Implementing a Command
- Mapping Commands to Messages
- Command Groups
- Command Flows
- Starting a Command Programmatically
- Handling Results and Observing Commands
- Command Lifecycle
- About Managed Objects
- Using Factories
- Asynchronous Object Initialization
- Object Initialization Order
- Object Lifecycle Methods
- Lifecycle Observer Methods
- Dynamic Objects
- Initializing View Wiring Support
- Explicit Component Wiring
- Component Wiring without Reflection
- Automatic Component Wiring
- Metadata Configuration
- MXML and XML Configuration
- Component Lifecycle
- Flex Popups and Native AIR Windows
- View Wiring in Modular Applications
- Available Extension Points
- Custom Metadata Tags
- Custom MXML and XML Tags
- Working with ObjectDefinitions
- Working with Scopes
- Custom Configuration Mechanisms
- Replacing IOC Kernel Services
- Initializing Extension Modules