autowire non visual objects not defined in context

7 views
Skip to first unread message

Piergiorgio Niero

unread,
Jan 22, 2010, 8:33:02 AM1/22/10
to springactionscript-dev
Hi there,
I tried to autowire non visual object instantiated at runtime but I
didn't find that capability in the framework (am I wrong?), so I wrote
a class in order to do this. (I'm using puremvc extensions, just make
container return current application context to make it run without
puremvc )

here's the code:

package
{
import flash.utils.describeType;

import org.as3commons.lang.ClassUtils;
import org.puremvc.as3.patterns.facade.Facade;
import
org.springextensions.actionscript.context.IConfigurableApplicationContext;
import
org.springextensions.actionscript.puremvc.interfaces.IIocFacade;

/**
* This class provides autowiring for subclasses.
*
* @author pigiuz
*
*/
public class AutowiringObjectBase
{
private var _iocFacade:IIocFacade;

public function AutowiringObjectBase()
{
_iocFacade = Facade.getInstance() as IIocFacade;
autoWire();
}

private function get container
():IConfigurableApplicationContext
{
return _iocFacade.container;
}

private function autoWire():void
{
var typeDescription:XML = describeType(this);
for each (var metaDataNode:XML in
typeDescription..metadata)
{
if (metaDataNode.attribute("name") == "Autowired")
{
var host:String;
var chain:String;
var propertyNode:XML = metaDataNode.parent();
var property:String = propertyNode.@name.toString
();
trace("Found Autowired property: " + property);
var objectName:String = property;
var autowireByType:Boolean = true;

for each (var arg:XML in metaDataNode.arg)
{
if (arg.attribute("key") == "host")
{
host = arg.attribute("value")
}
else if (arg.attribute("key") == "chain")
{
chain = arg.attribute("value");
}
else if (arg.attribute("value") == "byName")
{
autowireByType = false;
}
}
if (autowireByType)
{
if (host && chain)
{
// CHAINED AUTOWIRE
trace("Autowiring: " + property + " in " +
this + " from " + host + "." + chain);
var hostObject:Object = container.getObject
(host);
if (hostObject)
{
this[property] = hostObject[chain];
}
}
else
{
// AUTOWIRE BY TYPE
var clazz:Class = ClassUtils.forName
(propertyNode.@type.toString());
var objectNames:Array =
container.getObjectNamesForType(clazz);
if (objectNames.length == 1)
{
objectName = objectNames[0];
}
trace("Autowiring by type: " + property +
" in " + this);
this[property] = container.getObject
(objectName);
}
}
else
{

// AUTOWIRE BY NAME
trace("Autowiring by name:" + property + " in
" + this);
this[property] = container.getObject
(objectName);
}
propertyNode = null;
host = null;
chain = null;
}
metaDataNode = null;
}
// dispose describetype
typeDescription = null;
}


}
}


you can find some more explanations in this post on my blog:
http://www.flashfuck.it/2010/01/21/spring-actionscript-autowire-objects-not-defined-in-context/

is there any better way to do this, or any issues generated by doing
this?

byez
Piergiorgio Niero

Roland

unread,
Jan 22, 2010, 8:41:09 AM1/22/10
to springactionscript-dev
Hey Piergiorgio,

I left a comment on your blog regarding your question, hope it helps a
little.

cheers,

Roland

On Jan 22, 2:33 pm, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

>                     var property:String = propertyNo...@name.toString


> ();
>                     trace("Found Autowired property: " + property);
>                     var objectName:String = property;
>                     var autowireByType:Boolean = true;
>
>                     for each (var arg:XML in metaDataNode.arg)
>                     {
>                         if (arg.attribute("key") == "host")
>                         {
>                             host = arg.attribute("value")
>                         }
>                         else if (arg.attribute("key") == "chain")
>                         {
>                             chain = arg.attribute("value");
>                         }
>                         else if (arg.attribute("value") == "byName")
>                         {
>                             autowireByType = false;
>                         }
>                     }
>                     if (autowireByType)
>                     {
>                         if (host && chain)
>                         {
>                             // CHAINED AUTOWIRE
>                             trace("Autowiring: " + property + " in " +
> this + " from " + host + "." + chain);
>                             var hostObject:Object = container.getObject
> (host);
>                             if (hostObject)
>                             {
>                                 this[property] = hostObject[chain];
>                             }
>                         }
>                         else
>                         {
>                             // AUTOWIRE BY TYPE
>                             var clazz:Class = ClassUtils.forName

> (propertyNo...@type.toString());


>                             var objectNames:Array =
> container.getObjectNamesForType(clazz);
>                             if (objectNames.length == 1)
>                             {
>                                 objectName = objectNames[0];
>                             }
>                             trace("Autowiring by type: " + property +
> " in " + this);
>                             this[property] = container.getObject
> (objectName);
>                         }
>                     }
>                     else
>                     {
>
>                         // AUTOWIRE BY NAME
>                         trace("Autowiring by name:" + property + " in
> " + this);
>                         this[property] = container.getObject
> (objectName);
>                     }
>                     propertyNode = null;
>                                         host = null;
>                                         chain = null;
>                 }
>                 metaDataNode = null;
>             }
>             // dispose describetype
>             typeDescription = null;
>         }
>
>     }
>
> }
>

> you can find some more explanations in this post on my blog:http://www.flashfuck.it/2010/01/21/spring-actionscript-autowire-objec...

Piergiorgio Niero

unread,
Jan 22, 2010, 9:09:42 AM1/22/10
to springactio...@googlegroups.com
thank you for your comment roland,
however maybe my explanation wasn't so good, let me try to explain better :)

I know I can autowire properties in that way but that approach does not fit to my scenario:

I need to creare N instances of a class without having to define those objects on context.

think about this:
for (var i:int=0;i<n;i++){
 new MyAutowiringClass();
}
if MyAutoWiringClass extends AutowiringObjectBase (the class I posted before) and has some properties marked as [Autowired] those properties are injected automatically and I did not write 1 line of xml on the context.


--
You received this message because you are subscribed to the Google Groups "springactionscript-dev" group.
To post to this group, send email to springactio...@googlegroups.com.
To unsubscribe from this group, send email to springactionscrip...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/springactionscript-dev?hl=en.


Piergiorgio Niero 






Roland

unread,
Jan 23, 2010, 1:57:18 PM1/23/10
to springactionscript-dev
Hey Piergiorgio,

while your solution works, there are however a few points of criticism
I have.
First of all, having to inherit from a single monolithic base class to
handle annotated
injections might be feasible in a small project, it doesn't scale very
well. You'd end up
with a whole bunch of base classes that basically all do the same
thing, expose the
application context to its instance. Plus the Facade.getInstance()
invocation is something
you'd want to get rid of as soon as possible since this tightly
couples your code to a singleton
which makes it harder to unit test.
I will add however that the current incarnation of Spring Actionscript
(v0.8.1) doesn't offer you
a mechanism that could make things workable for you. However, I'm
thinking of adding a new
method to the application context: getInstance(class:Class);
This method could instantiate the specified class and pass it directly
into the wire() method of the
context, that way all injections will be performed based on its
annotations again.
Your code would end up looking like this:

for (var i:int=0;i<n;i++){

applicationContext.getInstance(MyAutowiringClass);
}

Does anyone else on the list have any ideas on this? Please feel free
to chime in...
Would getInstance() be a suitable name? Or would createInstance() be
better?

cheers,

Roland

On 22 jan, 15:09, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

> > For more options, visit this group athttp://groups.google.com/group/springactionscript-dev?hl=en.

Piergiorgio Niero

unread,
Jan 25, 2010, 4:18:58 AM1/25/10
to springactio...@googlegroups.com
Ciao Roland :)

I agree with what you underlined, depending on a singleton is a real pain in the ass and it's not the best solution.
In the class I posted I used a IocFacade in order to have a quick access to the applicationContext, I absolutely agree with you on the applicationContext.createInstance method :)

PS: i'm for createInstance, getInstance reminds me a singleton getter

looking forward for the new method :)
ciao
Piergiorgio


Roland

unread,
Feb 3, 2010, 5:31:10 AM2/3/10
to springactionscript-dev
Hey Piergiorgio (damn, that name is hard to spell, hehe),

I've added this method to the IObjectFactory interface:

public function createInstance(clazz:Class, constructorArguments:Array
= null):*;

your code would now look like this:

for (var i:int=0;i<n;i++){

applicationContext.createInstance(MyAutowiringClass);
}

And you no longer will need the base class to handle the injections.

Changes are available in the trunk.

On 25 jan, 10:18, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

Piergiorgio Niero

unread,
Feb 3, 2010, 6:10:00 AM2/3/10
to springactio...@googlegroups.com
good to know!
i'll update soon the post on my blog with this new feature (and my code too! :))

ciao
Piergiorgio

ps: my name is something like "peter-george" in italian, it's not so hard!!c'mooon!!! :D


pix303

unread,
Feb 4, 2010, 4:37:04 AM2/4/10
to springactionscript-dev
Hi Piergiorgio and Roland

I follow your interesting thread and, for better understand the way to
use springas, i have some questions:
- the vantage of using createInstance() method is that the
"MyAutowiringClass" doesn't need to be defiend in the application
context?
- the autowired properties of MyAutowiringClass don't need to be
defiend in the application context?
- doesn't createInstance() couple the MyAutowiringClass with the
factory class?

In a similar scenario i implement my factory class with
IApplicationContextAware interface in order to use the
IApplicationContext.getObject; of course my objects are defined in the
context with lazy-init attribute set to true and it cant be seen as a
vantage when you have to manage many object.

Thanks for answers and suggestions.

Paolo

On 3 Feb, 12:10, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

> ...
>
> leggi tutto

pix303

unread,
Feb 4, 2010, 4:36:21 AM2/4/10
to springactionscript-dev
Hi Piergiorgio and Roland

I follow your interesting thread and, for better understand the way to
use springas, i have some questions:
- the vantage of using createInstance() method is that the
"MyAutowiringClass" doesn't need to be defiend in the application
context?
- the autowired properties of MyAutowiringClass don't need to be
defiend in the application context?
- doesn't createInstance() couple the MyAutowiringClass with the
factory class?

In a similar scenario i implement my factory class with
IApplicationContextAware interface in order to use the
IApplicationContext.getObject; of course my objects are defined in the
context with lazy-init attribute set to true and it cant be seen as a
vantage when you have to manage many object.

Thanks for answers and suggestions.

Paolo


On 3 Feb, 12:10, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

Roland

unread,
Feb 4, 2010, 5:01:57 AM2/4/10
to springactionscript-dev
Hey there Paolo,

you're correct in your first two assumptions, the createInstance()
method allows you
to create an instance of a specified Class that has been annotated
with [Autowired] metadata.
For this class there does not need to be an ObjectDefinition present
in the container, since
all injections are defined in the metadata.
I don't agree with the last point though, I don't believe the
MyAutowiringClass class would be tightly
coupled to the factory. Coupled to a certain extent, yes, but
loosely :) The only coupling to Spring
Actionscript would be the metadata, but there's nothing from stopping
a different library from interpreting
the exact same metadata and performing the injections.
Using the metadata is indeed more of a coupling between class and
factory then using pure XML based
object definitions. There's proponents and opponents of both ways,
Spring Actionscript just offers them both
so everybody stays happy :)

cheers,

Roland

> ...
>
> read more »

pix303

unread,
Feb 5, 2010, 3:52:31 AM2/5/10
to springactionscript-dev
I made a sample app and i tested the usefulness of createInstance().
Using annotations it seems to be more consistent.
I'm agree about the third point (the coupling is still weak) but the
answer to 2nd question, i think, it'is no: all the autowired
properties of MyAutowiringClass have to be defined on the app-
context.xml.

regards

paolo

> ...
>
> leggi tutto

Piergiorgio Niero

unread,
Feb 5, 2010, 4:02:50 AM2/5/10
to springactio...@googlegroups.com
Ciao Paolo,
I think this method is great because of the decoupling from the context.
I mean: if I'd have to define every property to autowire in the context I'd be strictly coupled to it.
What I needed for my purposes was to be able to instantiate a class at runtime
as many times as I want without depending on the context, this means you leverage what you defined 
on the context but you do not have to add further configurations, further, you reuse the same syntax you use for visual objects (I mean the [Autowired] metatag).
my 2 cents,
Piergiorgio


ps: italiano?



--
You received this message because you are subscribed to the Google Groups "springactionscript-dev" group.
To post to this group, send email to springactio...@googlegroups.com.
To unsubscribe from this group, send email to springactionscrip...@googlegroups.com.

Roland

unread,
Feb 5, 2010, 4:20:57 AM2/5/10
to springactionscript-dev
Hmm,

while I agree that it serves to be researched to be able to define all
types of dependency in Metadata, I do not
agree that defining your dependencies in XML is a strict coupling of
your classes. It might a coupling of
your DEPENDENCIES, but that is a different discussion :)
The primary advantage of defining your dependencies in XML is that tey
can be changed without having to
re-compile your application, in some cases this can prove incredibly
useful. The XML is not necessarily
coupled to one implementation of an application context, just like the
metadata is not coupled to a specific
implementation.
Piergiorgio, in your case, defining your dependencies in metadata is
only a *different* way of doing this
compared to creating object definitions for them, either way, these
dependencies need to be defined *somewhere*. :)

But like I said, being able to completely define dependencies in
metadata sounds like a viable plan, its not easy
I must say, the component scan mechanism already does this to a
certain extent. This has proved to be quite slow
though, plus I recently noticed that the class name extraction
functionality seems to be throwing errors in Flex4
generated swf's. So for now, it's still very much prototypical :)

Anyways, let's be clear about one thing, this functionality will not
make it for the version 1.0 release.
But, after that, it is certainly an avenue we will explore further,
since its very obvious that there are metadata fans and
XML fans alike, and we would like to keep everyone happy :)

I will create a JIRA ticket for this so it will end up on the roadmap.

thank you bother for your input!

cheers,

Roland

On Feb 5, 10:02 am, Piergiorgio Niero <piergiorgio.ni...@gmail.com>

> ...
>
> read more »

pix303

unread,
Feb 5, 2010, 4:39:41 AM2/5/10
to springactionscript-dev
On 5 Feb, 10:02, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

Ok, i'm agree. But you depend on context.xml to define all the common
class/properties that others classes pick up by annotations. is it
correct? or i miss something?
I think it can be very useful when you have to factory many different
types that share common object (model, manager, ecc), dont you?


Sì sono italiano... se ti fa piacere eventualmente mi piacerebbe
scambiare qualche parere anche in lingua (sono un po' duro di
comprendonio e non vorrei intepretare male o essere intepretato
male :)

Paolo

> ...
>
> leggi tutto

Piergiorgio Niero

unread,
Feb 5, 2010, 4:57:15 AM2/5/10
to springactio...@googlegroups.com
yes,
you always depend on the context to define your dependencies,
for example, if your class (to be created through createInstance())
has a property "myProperty" which is marked to be autowired
you NEED to have the definition of myProperty type (or name if you autowire by name)
in your context. what you don't need (imho) is to have to define every property to be autowired on the context.

I mean:
if your class Test has the property 

[Autowired]
public var myProperty:IMyTestClass;

your context must contain the definition of "myProperty" as <object>
otherwise autowiring will fail.

what you do not need is to have the definition of a Test class object in your context.

Piergiorgio


ps: bene! :)
se vuoi beccami in pvt o entra nella lista dell'ug (c'è il link nella firma) così ne parliamo in lingua anche con altra gente magari


--
You received this message because you are subscribed to the Google Groups "springactionscript-dev" group.
To post to this group, send email to springactio...@googlegroups.com.
To unsubscribe from this group, send email to springactionscrip...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/springactionscript-dev?hl=en.

pix303

unread,
Feb 5, 2010, 5:11:04 AM2/5/10
to springactionscript-dev
ok! now it's clear ;)

On 5 Feb, 10:57, Piergiorgio Niero <piergiorgio.ni...@gmail.com>
wrote:

> ...
>
> leggi tutto

Reply all
Reply to author
Forward
0 new messages