Prana 0.2 released with AS3 Reflection API

ActionScript, Flash, Flex, Prana 5 Comments »

I just managed to release a new version of the Prana Framework. The new release contains an AS3 Reflection API and some general updates.

Reflection API

A quick example of the Reflection API:

Actionscript:
  1. var instance:MyClass = new com.domain.MyClass();
  2.  
  3. // get the type info of the instance variable
  4. var type:Type = Type.forInstance(instance);
  5. // ... or via the class object
  6. //var type:Type = Type.forClass(MyClass);
  7. // ... or via the class name
  8. //var type:Type = Type.forName("MyClass");
  9.  
  10. // we now have access to the properties and methods
  11. // defined by the MyClass class
  12. trace(type.name); // outputs "MyClass"
  13. trace(type.fullName); // outputs "com.domain::MyClass"
  14. trace(type.methods);
  15. trace(type.staticConstants);
  16. trace(type.staticVariables);
  17. trace(type.constants);
  18. trace(type.variables);
  19. // ... and lots more
  20.  
  21. // it is also possible to dynamically invoke methods
  22. var result:* = type.methods[0].invoke(instance, arg1, arg2);

General info and downloads

New Developer for Prana

Other news is that my co-worker Kristof "Hickey" Neirynck has joined the development team. Welcome Kristof!

Hope you enjoy it! As usual, any feedback is kindly appreciated.


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

Prana is now on SourceForge

ActionScript, Design Patterns, Flash, Flex, Prana 3 Comments »

The Prana Framework I mentioned last week (here and here), has now been added to SourceForge.

In short, Prana is an Inversion of Control (IoC) Container written in ActionScript 3. It is a non-intrusive API for configuring Flash/Flex/Apollo applications. The library also contains general utilities. Possible additions may include an AOP framework and Mock Objects support for FlexUnit.

Check it out at http://sourceforge.net/projects/prana/.

A user mailinglist is available at https://lists.sourceforge.net/lists/listinfo/prana-user

Developers interested in sharing ideas or joining in for development can contact me at info{at}herrodius.com.


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

Looping through an IViewCursor with a for-loop

ActionScript, Flash, Flex 2 Comments »

If you've been working with collections in Flex 2 you most likely already ran into an infinite loop when iterating over a collection cursor because you forgot to call the moveNext() method on the cursor. I've been scratching my head a few times the last weeks just because of this and thought the "problem" could easily be solved by using a for-loop instead of a while-loop to iterate over the cursor.

Here's an example of a while-loop iterating over an IViewCursor:

Actionscript:
  1. var cursor:IViewCursor = myCollection.createCursor();
  2.  
  3. while (!cursor.afterLast) {
  4.   trace(cursor.current);
  5.   // forget this line and you're big trouble son!
  6.   cursor.moveNext();
  7. }

The for-loop equivalent looks like this:

Actionscript:
  1. for (var cursor:IViewCursor = myCollection.createCursor(); !cursor.afterLast; cursor.moveNext()) {
  2.   trace(cursor.current);
  3. }

In my opinion the for-loop approach looks a lot cleaner and is less error-prone than the while-loop. It also has fewer lines of code and will probably save some resources since the cursor is defined in the for-loop.


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

Introducing Prana: IoC Container for AS3

ActionScript, Design Patterns, Flash, Flex, Prana 7 Comments »

Note before starting: For a primer on Inversion of Control (IoC) and Dependency Injection, please read "Inversion of Control Containers and the Dependency Injection pattern" by Martin Fowler.

Prana's IoC container: an example

As an example, I took the Cairngorm Store modified by Renaun Erickson and used Prana to configure its service locator. You could imagine this application being deployed on several clients and they would all have their own AMFPHP gateway. It would be a pain if the application would have to be recompiled for each client just because the path to the remoting gateway changed. With Prana, we can specify the actual implementation of the remote services and the service locator in an external xml file called the application context (applicationContext.xml) and the IoC container will be responsible for setting things up for us. Let's see some code.

The service locator is now configured in the Services.mxml file. One of the services, the 'productService', is configured like this:

XML:
  1. <renaun:RemoteObjectAMF0
  2.   endpoint="http://localhost/amfphp/gateway.php"
  3.   id="productService"
  4.   source="com.adobe.cairngorm.samples.store.business.ProductDelegate"
  5.   showBusyCursor="true"
  6.   makeObjectsBindable="true">
  7. </renaun:RemoteObjectAMF0>

You can see that the endpoint property is pointing to a hard coded remoting gateway. As said earlier, in order to change this value for another deployed client, we would have to change the value and recomile the application. With Prana, we will just leave out the actual implementation like this:

XML:
  1. <renaun:RemoteObjectAMF0 id="productService"/>

So when the application is compiled, the service locator will know about a remote service called 'productService' but it will not know anything about its implementation details.

Defining the application context

We define the external configuration of the productService as follows. This configuration is stored in an xml file, called applicationContext.xml by convention (but you can call it whatever you like):

XML:
  1. <object id="productService" class="com.renaun.rpc.RemoteObjectAMF0">
  2.   <property name="id" value="productService"/>
  3.   <property name="endpoint" value="http://localhost/amfphp/gateway.php"/>
  4.   <property name="source" value="com.adobe.cairngorm.samples.store.business.ProductDelegate"/>
  5.   <property name="showBusyCursor" value="true"/>
  6.   <property name="makeObjectsBindable" value="true"/>
  7. </object>

Every object is defined in an 'object' node. We need to give each object and identifier (the 'id' attribute) and a class name (the 'class' attribute) so that the container knows which class to instantiate. The properties of the productService are defined in 'property' nodes which all have a 'name' and 'value' attribute. You can see for instance that the 'endpoint' property will be assigned the value 'http://localhost/amfphp/gateway.php'.

Note: Prana currently supports setter injection through implicit setters and not through explicit setters. (set myPropery vs. setMyProperty)

Besides the productService, we also have to configure the service locator so that it knows it is assigned a new instance of a remote service:

XML:
  1. <object id="serviceLocator" class="com.adobe.cairngorm.business.ServiceLocator" factory-method="getInstance">
  2.   <property name="productService">
  3.     <ref>productService</ref>
  4.   </property>
  5. </object>

Notice that we have specified a 'factory-method' attribute on the definition of the service locator. This is needed because Cairngorm's ServiceLocator is a singleton which you can access through the getInstance() method. When the container finds a factory method defined, it will not invoke the constructor of the class but instead will call the specified factory method to retrieve an/the instance of the class.

The productService is defined as a property of the serviceLocator, but notice here that the property node does not have an actual value assigned. Instead, is it has a 'ref' node which describes a reference to the id of another object defined in the application context.

Note: Currently reference properties only work when the refered to object is configured before the object that is refering to it. This will be solved in later versions of Prana.

The application context is ready. All we need to do now, is let the application know that it should load the context before starting up. In the Cairngorm Store example the application starts by getting the products for the store. This is defined in the onCreationComplete handler:

Actionscript:
  1. CairngormEventDispatcher.getInstance().dispatchEvent( new CairngormEvent( GetProductsEvent.EVENT_GET_PRODUCTS ) );

We will remove this here line and instead load the application context. Once the context is loaded, we can dispatch the event to get the products:

Actionscript:
  1. private var _objectDefinitionsLoader:IObjectDefinitionsLoader;
  2.  
  3. private function onCreationComplete():void {
  4.   _objectDefinitionsLoader = new XmlObjectDefinitionsLoader();
  5.   _objectDefinitionsLoader.addEventListener(ObjectDefinitionsLoaderEvent.COMPLETE, onObjectDefinitionsLoaderComplete);
  6.   _objectDefinitionsLoader.load("../applicationContext.xml");
  7. }
  8.  
  9. private function onObjectDefinitionsLoaderComplete(event:ObjectDefinitionsLoaderEvent):void {
  10.   CairngormEventDispatcher.getInstance().dispatchEvent( new CairngormEvent( GetProductsEvent.EVENT_GET_PRODUCTS ) );
  11. }

That's it. By loading the application context, all objects will be wired together behind the scenes. If wanted, we could access the container and request the productService from it:

Actionscript:
  1. var container:ObjectContainer = _objectDefinitionsLoader.container;
  2. var productService:RemoteObjectAMF0 = container.getObject("productService");

Other Prana capabilities

The Dependency Injection method in the example above is Setter Injection. Prana however also supports Constructor Injection. An example object definition for a constructor defined as Person(name:String = "", age:int = 0, isMarried:Boolean = false) is:

XML:
  1. <object id="johnDoe" class="be.indiegroup.prana.ioc.testclasses.Person">
  2.   <constructor-arg value="John Doe"/>
  3.   <constructor-arg value="36"/>
  4.   <constructor-arg value="true"/>
  5. </object>

Another thing is that you can (recursively) define properties as arrays or objects like this:

XML:
  1. <object id="testObject" class="be.indiegroup.prana.ioc.testclasses.TestObject">
  2.   <property name="anArray">
  3.     <array>
  4.       <value>stringValue</value>
  5.       <value>13</value>
  6.       <value>true</value>
  7.       <array>
  8.         <value>12</value>
  9.         <value>test</value>
  10.       </array>
  11.     </array>
  12.   <property>
  13.   <property name="anObject">
  14.     <object>
  15.       <property name="key1" value="value1"/>
  16.       <property name="key2" value="35"/>
  17.       <property name="key3" value="false"/>
  18.       <property name="key4">
  19.         <array>
  20.           <value>12</value>
  21.           <value>test</value>
  22.         </array>
  23.       </property>
  24.     </object>
  25.   </property>
  26. </object>

Download Prana 0.1

I hope you enjoyed this primer on Prana. Below is the Prana Framework available for download. It has the Prana.swc file, sources and docs. Please note that documentation is far from complete at this moment. The other download is the Cairngorm Store, modified by Renaun Erickson to use AMFPHP and modified by myself to use Prana. You can download them here:

  • Prana Framework 0.1
  • Prana Framework 0.1.1
  • Prana Framework 0.1.1 with dependencies
  • Cairngorm Store Prana Example
  • Download Prana on SourceForge: Prana SourceForge page

Have fun!


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 

AppSettings class for AS3

ActionScript, Flash, Flex 3 Comments »

Here's a class that comes in handy from time to time. It allows you to store key/value pairs, for configuration purposes for instance, and load them from an external XML source. You can also modify the settings by code. Here are some examples:

To add a setting or change the value of an existing setting, simply define it as a property as follows:
AppSettings.getInstance().mySetting = "myValue";

To get a setting, request it as a property:
var result:String = AppSettings.getInstance().mySetting;

To delete a setting, use the delete operator:
delete AppSettings.getInstance().mySetting;

The XML format is similar to that of .Net's AppSettings config section. All settings are contained in a node and the key/value pairs are placed in <add key="" value=""/> subnodes.

Example:
<appsettings>
<add key="myFirstSetting" value="aValue"/>
<add key="mySecondSetting" value="anotherValue"/>
</appsettings>

To load these XML settings, just call the load() method:
AppSettings.getInstance().load("pathtosettings.xml"); (to load from an xml file)
or
AppSettings.getInstance().load(myXmlObject); (to load from an xml object)

To use this class, just place the herrodius.swc from the bin folder in your classpath. More info is available in the release notes.

This class uses the flash_proxy class to control the dynamic properties. It is similar to the older __resolve() method but offers much better control.

The download contains the binaries, the docs and the source files: herrodius-as3lib-v0.1.zip

Any feedback is greatly appreciated.


Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
 
WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login