1 2 3 Previous Next 41 Replies Latest reply on Aug 28, 2006 10:12 AM by Adrian Brock

    Bean instantiate order with contextual injection

    Ales Justin Master

      If bean that has a 'contextual injection' is defined before the actual injectee, deployment fails.
      Is there a way to avoid this. Or is this expected behaviour?

      
      <?xml version="1.0" encoding="UTF-8"?>
      
      <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_1_0.xsd"
       xmlns="urn:jboss:bean-deployer">
      
       <bean name="testObject" class="org.jboss.test.kernel.inject.support.AnnotatedTypeStrictSimpleTestObject" />
      
       <bean name="injecteeInterface" class="org.jboss.test.kernel.inject.support.DuplicateTester"/>
      
      </deployment>
      
      
      


        • 1. Re: Bean instantiate order with contextual injection
          Adrian Brock Master

          That is because you have done it wrong.

          This MC is state machine a metadata model.

          What you should be doing is changing the way the AbstractDependencyValueMetaData
          works to include demand like processing when the "bean=" is missing.

          i.e. You create a new DependencyItem type like the demand dependency
          (see org.jboss.beans.metadata.plugins.AbstractDemandMetaData$DemandDependencyItem)

          In particular the method "public boolean resolve(Controller controller)"

          • 2. Re: Bean instantiate order with contextual injection
            Adrian Brock Master

            Additionally, please don't modify any "spi" interfaces
            without discussing it first.

            This change in Controller

            "
            /**
            * @return all instantiated contexts whose target is instance of this class clazz param
            */
            Set getInstantiatedContexts(Class clazz);

            /**
            * add instantiated context into contextsByClass map
            * look at all target's superclasses and interfaces
            */
            void addInstantiatedContext(ControllerContext context);

            /**
            * remove instantiated context from contextsByClass map
            * look at all target's superclasses and interfaces
            */
            void removeInstantiatedContext(ControllerContext context);
            "

            Should be a private implementation api not a public api.
            See for example AbstractKernelController add/removeSupplies.

            Additionally the Controller in dependency is an abstract model.
            It has no notion of "instantiate" beyond the state model that
            is plugged as an implementation detail.

            Neither does it have any notion of "java.lang.Class".
            It manages contexts which can be anything.
            It is only the KernelController that introduces the notion of POJO.

            • 3. Re: Bean instantiate order with contextual injection
              Adrian Brock Master

              I've moved these methods to the KernelController.

              • 4. Re: Bean instantiate order with contextual injection
                Ales Justin Master

                 

                "adrian@jboss.org" wrote:
                That is because you have done it wrong.

                This MC is state machine a metadata model.

                What you should be doing is changing the way the AbstractDependencyValueMetaData
                works to include demand like processing when the "bean=" is missing.

                i.e. You create a new DependencyItem type like the demand dependency
                (see org.jboss.beans.metadata.plugins.AbstractDemandMetaData$DemandDependencyItem)

                In particular the method "public boolean resolve(Controller controller)"


                I must probably put in a 'demand' of my property's class ... and for each context instantiation I supply all implementings classes?

                But what if there actually are more then one such matching bean - I would probably get the one that is first instantiated injected, discarting the fact that more matching bean can occur.

                What about @Inject meta data?
                Where to do the inspection and add dependency items?

                • 5. Re: Bean instantiate order with contextual injection
                  Adrian Brock Master

                   

                  "alesj" wrote:

                  I must probably put in a 'demand' of my property's class ... and for each context instantiation I supply all implementings classes?

                  But what if there actually are more then one such matching bean - I would probably get the one that is first instantiated injected, discarting the fact that more matching bean can occur.


                  In general that is an unsolvable problem with hot deployment.

                  You can solve it to the "first order" by requiring that any bean
                  with a contextual injection waits for those without to be deployed.

                  But then those beans with contextual injections may
                  introduce extra matches, i.e. "second order".

                  Try to solve the "second order" problem like the first leads
                  to "third order" problems.

                  The best you can do (in general) is remember that a
                  contextual injection was done and if another candidate
                  appears after the fact then issue a warning.


                  What about @Inject meta data?
                  Where to do the inspection and add dependency items?


                  AbstractKernelController.preprocessMetaData()
                  is where this gets done (assuming you are talking about annotations).
                  However when we do classloading dependencies, some of this
                  will have to move to the DescribeAction such that we know
                  the class exists.

                  • 6. Re: Bean instantiate order with contextual injection
                    Ales Justin Master

                     

                    "adrian@jboss.org" wrote:

                    The best you can do (in general) is remember that a
                    contextual injection was done and if another candidate
                    appears after the fact then issue a warning.


                    Where to hold such information?

                    assuming you are talking about annotations

                    That too (see below).
                    But what about actual @Inject in class annotation?
                    Where to look/inspect class for them - to add dependency 'demand' items - how to get bean class from AbstractDependencyValueMetaData?


                    AbstractKernelController.preprocessMetaData()
                    is where this gets done (assuming you are talking about annotations).
                    However when we do classloading dependencies, some of this
                    will have to move to the DescribeAction such that we know
                    the class exists.


                    How to add specific code about @Inject annotation into AnnotationMetaData.visit() - through children?



                    • 7. Re: Bean instantiate order with contextual injection
                      Adrian Brock Master

                       

                      "alesj" wrote:


                      Where to hold such information?


                      Where you hold it now, e.g.:

                      protected Map<Class, ClassContext> contextsByClass = CollectionsFactory.createConcurrentReaderMap();

                      private class ClassConext
                      {
                      private Set contexts;

                      // other info
                      }


                      • 8. Re: Bean instantiate order with contextual injection
                        Adrian Brock Master

                        If it gets complicated, it is probably better to turn into a first "delegate"
                        object to avoid polluting the AbstractKernelController.

                        • 9. Re: Bean instantiate order with contextual injection
                          Adrian Brock Master

                           

                          "alesj" wrote:

                          But what about actual @Inject in class annotation?
                          Where to look/inspect class for them - to add dependency 'demand' items - how to get bean class from AbstractDependencyValueMetaData?

                          ...

                          How to add specific code about @Inject annotation into AnnotationMetaData.visit() - through children?


                          I don't understand either of these questions.

                          Why would you be looking up the @Inject from the
                          AbstractDependencyValueMetaData (ADVM)?
                          It is a property of the class/method.

                          AnnotationMetaData.visit() is used to process
                          <bean>
                           <annotation>...
                          


                          Which AFAIK, (Kabir may know better) isn't properly integrated
                          except when AOP is used. i.e. The Bean/ClassInfo is not updated
                          with the annotation overrides.

                          • 10. Re: Bean instantiate order with contextual injection
                            Adrian Brock Master

                             

                            "adrian@jboss.org" wrote:

                            Why would you be looking up the @Inject from the
                            AbstractDependencyValueMetaData (ADVM)?
                            It is a property of the class/method.


                            With the annotation approach it is your job to create/add an ADVM
                            to the metadata.

                            • 11. Re: Bean instantiate order with contextual injection
                              Adrian Brock Master

                              Like I said originally, the annotations are a separate task.
                              You would be better off not trying to mix the two features.

                              1) Contextual injection - i.e. determining (and properly dependening on)
                              the injected context based on class rather than name.

                              2) Creating BeanMetaData from annotations rather than xml.

                              • 12. Re: Bean instantiate order with contextual injection
                                Ales Justin Master

                                 


                                But what about actual @Inject in class annotation?
                                Where to look/inspect class for them - to add dependency 'demand' items - how to get bean class from AbstractDependencyValueMetaData?

                                ...

                                How to add specific code about @Inject annotation into AnnotationMetaData.visit() - through children?



                                I don't understand either of these questions.

                                Why would you be looking up the @Inject from the
                                AbstractDependencyValueMetaData (ADVM)?
                                It is a property of the class/method.


                                I have a notion of Loose injection - if no matching bean is found no error is thrown - but this information is held in specific annotation.
                                Forget about Loose injection?


                                You would be better off not trying to mix the two features.


                                Yep, will seperate the two of them.
                                Or as you said - handling annotations with BeanMD creation.


                                1) Contextual injection - i.e. determining (and properly dependening on)
                                the injected context based on class rather than name.


                                How to get property class to add 'demand' dependency item in AbstractInjectionMD - AbstractPropertyMD doesn't hold any class type value - obviously, since no owner bean class inspection is done?


                                2) Creating BeanMetaData from annotations rather than xml.


                                Adding this in AbstractBeanMetaData.visit() through KernelConfigurer?

                                • 13. Re: Bean instantiate order with contextual injection
                                  Adrian Brock Master

                                   

                                  "alesj" wrote:

                                  I have a notion of Loose injection - if no matching bean is found no error is thrown - but this information is held in specific annotation.
                                  Forget about Loose injection?


                                  You can keep it if you like, but I don't see the use case.
                                  I generally dislike "silent failures".

                                  • 14. Re: Bean instantiate order with contextual injection
                                    Adrian Brock Master

                                     

                                    "alesj" wrote:

                                    1) Contextual injection - i.e. determining (and properly dependening on)
                                    the injected context based on class rather than name.


                                    How to get property class to add 'demand' dependency item in AbstractInjectionMD - AbstractPropertyMD doesn't hold any class type value - obviously, since no owner bean class inspection is done?


                                    Ok. Your problem is that the class is not available until the
                                    DescribeAction. That is when the classloader dependency is
                                    resolved. Until that point we can't guarantee the classloader even
                                    exists.

                                    So you're going to need a "placeholder" DependencyItem
                                    where you fill in the type of the property once the BeanInfo
                                    is resolved in DescribeAction.

                                    This is a bit messy, and would probably be better implemented
                                    as a "revisit" of the visitor where the extra visit does extra work
                                    once the BeanInfo is resolved, but that is a lot more work
                                    (in terms of making the old understand it rather than doing work twice).

                                    For now, I would just do context.getDependencyInfo(),
                                    iterate and update the "placeholder"s.



                                    2) Creating BeanMetaData from annotations rather than xml.


                                    Adding this in AbstractBeanMetaData.visit() through KernelConfigurer?


                                    See above. And see where annotations and their dependencies
                                    from AOP are resolved in the DescribeAction.

                                    1 2 3 Previous Next