Thursday, March 29, 2012

Released: AS3Commons-Bytecode v1.1!

Just a quick heads-up here: We have just released version 1.1 of AS3Commons-Bytecode:

Download Page

Documentation has been updated a little bit as well:

Proxy docs

Christophe has been getting his hands dirty in this release as well, he's managed to squash some last bugs that paved the way for the v1.1 release. So thanks a lot for his blood, sweat, tears and sanity ;)

We have added some extra speed optimizations in the ByteCodeType parser. This is, of course, an ongoing process, every time we find some new tricks we implement them. The speed improvements are only slight this time, but every millisecond counts :)
I did a simple test where I invoke a ByteCodeType.fromLoader() in an AIR application with all framework libraries included (which results in about a 2MB SWF mainly consisting of class information) which took about 2225 ms to complete in debug mode.

Furthermore, we have improved the proxying of getters, it now works properly actually ;)
In version 1.0 it was impossible to receive a reference to the getter function itself and pass it on to the interceptors. This was due to a technical limitation at the opcode level, where it is also impossible to get a reference to the actual getter function. So, what the proxy factory now does is create a custom namespaced method in the proxy class that basically does this:

Imagine your proxied class has a getter called 'name':

public function get name():String {
  return _name;
}

AS3Commons-Bytecode v1.1 will then generate an extra method on the proxy class that looks like this:

as3commons_bytecode function getter_name():String {
  return super.name;
}

After that, in the overridden getter method the function getName() will be passed into into the interceptors. That way the interceptors themselves can choose to invoke the getter or not, or at least determine at which time the getter will be invoked.

An important note has been added to the proxy documentation as well, concerning the ApplicationDomain reference that needs to be passed in to the defineProxy() method.

ByteCodeType now caches its type info per application domain (when before it only kept one cache). This allows the library to cache different type info for different app domains that potentially could share the same names.

So, it is very important to pass the correct ApplicationDomain reference into defineProxy(), otherwise the ProxyFactory won't be able to find the appropariate ByteCodeType info.
This ApplicationDomain needs to be the same reference as the loaderInfo.applicationDomain property that was passed into ByteCodeType.fromLoader().

It sounds more complicated than it is actually. What you do is simply keep a reference to loaderInfo.applicationDomain, and use that in each invocation of defineProxy().
Existing code that makes use of AS3Commons-bytecode 1.0 probably doesn't do this yet, so if you experience errors after upgrading to version 1.1, this is probably what's going on. The fix is fairly simple, as explained.

At the same time work is very slowly progressing on as3commons-aop as well, we have no idea yet when it'll see an official release, but the website will be up soon, we promise ;)

AS3Commons is busy with some other new project releases as well, projects donated by the likes of Claus Wahler and Brian Riley, so these are exciting times for the project!

That was all, happy coding to everyone!

cheers,

Roland

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