1 2 Previous Next 24 Replies Latest reply on Mar 27, 2007 11:36 AM by alesj

    Lifecycle aspects revisited

    kabirkhan

      One problem with the current lifecycle introduction aspects (JMXIntroduction, JndiIntroduction) is that they do not call invocation.invokeNext().

      This means that if we use both the @JMX and the @JndiBinding annotations to a bean, the first one in the chain wins, so we either get registered in JMX or in JNDI, but not both.

      If these asepcts are changed to call invokeNext(), we will eventually end up with the MethodInvocation trying to call the setKernelControllerContext() method in the target which does not exist, resulting in an exception. I think the woven/proxy code needs to be modified to detect if an interface introduction is the cause of the MethodInvocation, and if this is the case we do not attempt to call the target method at the end of the interceptor chain.

        • 1. Re: Lifecycle aspects revisited
          kabirkhan

          I also think it should be possible to make the pointcut attribute optional for the lifecycle events

           <aop:lifecycle-configure xmlns:aop="urn:jboss:aop-beans:1.0"
           name="JMXLifecycle"
           class="org.jboss.aop.microcontainer.aspects.jmx.JMXIntroduction"
           classes="@org.jboss.aop.microcontainer.aspects.jmx.JMX"
           </aop:lifecycle-configure>
          


          Since in most cases the pointcut will be something along the lines of

          execution(* CLASSES_VALUE->$implements{org.jboss.kernel.spi.dependency.KernelControllerContextAware}(..))">
          


          i.e.:
          execution(* @org.jboss.aop.microcontainer.aspects.jmx.JMX->$implements{org.jboss.kernel.spi.dependency.KernelControllerContextAware}(..))">
          


          If something apart from this defaul needs doing it will be possible to specify the "pointcut" attribute as it works at present.

          • 2. Re: Lifecycle aspects revisited
            kabirkhan

            Another issue at the moment is if something for example has both lifecycle-configure and aop:lifecycle-install aspects.

            In this case setKernelControllerContext() gets called both during configure and install, with no real way to controll which of the lifecycle aspects to call. This could be handled at aspect level, since we have access to the KernelControllerContext, but that seems slightly ugly. Would it make sense to make these methods more finegrained? i.e.

            public interface ConfigureKernelControllerContextAware extends KernelControllerContextAware
            {
             void setConfigureKernelControllerContext(KernelControllerContext context) throws Exception;
             void unsetConfigureKernelControllerContext(KernelControllerContext context) throws Exception;
            }
            
            public interface InstallKernelControllerContextAware extends KernelControllerContextAware
            {
             void setInstallKernelControllerContext(KernelControllerContext context) throws Exception;
             void unsetInstallKernelControllerContext(KernelControllerContext context) throws Exception;
            }
            
            ...
            


            WRT my previous post the default pointcut for a lifecycle-configure would then become
            execution(* CLASSES_VALUE->$implements{org.jboss.kernel.spi.dependency.ConfigureKernelControllerContextAware}(..))"
            


            • 3. Re: Lifecycle aspects revisited
              starksm64

              It seems that this notion should be something that integrates at the ClassAdapter as Adrian was talking about here: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=94495 rather than as interceptors on the KernelControllerContextAware methods. I'm not that familiar with the KernelControllerContextAction notions, but @JMX and @Jndi should probably show up as additional side effect behaviors run during the corresponding kernel lifecycle phase.

              • 4. Re: Lifecycle aspects revisited

                 

                "kabir.khan@jboss.com" wrote:

                In this case setKernelControllerContext() gets called both during configure and install, with no real way to controll which of the lifecycle aspects to call.


                You can check the state by looking at context.getState();
                But like you said, it might be easier to be able to define different pointcuts.

                • 5. Re: Lifecycle aspects revisited
                  starksm64

                  Shouldn't this be a more fundamental notion though? I mean, rather than trying to hook into an optional lifecycle callback, there should be an AOPInstallUnistallAction that pulls the the behaviors to apply from the metadata.

                  • 6. Re: Lifecycle aspects revisited

                     

                    "scott.stark@jboss.org" wrote:
                    there should be an AOPInstallUnistallAction that pulls the the behaviors to apply from the metadata.


                    Doesn't that suffers from the same problem?
                    e.g. What if somebody else wants to an XXXInstallUninstallAction as well
                    as a the AOP one?

                    In general the MC actions are defined by the person that installs the context
                    so they can add/remove/override the actions.
                    e.g. Think about the what we want to do in the profile service where we "null out"
                    the instantiate/configure lifecycle actions.

                    At least with the AOP introductions/advices you can define what they are in the AOP config.

                    Of course, we could go to a more "fundamental" full AOP advice chain in the MC actions
                    where you could add abritrary behaviour to the actions chosen by the person
                    that created the context?

                    But I think this would be even harder to configure since you don't really have
                    a "target" on which you define pointcuts? That is unless the pointcuts were
                    just the MC lifecycle events and we had some custom pointcut language
                    to identify where the advices are applied.

                    It does have the advantage that you don't need to wrap the target in a proxy
                    just to add an introduction for deployment time (rather than runtime) behaviour
                    performed during the MC lifecycle events.

                    • 7. Re: Lifecycle aspects revisited
                      starksm64

                      What I was thinking of is that the install/uninstall actions would be handled as orthogonal behaviors rather than a single chain. Nulling them out would be the same as removing the aspect.

                      Really what I'm suggesting is that the aop:xxx lifecycle elements populate the list of orthogonal behaviors that should be applied during that phase.

                      • 8. Re: Lifecycle aspects revisited

                         

                        "scott.stark@jboss.org" wrote:

                        Really what I'm suggesting is that the aop:xxx lifecycle elements populate the list of orthogonal behaviors that should be applied during that phase.


                        Ok so the aop:xxx lifecycle callbacks would implictly define the pointcuts?
                        I wasn't involved in the design of this part so we'll have see what Kabir thinks.

                        But it would make sense from my point of view if you could add an action
                        for deployment time processing without having to add an introduction into the POJO.

                        e.g. @JMX or @JNDI on the target bean would lead to lifecycle events on
                        the context but you don't have to go through the proxy at runtime
                        (although I know at least for the pure AOP this was almost a no-op anyway :-).

                        The other reason why this would be useful is because I want to have the ability
                        to see the MBean in the JMX-console even when the target doesn't exist for
                        the "on-demand" behaviour.
                        e.g. You would see a skeleton MBean with a single operation to start it.
                        I don't know how far Kabir got with this using an Introduction and a "hollow proxy"?

                        • 9. Re: Lifecycle aspects revisited
                          starksm64

                          Yes, that is what I'm thinking. It just seems that actually going through the full aop process to add this specific lifecycle extension is more work than necessary.

                          • 10. Re: Lifecycle aspects revisited
                            kabirkhan

                            I've largely worked through the AOP side of replacing the old "lifecycle aspects" with "lifecycle actions".

                            I propose something like the following interface for the lifecycle actions

                            interface LifecycleAction
                            {
                             void install(KernelControllerContext ctx);
                             void uninstall(KernelControllerContext ctx);
                            }
                            


                            I'm not sure where to fit it in though. Can I populate the KernelControllerContext with the lifecycle handlers for the different states?

                            I need some way of getting hold of the Advisor, since this is where the per-bean annotations are stored, and also it is a convenient way of reading the annotations in the class. But this may be solveable by something Adrian mentioned before about storing the metadata information in the Class(Instance)Adapter and accessing that via the KCC?


                            • 11. Re: Lifecycle aspects revisited
                              kabirkhan

                              http://jira.jboss.com/jira/browse/JBMICROCONT-154
                              I should be ready to commit something later today - question is to which branch?

                              What we have is a new LifecycleCallbackMetaData which gets populated by the DescribeAction + AOPDependencyBuilder. It does not really use AOP much for anything other than the matching of the classes pointcuts. These lifecycle callbacks are then added to the BeanMetaData.

                              I've modified KernelControllerContextAction install/uninstall to look for lifecycle callback metadata and if this exists to invoke the callbacks.

                              It is configured as follows

                               <aop:lifecycle-configure xmlns:aop="urn:jboss:aop-beans:1.0"
                               name="DependencyAdvice"
                               class="org.jboss.aop.microcontainer.aspects.jmx.JMXLifecycleCallback"
                               classes="@org.jboss.aop.microcontainer.aspects.jmx.JMX">
                               <property name="mbeanServer"><inject bean="MBeanServer"/></property>
                               </aop:lifecycle-configure>
                              


                              Which translates to

                               <bean name="DependencyAdvice" class="org.jboss.aop.microcontainer.aspects.jmx.JMXLifecycleCallback">
                               <property name="mbeanServer"><inject bean="MBeanServer"/></property>
                               </bean>
                              
                               <bean name="DependencyAdvice$Binding" class="org.jboss.aop.microcontainer.beans.LifecycleBinding">
                               <property name="callbackBean">DependencyAdvice</property>
                               <property name="manager"><inject bean="AspectManager"/></property>
                               <property name="classes">@org.jboss.aop.microcontainer.aspects.jmx.JMX</property>
                               <property name="state">Configured</property>
                               </bean>
                              
                              


                              The callbacks are no longer "interceptors", so there is no chain, and by default it will look for methods called install and uninstall. Callback methods must take the KernelControllerContext as a parameter:

                              public class JMXLifecycleCallback
                              {
                               private MBeanServer server;
                              
                               public void setMbeanServer(MBeanServer server)
                               {
                               this.server = server;
                               }
                              
                               public void install(KernelControllerContext context) throws Exception
                               {
                               JMX jmx = readJmxAnnotation(context);
                               ObjectName objectName = createObjectName(context, jmx);
                              
                               //register in jmx
                               }
                              
                               public void uninstall(KernelControllerContext context) throws Exception
                               {
                               JMX jmx = readJmxAnnotation(context);
                               ObjectName objectName = createObjectName(context, jmx);
                              
                               //unregister in jmx
                               }
                              
                               private JMX readJmxAnnotation(KernelControllerContext context) throws Exception
                               {
                               if (context.getMetaData() != null)
                               {
                               return context.getMetaData().getAnnotation(JMX.class);
                               }
                               return null;
                               }
                              
                               private ObjectName createObjectName(KernelControllerContext context, JMX jmx) throws Exception
                               {
                               ...
                               }
                              }
                              



                              • 12. Re: Lifecycle aspects revisited

                                Since we are now "intercepting" the controller actions, this should be something
                                that can be applied to any context, not just POJO.

                                As such, the api should be the more generic:
                                org.jboss.dependency.plugins.spi.action.ControllerContextAction
                                rather than KernelControllerContextAware.

                                • 13. Re: Lifecycle aspects revisited
                                  starksm64

                                  Put it in the mc trunk and we'll figure out what to do with the what get merged to/from the 2.0 branch after the jboss5.beta2 release.

                                  • 14. Re: Lifecycle aspects revisited
                                    kabirkhan

                                    I've committed what I have done so far to mc trunk. The relevant tests in the aop-mc-int project are:

                                    InitialLifecycleCallbackTestCase
                                    InitialLifecycleCallbackWithDependencyTestCase
                                    NonDefaultMethodsLifecycleCallbackTestCase
                                    CreateBeansLifecycleCallbackTestCase
                                    CreatedBeansLifecycleWithDependencyTestCase
                                    LifecycleTestCase
                                    MultipleLifecycleTestCase
                                    JMXLifecycleTestCase
                                    JndiLifecycleTestCase

                                    Adrian, I'm not getting your comment? The lifecycle callbacks no longer use KernelControllerContextAware. KernelControllerContextAction invokes the callback methods that should be run on the bean that is the "callback handler". It passes in the current KernelControllerContext into the callback method.

                                    1 2 Previous Next