Showing posts with label progress. Show all posts
Showing posts with label progress. Show all posts

Monday, March 5, 2012

Spring Actionscript 2.0 Progress Report - Part IV

Well, hello there!
Time for another progress report on the ongoing development of Spring Actionscript version 2.0. I think we're inching towards a true beta version, once I think we're feature-complete that'll happen. But not just yet. :)
So far I do encourage people to start using the library, right now within my company Stack & Heap we've been using version 2.0 in at least three of our current projects and things are running very smoothly.
Let's run through the new stuff that has been added, changed or improved.

Lazy dependency injection
This is a feature that I needed in my current project. Basically I stumbled upon a use-case where the container needed to instantiate an object that has a dependency on another object that isn't available yet at container startup.
The object in question is retrieved from the server and needs to be injected into that particular object.
Of course, its possible to just inject the instance from within the presentationmodel that performs the service call, but things get more interesting if more than one object has a dependency on the server object. And what if the server object itself needs to receive injections as well?

It would be a lot nicer to be able to just define an object definition for this server object and, once it has arrived from the server, hand it over to the container and let it handle it from there.

New Object Definition Scopes
In order to facilitate the configuration for lazy dependencies we decided to add some extra scopes to the ObjectDefinitionScope enumeration. The new scopes are:
  • ObjectDefinitionScope.STAGE
  • ObjectDefinitionScope.REMOTE
The first one, ObjectDefinitionScope.STAGE, was added to indicate that an object definition is associated with a stage component. (doh...) Before, we recommended to set the scope to ObjectDefinitionScope.PROTOTYPE for such definitions, to make sure the component didn't get instantiated as a singleton unnecessarily. But this new scope will hopefully add some clarity to the configuration.

The second one, ObjectDefinitionScope.REMOTE, is meant for the server objects I mentioned. So, the object definition is added to the configuration just as any other, with the exception that the scope is set to the aforementioned value:

 <sas:Object id="myServerObject" scope="remote" clazz="MyServerObjectClass"/>  

Now, after the object has been retrieved from the server (or any other origin than the container) it needs to be added to the container. For this you can use the manage() method on the application context:

 applicationContext.manage(serverObject);

The object definition that is associated with the instance will be looked up by type in the container. If no class can be defined in the configuration (because the class isn't available at startup for instance) its also possible to define the definition id as an optional argument:

 applicationContext.manage(serverObject, "myServerObject");

After this invocation any already existing object instances that have a dependency on myServerObject will be injected with the server object.

EventBus Configuration
As reported before, eventbus configuration can be added to the object definition in version 2.0. The original MXML config looked like this:

 <sas:Object id="dispatcher" clazz="MyDispatchingClass"/>

 <sas:EventRouter instance="dispatcher">  
  <sas:EventRouterConfiguration eventNames="{MyEventClass.SOME_TYPE}"/>  
 </sas:EventRouter>  

This has been simplified slightly, its now possible to just nest the event routing configuration directly with the object definition:

 <sas:Object id="dispatcher" clazz="MyDispatchingClass">  
  <sas:EventRouterConfiguration eventNames="{MyEventClass.SOME_TYPE}"/>  
 </sas:Object>  

Same works for event handling configuration:

  <sas:Object id="handler" clazz="{MyHandlingClass}">   
  <sas:EventHandlerMethod name="eventHandlerMethod"  
   eventName="{MyEventClass.SOME_TYPE}"/>  
  </sas:Object>  
That ought to make the overall configuration a little more concise and readable, I hope.

Context Customization
it is now possible swap out most of the internals of the object factory by adding custom implementations of the following interfaces to the configuration:
  • IDependencyInjector
  • IEventBus
  • IObjectDestroyer
  • IAutowireProcessor
Hopefully this will enable Spring Actionscript users to support more unusual use-cases that the default container logic isn't prepared for.

ApplicationPropertiesObjectFactoryPostProcessor
This processor is already present in the Spring Actionscript v1.0 and now ported to version 2.0. (Thanks @herrodius)
It enables the MXMLApplicationContext to inject a number of Application properties into its managed objects. The following properties are available:


  • application.frameRate
  • application.historyManagementEnabled
  • application.pageTitle
  • application.resetHistory
  • application.scriptRecursionLimit
  • application.scriptTimeLimit
  • application.url
  • application.url.protocol
  • application.url.host
  • application.url.port
  • application.usePreloader
  • application.viewSourceURL
And besides those, any application parameters will be added by name as well. So if the a parameter called myAppVar is passed into the application it will be available as an external property by the name of application.myAppVar.
To inject these values into an object add them into the configuration like this:

 <sas:Object id="myClass" clazz="{MyClass}">  
  <sas:Property name="frameRate" value="$(application.frameRate)"/>  
 </sas:Object>  

Default Definition Properties
Object definitions have, hopefully, sensible defaults. But we've added some shortcuts to enable you to change those without having to set these properties on every definition in the configuration.
The <sas:SASObjects/> element now has a number of the same properties as the IObjectDefinition which will be inherited by any definition within that config:
  • autoWireMode
  • childContextAccess
  • dependencyCheck
  • destroyMethod
  • factoryMethod
  • factoryObjectName
  • initMethod
  • isAutoWireCandidate
  • isLazyInit
  • parentName
  • scope
  • skipMetadata
  • skipPostProcessors
For now this is only implemented in the MXML configuration, but naturally this will also be implemented in the XML and metadata versions.

In Conclusion
Those are the newest features (I hope I haven't forgotten any actually...), apart from those, there have been quite a number of bugfixes and optimizations. The autowiring has been sped up quite a bit, as well as the dependency checker. Furthermore, my colleague @bertvandamme fixed a particularly nasty bug in the popup injection logic which would screw up the FocusManager for modal popups. Good times! :)

I haven't gotten round to updating the Spring Actionscript 2.0 documentation yet, but hopefully I'll be able to add some more to that in the near future.

New snapshots have been deployed to the maven repository as per usual.

Here are the forums if you'd like to discuss anything in public:
Spring Actionscript forum

You can follow me on twitter: @mechhead
Or follow Spring Actionscript: @springas

Our JIRA bugbase can be reached here:
SpringSource JIRA

And that's all folks, until next time, happy coding!

cheers,

Roland

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!