Monday, September 19, 2011

Spring Actionscript v2.0 Progress Report - part IV

So, after the release of as3commons-bytecode v1.0 (by the way, v1.1 is nearing completion already hehe), it was time to focus back on Spring Actionscript v2.0

I've been mostly busy re-setting up the site generation. We are building our documentation in the Docbook format. Its has a bit of a learning curve, but once you get the hang of it, and especially the extension points of the transformation classes, Docbook is a great choice to encode technical documentation in. For me it was important to be able to simply enclose a class name with a <literal/> element and have a custom XSLT sheet transform this to a <a href="...">Classname</a> result. With the href containing a valid link to the correct ASDoc page.
Luckily the intermittent XML format that is being spat out by the ASDoc compiler helps out here, so that saves me quite a bit of typing. We used to already have a system in place but this still required me to copy/paste the fully qualified into an xlink:href attribute. Which sucks if you have hundreds of class names strewn throughout the reference docs. But now that pain is gone :)

Anyways, once that was out of the way I added some custom xslthl extensions, so now we have some nicely highlighted code snippets as well.

And then the writing started... I've tried to re-organize the old reference docs into something with a little bit better of an overview. I hope I've succeeded...

But besides writing documentation there *have* been some small additions to the library since the last progress report. Let's see what they are.

MXML EventBus Custom Configuration

For XML configuration we described the Eventbus namespace handler to easily configure eventhandlers, interceptor, listenerinterceptors and event routers in the second progress report. In the third one we described the ICustomObjectDefinitionComponentinterface.
Using this interface we now offer some Eventbus configuration extensions for the MXML configuration.
So, to configure an Eventhandler in MXML use this MXML markup in your configuration:

<sas:EventHandler instance="metadataHandler">
    <sas:EventHandlerMethod name="handleEvent" eventName="complete"/>
</sas:EventHandler>

Where instance is the object name whose handleEvent method will be used as the eventhandler for events with the name complete.
To add a topic or topics, use the topics property:
<sas:EventHandler instance="metadataHandler">
    <sas:EventHandlerMethod name="handleEvent" eventName="complete" topics="topic1,topic2"/>
</sas:EventHandler>

For an event interceptor, add this MXML markup:
<sas:EventInterceptor instance="eventInterceptor">
    <sas:InterceptionConfiguration eventName="complete"/>
</sas:EventInterceptor>
Same applies here for topics, or topic properties, or if you want to intercept an event class instead of an event by name:
<sas:EventInterceptor instance="eventInterceptor">
    <sas:InterceptionConfiguration eventClass="{MyCustomEvent}" topics="topic1" topicProperties="myProperty,myOtherProperty"/>
</sas:EventInterceptor>
And event listener interceptor is almost the same as an interceptor, configuration-wise:
<sas:EventListenerInterceptor instance="eventListenerInterceptor">
    <sas:InterceptionConfiguration eventName="complete" topics="topic1"/>
</sas:EventListenerInterceptor>
And lastly, there is the RouteEvents markup, used to automatically send one or more specified events dispatched by a specified object through the EventBus. To configure this in MXML, use this markup:
<sas:EventRouter instance="eventRouterInstance">
    <sas:EventRouterConfiguration eventNames="busy,progress,ready" topics="topic1"/>
</sas:EventRouter>
And that's it!

Factory objects

Spring Actionscript v1.x offered the IFactoryObject to perform complex object creation and configuration for cases where XML or MXML markup was simply to verbose or unwieldy. Now Spring Actionscript v2.0 doesn't require you to implement the interface any more, you can simply add this metadata to your class:
[Factory(factoryMethod="createNewInstance")]
public class IncrediblyComplicatedObjectFactoryThatDoesNotImplementIFactoryObject {

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

}

Now all you have to do is add this class as an object definition to your configuration and it'll be automatically picked as a factory object by the container.

If you don't want to litter your classes with metadata, you can also use the XML configuration, to achieve this, first add the util namespace handler to your XMLApplicationContext:

xmlApplicationContext.addNamespaceHandler(new UtilNamespaceHandler());

Then add this namespace to your XML configuration:
xmlns:util='http://www.springactionscript.org/schema/util'

And finally, add this markup to the XML itself:
<util:factory
    factory-method="createNewInstance"
    class="com.myclasses.factories.IncrediblyComplicatedObjectFactoryThatDoesNotImplementIFactoryObject"
    id="incrediblyComplicatedObject"/>

Naturally, there is also the possibility to do the same in MXML configuration, use this MXML markup instead:
<sas:FactorObjectDefinition
    factoryMethod="createNewInstance"
    clazz="{IncrediblyComplicatedObjectFactoryThatDoesNotImplementIFactoryObject}"
    id="incrediblyComplicatedObject"/>

Metadata configuration

One of the disadvantages of the metadata configuration used to be that you can only add the [Component] metadata to classes that you have source code access to. It was impossible to add object definitions for Flex classes, or any other third party libraries for that matter.
Or maybe you simply dislike having all of the [Component] metadata strewn around your code base. Certainly in larger projects this might become a handicap.
Therefore I have added the [Configuration] metadata tag. This can be added to a class that functions as nothing more than a placeholder for object definition specific metadata.

Here's an example of what this class might look like:
[Configuration]
public class MyConfiguration {

    [Constructor(args="ref=objectName2")]
    [Invoke(name="someMethodName",args="ref=objectName1, value=10")]
    [Property(name="wireOnlyOnce",value="true")]
    [Component(id="processor",isLazyInit="true")]
    public var defaultAutowiringStageProcessor:DefaultAutowiringStageProcessor;
}

What this does is add an object definition for the class DefaultAutowiringStageProcessor, with object name 'processor'. It will inject the object with name objectName2 into its constructor, it will set its wireOnlyOnce property to true, it will invoke it someMethodName with two arguments: an instance of the object with name objectName1 and a value of 10. And finally, it will set is lazyInit property to true.

Just make sure that this class will get compiled into your resulting SWF by declaring it somewhere, otherwise the MetadataApplicationContext won't be able to detect it.

There will be an extension point for this as well, to be able to add custom metadata to these configurations that can add extra configuration logic to specific object definitions. But that is for the next progress report :)

Beta site is online!

And finally I am happy to annoucne that the beta site for Spring Actionscript v2.0 is now online! As you will see the reference documentation is far from complete. This is VERY much a work in progress, but as I mention this is a BETA site, with BETA software. So bear with me :)

So please, anything you download from there, please do not be surprised if it crashes, explodes or doesn't work like it says on the box. Do however play around with it, poke holes in it, and contact us with questions, suggestions, criticism and ideas.

You can find the beta site at this address: http://beta.springactionscript.org

I believe that's it for now, until the next time, happy coding!

1 comment:

  1. Hey Roland, just a heads up letting you know these progress reports are proving to be invaluable. Keep them coming!

    ReplyDelete