Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: Manual Configuration, and existing instances

  1. #11
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default np

    glad to help, lemme know how you're faring.

    later,

    ROland

    P.S. Oh, and do check out http://www.springactionscript.org again, its just had a huge update today with the latest version of all the docs.
    Last edited by 666shooter; Jul 15th, 2009 at 11:00 AM. Reason: added URL

  2. #12
    Join Date
    Feb 2009
    Location
    Cape Town, South Africa
    Posts
    21

    Default Success! mostly..

    Woop!

    So, I managed to get my Injection adapter working a little while ago.. for the most part.

    useValue is sorted out (extending DefaultListableObjectFactory and throwing the value/instance in the singletonCache worked perfectly), but now I'm having trouble with the singletons: dependencies aren't being injected on lazily instantiated singletons.

    In essence I think it comes down to this: things work out when I instantiate objects and then inject into them manually (using injectInto), but objects that get constructed by the Spring container, don't end up having their dependencies resolved - Spring obviously ignores my [Inject] annotations.

    I tried to work around this by inspecting class metadata for dependencies when I set up injection rules through my adapter. But how Spring is supposed to figure out my named injection points I'm not sure

    Here's how it's looking:

    Code:
    package net.boyblack.robotlegs.adapters
    {
        import net.boyblack.robotlegs.core.IInjector;
    
        import org.as3commons.lang.ClassUtils;
        import org.as3commons.lang.ObjectUtils;
        import org.as3commons.reflect.Field;
        import org.as3commons.reflect.MetaData;
        import org.as3commons.reflect.Type;
        import org.springextensions.actionscript.ioc.ObjectDefinition;
        import org.springextensions.actionscript.ioc.ObjectDefinitionScope;
        import org.springextensions.actionscript.ioc.factory.support.RobotLegsObjectFactory;
    
        public class SpringInjector implements IInjector
        {
            protected var factory:RobotLegsObjectFactory;
    
            public function SpringInjector()
            {
                factory = new RobotLegsObjectFactory();
            }
    
            public function bindValue(whenAskedFor:Class, useValue:Object, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ObjectUtils.getFullyQualifiedClassName(useValue);
                var key:String = named ? named : whenAskedForClassName;
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON);
                factory.cacheSingletonValue(key, useValue);
            }
    
            public function bindClass(whenAskedFor:Class, instantiateClass:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ClassUtils.getFullyQualifiedName(instantiateClass);
                var dependencies:Array = findDependencies(instantiateClass);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.PROTOTYPE, dependencies);
            }
    
            public function bindSingleton(whenAskedFor:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = whenAskedForClassName;
                var dependencies:Array = findDependencies(whenAskedFor);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON, dependencies);
            }
    
            public function bindSingletonOf(whenAskedFor:Class, useSingletonOf:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ClassUtils.getFullyQualifiedName(useSingletonOf);
                var dependencies:Array = findDependencies(useSingletonOf);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON, dependencies);
            }
    
            public function injectInto(target:Object):void
            {
                var type:Type = Type.forInstance(target);
                var fields:Array = type.fields;
                for each (var field:Field in fields)
                {
                    if (field.hasMetaData('Inject'))
                    {
                        var named:String = null;
                        var mds:Array = field.getMetaData('Inject');
                        for each (var md:MetaData in mds)
                        {
                            if (md.hasArgumentWithKey('name'))
                            {
                                named = md.getArgument('name').value;
                                break;
                            }
                            else if (md.hasArgumentWithKey('id'))
                            {
                                named = md.getArgument('id').value;
                                break;
                            }
                        }
                        named = named ? named : field.type.fullName;
                        target[field.name] = factory.getObject(named);
                    }
                }
            }
    
            public function unbind(clazz:Class, named:String = null):void
            {
                named = named ? named : ClassUtils.getFullyQualifiedName(clazz);
                factory.removeObjectDefinition(named);
            }
    
            protected function registerObjectDefinition(whenAskedForClassName:String, useClassName:String, named:String, scope:ObjectDefinitionScope, dependencies:Array = null):void
            {
                var objdef:ObjectDefinition = new ObjectDefinition(useClassName);
                var key:String = named ? named : whenAskedForClassName;
                objdef.dependsOn = dependencies ? dependencies : objdef.dependsOn;
                objdef.scope = scope;
                factory.registerObjectDefinition(key, objdef);
            }
    
            protected function findDependencies(clazz:Class):Array
            {
                var type:Type = Type.forClass(clazz);
                var fields:Array = type.fields;
                var dependencies:Array = new Array();
                for each (var field:Field in fields)
                {
                    if (field.hasMetaData('Inject'))
                    {
                        var named:String = null;
                        var mds:Array = field.getMetaData('Inject');
                        for each (var md:MetaData in mds)
                        {
                            if (md.hasArgumentWithKey('name'))
                            {
                                named = md.getArgument('name').value;
                                break;
                            }
                            else if (md.hasArgumentWithKey('id'))
                            {
                                named = md.getArgument('id').value;
                                break;
                            }
                        }
                        named = named ? named : field.type.fullName;
                        dependencies.push(named);
                    }
                }
                trace('dependencies for ' + clazz + ' : ' + dependencies);
                return dependencies;
            }
    
        }
    }

  3. #13
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default IOBjectDefinition

    You will have to construct those dependencies yourself and add them to the objectdefinition.
    So, take a good look at the ObjectDefinition sources, all dependency and injection information can be stored in there.
    One thing you have remember, if you are injecting another object (one that is managed by your container) into a property or whatever, add this to the ObjectDefinition as a RuntimeObjectReference. This is an implementation of the IObjectReference interface, which only needs to have one property: objectName.
    This objectName is the name with which an object is registered in the container, by adding using this RuntimeObjectReference in your ObjectDefinitions the container will understand that it needs to retrieve the object from itself, through the usual getObject() pipeline.

    I created a graphical view of the getObject flow in the reference docs:

    http://www.springactionscript.org/docs/reference/html/container-documentation.html#a_graphical_overview_of_the_get object_flow


    I hope this helps, good luck to you,


    Roland
    Last edited by 666shooter; Jul 16th, 2009 at 03:15 AM. Reason: added API reference links

  4. #14
    Join Date
    Feb 2009
    Location
    Cape Town, South Africa
    Posts
    21

    Default RuntimeObjectReference

    Thank you Roland, you rock! All I needed to do was set some RuntimeObjectReferences on the properties object of the ObjectDefinition.

    For anyone who's interested, here's how to use Spring "Guice/SmartyPants style" (I'm sure it can be improved though):

    Code:
    package net.boyblack.robotlegs.adapters
    {
        import net.boyblack.robotlegs.core.IInjector;
        
        import org.as3commons.lang.ClassUtils;
        import org.as3commons.lang.ObjectUtils;
        import org.as3commons.reflect.Field;
        import org.as3commons.reflect.MetaData;
        import org.as3commons.reflect.Type;
        import org.springextensions.actionscript.ioc.ObjectDefinition;
        import org.springextensions.actionscript.ioc.ObjectDefinitionScope;
        import org.springextensions.actionscript.ioc.factory.config.RuntimeObjectReference;
        import org.springextensions.actionscript.ioc.factory.support.RobotLegsObjectFactory;
    
        public class SpringInjector implements IInjector
        {
            protected var factory:RobotLegsObjectFactory;
    
            public function SpringInjector()
            {
                factory = new RobotLegsObjectFactory();
            }
    
            public function bindValue(whenAskedFor:Class, useValue:Object, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ObjectUtils.getFullyQualifiedClassName(useValue);
                var key:String = named ? named : whenAskedForClassName;
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON);
                factory.cacheSingletonValue(key, useValue);
            }
    
            public function bindClass(whenAskedFor:Class, instantiateClass:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ClassUtils.getFullyQualifiedName(instantiateClass);
                var properties:Object = findProperties(instantiateClass);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.PROTOTYPE, properties);
            }
    
            public function bindSingleton(whenAskedFor:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = whenAskedForClassName;
                var properties:Object = findProperties(whenAskedFor);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON, properties);
            }
    
            public function bindSingletonOf(whenAskedFor:Class, useSingletonOf:Class, named:String = null):void
            {
                var whenAskedForClassName:String = ClassUtils.getFullyQualifiedName(whenAskedFor);
                var useClassName:String = ClassUtils.getFullyQualifiedName(useSingletonOf);
                var properties:Object = findProperties(useSingletonOf);
                registerObjectDefinition(whenAskedForClassName, useClassName, named, ObjectDefinitionScope.SINGLETON, properties);
            }
    
            public function injectInto(target:Object):void
            {
                var type:Type = Type.forInstance(target);
                var fields:Array = type.fields;
                for each (var field:Field in fields)
                {
                    if (field.hasMetaData('Inject'))
                    {
                        var named:String = null;
                        var mds:Array = field.getMetaData('Inject');
                        for each (var md:MetaData in mds)
                        {
                            if (md.hasArgumentWithKey('name'))
                            {
                                named = md.getArgument('name').value;
                                break;
                            }
                            else if (md.hasArgumentWithKey('id'))
                            {
                                named = md.getArgument('id').value;
                                break;
                            }
                        }
                        named = named ? named : field.type.fullName;
                        target[field.name] = factory.getObject(named);
                    }
                }
            }
    
            public function unbind(clazz:Class, named:String = null):void
            {
                named = named ? named : ClassUtils.getFullyQualifiedName(clazz);
                factory.removeObjectDefinition(named);
            }
    
            protected function registerObjectDefinition(whenAskedForClassName:String, useClassName:String, named:String, scope:ObjectDefinitionScope, properties:Object = null):void
            {
                var objdef:ObjectDefinition = new ObjectDefinition(useClassName);
                var key:String = named ? named : whenAskedForClassName;
                objdef.properties = properties ? properties : objdef.properties;
                objdef.scope = scope;
                factory.registerObjectDefinition(key, objdef);
            }
    
            protected function findProperties(clazz:Class):Object
            {
                var type:Type = Type.forClass(clazz);
                var fields:Array = type.fields;
                var properties:Object = new Object();
                for each (var field:Field in fields)
                {
                    if (field.hasMetaData('Inject'))
                    {
                        var named:String = null;
                        var mds:Array = field.getMetaData('Inject');
                        for each (var md:MetaData in mds)
                        {
                            if (md.hasArgumentWithKey('name'))
                            {
                                named = md.getArgument('name').value;
                                break;
                            }
                            else if (md.hasArgumentWithKey('id'))
                            {
                                named = md.getArgument('id').value;
                                break;
                            }
                        }
                        named = named ? named : field.type.fullName;
                        properties[field.name] = new RuntimeObjectReference(named);
                    }
                }
                return properties;
            }
    
        }
    }
    And the Object Factory:

    Code:
    package org.springextensions.actionscript.ioc.factory.support
    {
        import org.springextensions.actionscript.ioc.IObjectDefinition;
    
        public class RobotLegsObjectFactory extends DefaultListableObjectFactory
        {
            public function RobotLegsObjectFactory()
            {
                super();
            }
    
            public function cacheSingletonValue(objectName:String, value:Object):void
            {
                singletonCache[objectName] = value;
            }
    
        }
    }
    Last edited by drscn; Jul 16th, 2009 at 07:59 AM. Reason: To add Object Factory definition

  5. #15
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default congrats!

    Hey Shaun,

    I'm happy to see you got everything working fairly quickly, cheers on that!

    I already had a feeling you were the Shaun from 'RobotLegs' fame Really nice to see this type of integration, thanks!

    greets,

    Roland

  6. #16
    Join Date
    Feb 2009
    Location
    Cape Town, South Africa
    Posts
    21

    Default

    Couldn't have done it without your help!

    As for "RobotLegs fame"... ha! I have a sneaking suspicion that I've completely missed the point with my framework, and done something along the lines of turning an IoC container back into a Service Locator! Actually, I started RobotLegs with the hopes that someone else (read: someone more skilled) would pick it up and run with it. In the meantime, I'll keep playing around, and hopefully come up with something useful.

    Anyhow, looking forward to the Spring ActionScript 0.8 release. Best of luck with that.

    PS: great job on the documentation for the project - very comprehensive and useful.

  7. #17
    Join Date
    Dec 2008
    Location
    Brussels
    Posts
    407

    Default well...

    I haven't gotten a chance to take an in-depth look at your framework, so I can't honestly say that you missed the point
    From what I gleaned from it, it seems you're taking the metadata based injection approach, which isn't bad at all, just a matter of preference or convenience. The interface itself seems quite friendly at first sight.
    But even if, in your opinion, you've missed the point in hindsight, you still gave yourself a bunch of valuable experience. Knowing and understanding 'the wrong way' is very good to know as well

    greets,

    Roland

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •