12 Replies Latest reply on May 22, 2008 1:51 AM by alesj

    expressing dependent states

    jhalliday

      So I'm busy migrating the transaction manager in JBossAS 5.0 from JMX to POJO and I run into a little problem with the JTS version... The TransactionManager bean does things in its 'create()' method that depend on the CorbaORBService MBean having run its 'startService()' method beforehand.

      So the problem is twofold - I need to have a bean depending on an mbean (that bit seems to work) but I additionally need to have two different lifecycle phases ordered in a particular way. I don't seem to be able to express in my bean's xml "Don't 'create' me until 'the orb' has been 'started'". Of course this needs to be generalized to any (m)beans and any lifecycle phases. Any way to support that?

      Thanks

        • 1. Re: expressing dependent states

          You're breaking the MBean rules.
          You shouldn't expect some dependency to be started in your create lifecycle.
          I'm surprised this worked when you were an MBean? Maybe just luck :-)

          The obvious solution would be to inject the ORBService as a parameter
          into your create() method. It then must be started/installed to be passed
          as such a parameter.

          <bean ...>
           <create>
           <parameter><inject bean="ORBService"/></parametrer>
           </create>
          


          But if you don't want to change your code then you can use the "demand"
          instead of "depends' to achieve what you want:

          Example from the schema:
          http://viewvc.jboss.org/cgi-bin/viewvc.cgi/jbossas/projects/microcontainer/trunk/kernel/src/resources/main/schema/jboss-beans-common_2_0.xsd?view=log
           The demand is used to specify a dependency on a supply
          
           and when the demand should be supplied
          
          
          
           e.g.:
          
           ISupply must be installed before IDemand is constructed
          
          
          
           <bean name="IDemand">
          
           <demand state="Instantiated">theSupply</demand>
          
           </bean>
          
           <bean name="ISupply" ...>
          
           <supply>theSupply</supply>
          
           </bean>
          


          In your case you would
          <demand state="Create">ORBService</demand>
          


          • 2. Re: expressing dependent states
            jhalliday

            Injecting it to the create would be fine and will actually save me a JNDI lookup, but ORBService is not a bean it's a JMX MBean. Is injection of those supported?

            • 3. Re: expressing dependent states
              jhalliday

              > You're breaking the MBean rules.
              > You shouldn't expect some dependency to be started in your create lifecycle.
              > I'm surprised this worked when you were an MBean? Maybe just luck :-)

              Probably because I've changed the TransactionManager to do more of its setup in create() rather than start(). In my view the real problem is that CorbaORBServer does things in startService() that actually belong earlier in the lifecycle. Pretty much everything other than orb.run() infact. But since there are no real guidelines on what goes where in the lifecycle it's all a matter of opinion. Since it can't be guaranteed that the authors of two entities have the same opinion, there needs to be a flexible wiring of state dependencies.

              • 4. Re: expressing dependent states

                 

                "jhalliday" wrote:
                But since there are no real guidelines on what goes where in the lifecycle it's all a matter of opinion.


                ????
                http://wiki.jboss.org/wiki/ServiceLifecycle

                But that doesn't mean that people follow the rules. ;-)

                • 5. Re: expressing dependent states

                   

                  "jhalliday" wrote:
                  Injecting it to the create would be fine and will actually save me a JNDI lookup, but ORBService is not a bean it's a JMX MBean. Is injection of those supported?


                  Yes, it injects the mbean instance. It's equivalent to what we used to do
                  when we used the getInstance() attribute of an MBean
                  then do something like:
                  public MyMBean getInstance()
                  {
                   return this;
                  }
                  


                  If you're just after the ORB, then you can do something like:
                  <create>
                   <parameter><inject bean="ORBService" property="ORB"/></parameter>
                  </create>
                  

                  or even just inject it as a property on your bean.

                  • 6. Re: expressing dependent states
                    jhalliday

                    Hmm, presumably injecting it as a parameter to some lifecycle method ensures the property has actually been configured correctly (ORBService may setORB(...) in e.g. startService()), whereas injecting it as a property on the bean does not. Property injection is built on the assumption that a bean's properties are initialized at bean creation time I guess? Besides, if I inject it as a property of my bean, I may be tempted to use it in create() rather than start(), which would be against the guidelines I think. So the correct approach would seem to be

                    <start>
                     <parameter><inject bean="ORBService" property="ORB"/></parameter>
                    </start>
                    


                    • 7. Re: expressing dependent states

                       

                      "jhalliday" wrote:
                      Hmm, presumably injecting it as a parameter to some lifecycle method ensures the property has actually been configured correctly (ORBService may setORB(...) in e.g. startService()), whereas injecting it as a property on the bean does not. Property injection is built on the assumption that a bean's properties are initialized at bean creation time I guess? Besides, if I inject it as a property of my bean, I may be tempted to use it in create() rather than start(), which would be against the guidelines I think. So the correct approach would seem to be


                      No. "inject" is different from "depends".
                      The MC is a lot more flexible than the old service lifecycle.
                      In fact, the JBoss5 service lifecycle is more flexible than the old JBoss4 one. ;-)

                      depends is a two phase lifecycle create/start that is backwards compatible with
                      the old MBean service lifecycle.
                      The MBean lifecycle was originally done as two phase to solve circular dependency
                      issues (which most services don't have anyway ;-).

                      inject works by requiring the dependency is INSTALLED (i.e. it has completed its whole
                      lifecycle) before the object can be injected into the dependee.
                      Circular dependencies are handled in a different (more explicit) way in the MC,
                      see the getting started docs. i.e. You can override what state the dependency
                      must be in before it is injected.

                      e.g. You can inject an MBean instance or property into a constructor, propertly, lifecycle
                      method parameter, etc. and it will guarantee the MBean has been fully started before
                      that part of the lifecycle gets invoked.

                      There's a different philosophy between the two mechanisms.

                      ASIDE:
                      In JBoss5 MBeans have gained some (but not all) of this injection flexibility
                      from the ServiceController being implemented on top of the MC.
                      e.g. There is now a proper lifecycle for the setAttribute() invocations on the
                      mbeans so they can use "inject" semantics rather than "depends optional-attribute".


                      • 8. Re: expressing dependent states
                        jhalliday

                        wow, cool.

                        So in that case injecting it as a property of my bean will give the same value as injecting it as a parameter of a lifecycle method call. The difference I guess is limited to the potential for concurrent execution.

                        In the case of injection as a bean property, the lifecycles must be strictly serial ordered. Whereas, with lifecycle method parameter injection, the bean on which the injection is occurring can go through any of the lifecycle phases before the one for which it requires the injected parameter, concurrently with the lifecycle of the bean that will be injected.

                        Is that right? Does MC actually use or plan to use concurrent startup to speed things up? If so, there is potential advantage in sticking with parameter injection rather than injecting it as a property on my bean.

                        • 9. Re: expressing dependent states

                           

                          "jhalliday" wrote:

                          Is that right? Does MC actually use or plan to use concurrent startup to speed things up? If so, there is potential advantage in sticking with parameter injection rather than injecting it as a property on my bean.


                          Yes, but I don't really see how delaying the injection increases the concurrency?

                          In most circumstances if you have dependencies they are going to wait until
                          you are fully installed so it doesn't really matter if you inject some other service
                          into a property or a lifecycle method.

                          On an aesthetic point, some advocates of IOC (e.g. nano/pico container) suggest
                          you should inject into the constructor parameters since then you can
                          be immutable and it is less error prone (you are forced to inject all the parameters
                          while people are not forced to set all the properties or configure lifecycle methods).


                          • 10. Re: expressing dependent states
                            alesj

                            You can add 'state' attribute to inject, meaning you want your injectee to be in/past that state - in your case you would put Start:

                            <bean ...>
                             <create>
                             <parameter><inject bean="ORBService" state="Start"/></parametrer>
                             </create>
                            



                            • 11. Re: expressing dependent states
                              alesj

                               

                              "adrian@jboss.org" wrote:

                              But if you don't want to change your code then you can use the "demand"
                              instead of "depends' to achieve what you want:

                              In your case you would
                              <demand state="Create">ORBService</demand>
                              

                              That's not entirely true, since it doesn't do all/exactly what Jonathan asked. ;-)

                              In this case he's missing dependent state configuration.
                              He's forced to have ORBService in Installed state, which is something he might not want since he's fine with just Start.

                              The demand notion is not the right place for this, since demand/supply concept handles things beyond contexts handled by MC - a generic match mechanism. And as such some items we demand might not have dependent state.

                              Should we create new context-demand notion?


                              • 12. Re: expressing dependent states
                                alesj

                                 

                                "alesj" wrote:

                                ..., since demand/supply concept handles things beyond contexts handled by MC - a generic match mechanism. And as such some items we demand might not have dependent state.

                                This part is wrong, or at least it doesn't explain the real problems behind our demand/supply.

                                First, items *do* have dependent state, since every supply is backed-up by a kernel controller context.

                                It's the way we have it implemented.
                                Currently we add/register all supplies from BeanMetaData at Installed state. So no way of knowing if some supplier can supply the supply before (a lot of supplies here :-).

                                We can extend the supply notion in a similar way we extended installs, to be applicable in any state.
                                Then having
                                Map<ControllerState, Map<Object, List<KernelControllerContext>>>
                                

                                in AbstractKernelController.

                                "alesj" wrote:

                                Should we create new context-demand notion?

                                Definitely not. :-)