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!

Wednesday, September 14, 2011

Released: AS3Commons-Bytecode version 1.0!

So, its been more than a year in the making. If I check the changelog, the first commit of as3commons-bytecode was done at the 27th of June 2010.


I've decided to call this release v1.0. I could think of another thousand things to be tweaked and improved but at a certain moment there needs to be a first final release :)
This certainly doesn't mean the library is now finished, I will keep on tweaking and improving the library. Hopefully users of the library will join in the discussion and suggest new features or improvements.

So, now perhaps is the time to look back, reflect and tell a little about the history of as3commons-bytecode :)

I started as3commons-bytecode after taking over the Loom project from Maxim Porges (http://code.google.com/p/loom-as3/). I had begun implementing an AOP solution for Spring Actionscript, first focusing on the pointcut scanning logic because I was following Maxim's progress with Loom and thought this would be an ideal library to use as its foundation.
Sadly, before the library was finished Maxim couldn't offer the personal resources anymore to continue the project. This certainly threw my schedule off :) At first I considered using the FLemit and FLoxy libraries but found that they were too specifically aimed at generating mocks. I need something more generic.

So that's when I started spelunking through the Loom code and step-by-step I actually started to understand what was going on. Before, I was very reluctant since I considered this stuff way beyond my mortal understanding. But I managed to fix some bugs and that's when I contacted Maxim and asked him if it was alright for me take over the project and bring it into the AS3Commons project.
Luckily Maxim was alright with this and so my nightmare begun haha :)

First thing I implemented was the bytecode based reflection. Since it appeared to be relatively simple and was a good way for me to get to know the code base a little. When this was done I started the task of finishing the parsing of all of the opcodes since this hadn't been completed yet. This was when the proverbial shit hit the fan because this is when I started to find out about subtle AVM documentation errors. Or just plain non-existent documentation...Luckily, a trip through the Tamarin source code offered quite a lot of valuable insight as well.
Actually getting the opcode parsing completely to work only got finished a few weeks ago :)

Next step was to generate classes at run-time. I was familiar enough with the ABC format by now to come up with an API to let a developer assemble an ABC file without needing to have any intimate knowledge of 'what lies beneath'. I actually used the .NET System.emit namespace as an inspiration.

Around the time that class generation was implemented, James Ward contacted Maxim Porges to see if he could persuade him to continue his work on Loom since James and Michael Labriola had been hacking away on a mechanism that could intercept SWF loading by the Flash Player.
An ideal hook for AOP and other black magic.
Maxim then forwarded James to me and afterwards Michael and James offered some invaluable help and advice in further developing as3commons-bytecode. Eventually this culminated in their Mixing Loom project (James' blog introduction) and their fantastic session called 'Planet of the AOPs' at the 360|Flex conference in Denver. This was the first true introduction of AOP to the Flash community I guess you could say.

After class generation was working the next step was to provide a generic API for generating dynamic run-time proxies. These are basically subclasses (generated at runtime) that incorporate an interception mechanism for methods and accessors (getters and setters). So when a method gets invoked on the dynamic subclass it will first invoke any registered interceptors, enabling these interceptor to perhaps change or replace the behavior of the underlying functionality. Most mocking libraries (like asmock, mockolate or mockito-flex) are based on this logic.

The API for this is explained in this documentation section on the as3commons site.

Naturally, the most interesting solution that can be created using this proxy API are AOP mechanisms and quite soon after the proxy API became available Marty Pitt went ahead and created Flapper. An AOP extension for the Parsley framework. As if this wasn't enough, he then also created another library called Dynamic Services, also a Parsley extension. This library is able to take an interface that describes a service class and generate this service on-the-fly. This can save you a lot of typing :)

David Arno discovered the library as well and went out to create AS3Introspection, a library that he himself dexcribes as "describeType on steroids". I think that pretty much covers it :)

Jeff Ardillo then went ahead and showcased a technique to create proxies without having to depend on the ProxyFactory to create them in his excellent blog article 'Aspect Oriented Programming in Flex'.

I am very excited to see all of these initiatives take shape as this is exactly the reason why I started as3commons-bytecode. It was its specific aim to be a foundational library and facilitate a platform for other developers to base their own solutions on. Seeing this actually taking place is very satisfying indeed, so kudos to all of you who have taken the library to its next level!

Lately the Flash/Flex twitter- and blogosphere has been buzzing a lot with all sorts of AOP solutions. The Swiz framework just announced their own AOP functionality in their upcoming version 2.0, for instance. This is all great news and opens up all sorts of new and exciting possibilities on the Flash platform.

In that spirit, expect to see a new As3Commons project to be released in the near future as well. It'll be called as3commons-aop and will offer a bunch of standard interfaces and API's that deal with advices and pointcut scanning. Hopefully this will help developers to easily incorporate AOP functionality in other frameworks out there. As we are used to eating our own dogfood, Spring Actionscript will naturally use as3commons-aop as its AOP foundation :)

Yet, I would like to stress, don't focus only on the AOP possibilities of as3commons-bytecode. I believe that projects like Marty Pitt's Dynamic Services show that much more can be achieved with the ability to generate classes at run-time. So be creative and try to come up with some more interesting solutions!

Thank you very much to everyone who has submitted bug reports, feature requests and developed solutions based as3commons-bytecode!

Happy coding!

P.S. If you'd like to get involved with as3commons-bytecode's development or the as3commons project in general, please drop us a line! We always appreciate more help and contributions!

Sunday, September 4, 2011

Spring Actionscript v2.0 Progress Report - part III

We're gradually getting ready for a first beta release. Most of the foundational parts of the IoC container have now been refactored and unit tested. (Although the unit testing is still an ongoing process)
Spring Actionscript 2.0 was put on the backburner just a little bit the past week since a bunch of debugging work for the AS3Commons-Bytecode library took up just a little bit more time than was anticipated... Apologies for this. (But expect a new AS3Commons-Bytecode release as well in the coming days :))
In the past few weeks the following has been added:

IMetadataDestroyer interface

To be able to undo the processing of an IMetadataprocessor a second interface has been added. Its much like the IStageObjectProcessor and IStageObjectDestroyer logic. One performs certain logic, the other is able to undo this logic in case this is necessary. The interface is quit simple:
public interface IMetadataDestroyer {
  function get metadataNames():Vector.<String>;
  function destroy(instance:Object, container:IMetadataContainer, metadataName:String, objectName:String):void;
}

MXML Application context

Besides the XML based configuration, naturally, the MXML based configuration makes its comeback as well. It has changed slightly compared to the one in Spring Actionscript 1.x, but the changes aren't enormously disrupting.
The MXMLApplicationContext itself is now also an MXML element, so here's how its declared in an application:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
   xmlns:s="library://ns.adobe.com/flex/spark"
   xmlns:mx="library://ns.adobe.com/flex/mx"
   xmlns:sas="http://www.springactionscript.org/mxml/config"
   creationComplete="application1_creationCompleteHandler(event)">
<fx:Declarations>

<sas:MXMLApplicationContext configurations="{[TestObjects]}"
configurationPackage="{new FullConfigurationPackage()}"
id="MXMLContext"
autoLoad="true"
complete="{onComplete(event)}"/>


</fx:Declarations>
</s:Application>
As you can see, the configuration is fed to this Application Context usingits 'configurations' property, which accepts an Array of Classes. In this casethe TestObjects class is also an MXML file and looks like this:

<sas:SASObjects xmlns:fx="http://ns.adobe.com/mxml/2009"xmlns:s="library://ns.adobe.com/flex/spark"xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:sas="http://www.springactionscript.org/mxml/config">
<fx:Script>
<![CDATA[
import classes.MetadataHandler;

import mx.collections.ArrayCollection;
[Bindable]
public var collection:ArrayCollection = new ArrayCollection(['value1', 'value2']);
]]>
</fx:Script>
<fx:Declarations>
<sas:Object id="test"
clazz="{Object}">
<sas:Property name="list"
  ref="collection"/>
</sas:Object>

<sas:Object clazz="{MetadataHandler}"
id="metadataHandler"/>
</fx:Declarations>

</sas:SASObjects>
The object definitions haven't changed at all from Spring Actionscript 1.x, apart from the extra properties that were described in part I of the progress report. As you can see, it's also possible to just declare regular object instantiatons in the configuration and have them being treated as singletons in the context. For instance the ArrayCollection called collection can be retrieved from the ApplicationContext simply by invoking MXMLContext.getObject('collection');.
As you can also see, the collection singleton is also being injected into the object called 'test' in its property called 'list'.
Naturally, MXML object such as RemoteObject can also directly be declared inside the configuration, without having to resort to creating an <Object/> element for it. Direct declaration only works for singleton of course.
The MXMLApplicationContext is, like the XMLApplicationContext, nothing but a convenience subclass. It also very much possible to construct one manually like this:
var applicationContext:DefaultApplicationContext = new DefaultApplicationContext(null, rootView);
var provider:MXMLObjectDefinitionsProvider = new MXMLObjectDefinitionsProvider();
provider.addConfiguration(TestObjects);
applicationContext.addDefinitionProvider(provider);
applicationContext.addEventListener(Event.COMPLETE, handleComplete);
applicationContext.load();

ICustomObjectDefinitionComponent interface

Similar to namespace handlers that make the XML configuration a little easier to read, the MXML configuration can contain ICustomObjectDefinitionComponents. Implementations of this interface can define a custom configuration for a certain type of object and offer a few shortcuts for this configuration. The interface is quite easy again:
public interface ICustomObjectDefinitionComponent extends IMXMLObject {
  function execute(applicationContext:IApplicationContext, objectDefinitions:Object):void;
}
Once the MXMLApplicationContext starts loading its MXMLObjectDefinitionsProvider and encounters an ICustomObjectDefinitionComponent, it will invoke its execute() method and pass in a reference to the MXMLApplicationContext and its objectDefinitions instance.
The objectDefinitions instance is an anonymous object that serves as a Name->IObjectDefinition lookup for the definitions
that are created by the MXMLObjectDefinitionsProvider. So an ICustomObjectDefinitionComponent implementation can just add its own
definitions to this instance.
No implementations are yet available in Spring Actionscript 2.0, but we're planning to create some shortcuts for the eventhandling and interception, similar to the XML shortcuts described in part II of this progress report.

Metadata Application Context

Lastly, there is the MetadataApplicationContext, which does exactly as its name suggests: It creates ObjectDefinitions that are defined in metadata. This ApplicationContext needs to have its rootView set, this is because it uses this rootView to resolve the correct loaderInfo reference which is used to scan the SWF's bytecode for the necessary metadata annotations. So, if the MetadataApplicationContext is part of a regular application, this would suffice:
var context:MetadataApplicationContext = new MetadataApplicationContext(Application(FlexGlobals.topLevelApplication));
context.addEventListener(Event.COMPLETE,onComplete);
context.load();
The metadata hasn't changed, you can check out the existing doc sections for
it: Spring Actionscript Component Scan.
Only one addition has been made actually, it is now also possible to define an external properties file in metadata. To do so annotate any class in your project with the following metadata:
[ExternalProperties(location="properties.txt")]
public final class ConfigurationClass {
}
Naturally, you can also add required='true' or preventCache='false' to the metadata arguments.

spring-actionscript-flex.swc

As promised, all Flex specific functionality is now part of a separate .swc.
So in order to use the MXMLApplicationContext you will need to add the spring-actionscript-flex.swc to your library path. The library also offers some extra namespace handlers that target flex specific classes. So in order to easily use those they have been packaged in an IConfigurationPackage implementation called FullFlexXMLConfigurationPackage.
As described in part II of this progress report, you can add such a configuration package using the configure() method on the application context:
var context:XMLApplicationContext = new XMLApplicationContext();
context.configure(new FullFlexXMLConfigurationPackage());

Creating a build

The SVN repository has changed a little bit, so in order to create your own beta build things have changed slightly. First, check out this directory from the Spring SVN repository:
In the checked out directory simple run this maven command: mvn clean compile in order to create a build.
Run mvn clean test to run the unit tests.
You will find the spring-actionscript-core and spring-actionscript-flex .swc's in their respective subdirectories. (spring-actionscript-core/target and spring-actionscript-flex/target)

In the near future...

Next up there's still a number of unit tests to be ported from Spring Actionscript 1.x. After that the documentation site will be overhauled. The current site is very rich in information but we feel it needs to be organised better into smaller bite-sized chunks that might be easier to digest for developer's who are new to the framework.
So we'll try and make a couple of 'Getting started' pages without immediately throwing every detail of the framework into the casual reader's face.
We'll try and get http://beta.springactionscript.org up and running as soon as possible.

In the further future...

We are in the planning stages of AOP support. In the past year we have been working hard on as3commons-bytecode which is the library that provides the most low-level support for AOP functionality, namely the creation of dynamic proxy classes and the dynamic manipulation of existing classes.
Next we will release an as3commons project called as3commons-aop which will provide a foundational library offering advice and aspect interfaces, a pointcut scanning system combined with an expression dialect. The template for this will naturally be Spring AOP, but we will try to make the foundational library framework agnostic enough so that other frameworks might use it as well.
This AOP library will then be used to implement the eventual Spring Actionscript AOP support.
All of this is a huge task which is mostly done in our spare time, so naturally we can't give you any release schedule... :)
Any help, however, is always welcome. So if you feel up for it, contact us either at as3commons.org or springactionscript.org (depending on what you'd like to do) and we'll see how we can help eachother out.
And like previous posts, we'd love to hear feedback from you. So any criticisms, ideas, suggestions are more than welcome.

Happy coding!