14 Replies Latest reply on Nov 12, 2006 8:21 PM by Brian Stansberry

    Injection of MBeanServer

    Brian Stansberry Master

      I'm a bit concerned that there's no longer any way to inject an MBeanServer into a PojoCache/Cache/TreeCache. In 1.x, the server was injected via the ServiceMBeanSupport's impl of javax.management.MBeanRegistration. In HEAD, that's gone with no replacement. We now rely solely on the internal MBeanServer lookup code in JmxUtil.

      That lookup code works fine in the AS, since JmxUtil prefers to find the "jboss" MBeanServer. Also works outside the AS if there is only one MBeanServer in the JVM. It's not reliable outside the AS if there is more than one MBeanServer in the JVM.

      This could be a real problem, because the way JBC now does JMX integration provides no hooks to allow a user to manage the integration themselves -- at least not if they use our factories. E.g. this won't work:

      MBeanServer weblogicServer = getWebLogicJMXFromSomewhere();
      Configuration config = buildConfigSomehow();
      Cache cache = DefaultCacheFactory.createCache(config, false);
      weblogicServer.registerMBean(cache, new ObjectName(...)); // FAIL! Cache is not an mbean


      At first I thought we could add get/setMBeanServer() to CacheSPI. But that doesn't work for PojoCache, which doesn't extend CacheSPI. Adding get/setMBeanServer() to PojoCache sounds terrible.

      Another option is to add overloaded methods to CacheFactory and PojoCacheFactory, where the MBeanServer is passed to createCache. The factory can then pass the server into TreeCache and PojoCacheImpl.

        • 1. Re: Injection of MBeanServer
          Scott Stark Master

          Why does the cache need the MBeanServer? The existing behavior can be obtained by wrapping a pojo cache(its not pojo if it relies on jmx classes) in an mbean that implements MBeanRegistration. The JMX integration should be a layer independent of the core class.

          • 2. Re: Injection of MBeanServer
            Brian Stansberry Master

            The core cache only 'needs' the MBeanServer so it can register itself and it's interceptors with it, if it's configured to do so.

            But, you're right, that's not the way to go. The core cache shouldn't be dealing with this stuff.

            Question: how does stuff get registered in JMX if deployed via a -beans.xml? I vaguely recall reading somewhere months ago that that could be done, but I can't find anyplace showing how. From what I see now (e.g. the AspectManager bean in the AS), it looks like the bean needs to expose a property where the MC passes in the MBeanServer; presumably it's then the bean's responsibility to register itself. Please let me know if that's wrong.

            • 3. Re: Injection of MBeanServer
              Scott Stark Master

               

              "bstansberry@jboss.com" wrote:

              Question: how does stuff get registered in JMX if deployed via a -beans.xml? I vaguely recall reading somewhere months ago that that could be done, but I can't find anyplace showing how. From what I see now (e.g. the AspectManager bean in the AS), it looks like the bean needs to expose a property where the MC passes in the MBeanServer; presumably it's then the bean's responsibility to register itself. Please let me know if that's wrong.


              Yes, that is wrong. The bean should not be doing anything except its core purpose. Beans are not registered with jmx automatically. There has to be a configuration that expresses this aspect, and the jmx aspect should be exposing the configured attributes/operations from the pojo.

              The org.jboss.test.microcontainer.test.JMXDecoratedTestCase illustrates the use of a JMX annotation and associated org.jboss.aop.microcontainer.aspects.jmx.JMXIntroduction which handles the registration of a simple bean like:

              package org.jboss.test.microcontainer.support;
              
              import org.jboss.aop.microcontainer.aspects.jmx.JMX;
              
              @JMX(name="test:name=AnnotatedBean", exposedInterface=SimpleBeanImplMBean.class)
              public class SimpleBeanAnnotatedImpl extends SimpleBeanImpl
              {
              }
              


              Let's get this fleshed out with Kabir's help.

              In the interim if you run into issues, I would look at creating a CacheJmxWrapper that exposes the mbean interface and delegates to the pojo cache to make sure jmx is fully separated out of the core.


              • 4. Re: Injection of MBeanServer
                Brian Stansberry Master

                Thanks. The use of the annotation is what I'd read and forgotten. I thought the "inject the MBeanServer via a property" approach seemed too hacky!

                "scott.stark@jboss.org" wrote:

                The org.jboss.test.microcontainer.test.JMXDecoratedTestCase illustrates the use of a JMX annotation and associated org.jboss.aop.microcontainer.aspects.jmx.JMXIntroduction which handles the registration of a simple bean like:

                package org.jboss.test.microcontainer.support;
                
                import org.jboss.aop.microcontainer.aspects.jmx.JMX;
                
                @JMX(name="test:name=AnnotatedBean", exposedInterface=SimpleBeanImplMBean.class)
                public class SimpleBeanAnnotatedImpl extends SimpleBeanImpl
                {
                }
                


                Let's get this fleshed out with Kabir's help.


                OK. For clustering the part I'm going to want to be sure works well is overriding the @JMX name attribute via XML. Most clustering beans can be deployed multiple times with different partitions, with the partition name as an attribute of the ObjectName. And of course there can be multiple JBC instances in the server.

                Manik, one thing this implies is a compile-time dependency in JBC on the microcontainer jars. I think that was an inevitability anyway. We could avoid this by having the JMX integration in the AS cluster module or the fledgling cluster project, but that seems ugly.


                In the interim if you run into issues, I would look at creating a CacheJmxWrapper that exposes the mbean interface and delegates to the pojo cache to make sure jmx is fully separated out of the core.


                I did that this morning; even named the class "CacheJmxWrapper". Pending sorting out use of @JMX, it knows how to register itself w/ JMX if the MC injects an MBeanServer, a la AspectManager. That may be how I leave it for the next week or so while I focus on getting all the AS clustering code working with the new JBC 2.0 API.

                This class will probably also be the basis for integrating JBC 2.0 in the old JMX Microkernel.

                There's still legacy code in TreeCache that let's TreeCache register itself w/ JMX; I'll remove that tomorrow once others get a chance to read this thread and express any opinions.

                • 5. Re: Injection of MBeanServer
                  Scott Stark Master

                  The compile time dependency is the bad thing about annotations. You can specifiy this via xml and I would not even use the JMX annotation for something like a cache (or any core jboss framework classes) since there are likely to be many of them and no reasonable defaults that should be hard-coded. See the microntainer aop-mc-int/src/resources/tests/org/jboss/test/microcontainer/test/JMXDecoratedTestCase.xml

                  where this is demonstrated:

                  ...
                   <bean name="Bean" class="org.jboss.test.microcontainer.support.SimpleBeanImpl">
                   <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="", exposedInterface=org.jboss.test.microcontainer.support.SimpleBean.class)</annotation>
                   </bean>
                  
                   <bean name="Bean1" class="org.jboss.test.microcontainer.support.SimpleBeanImpl">
                   <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:name=NotBean1", exposedInterface=org.jboss.test.microcontainer.support.SimpleBeanImplMBean.class)</annotation>
                   </bean>
                  



                  • 6. Re: Injection of MBeanServer
                    Brian Stansberry Master

                    Deploying this bean:

                     <bean name="TomcatClusteringCache" class="org.jboss.cache.pojo.jmx.PojoCacheJmxWrapper">
                     <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.cache:service=TomcatClusterCache,partition=${jboss.partition.name:DefaultPartition}", exposedInterface=org.jboss.cache.pojo.jmx.PojoCacheJmxWrapperMBean.class)</annotation>
                    
                     <depends>jboss:service=Naming</depends>
                     <depends>jgroups.mux:name=Multiplexer</depends>
                    
                     <property name="configuration"><inject bean="TomcatClusteringCacheConfig"/></property>
                    
                     </bean>


                    results in the bean not getting registered in JMX and this in the log:

                    2006-11-05 22:06:03,500 WARN [org.jboss.kernel.plugins.dependency.DescribeAction] You have defined annotations for bean 'TomcatClusteringCache', but no KernelRepository has been installed under the name 'Repository'

                    I'll take this up with Kabir.

                    • 7. Re: Injection of MBeanServer
                      Ales Justin Master

                      You are missing a 'Repository' bean in your beans definitions.

                      As Scott said -> aop-mc-int/src/resources/tests/org/jboss/test/microcontainer/test/JMXDecoratedTestCase.xml.

                       <bean name="Repository" class="org.jboss.aop.microcontainer.integration.AOPKernelRepository">
                       <constructor factoryClass="org.jboss.aop.microcontainer.integration.AOPKernelRepository" factoryMethod="instance"/>
                       </bean>
                      
                      
                       private MetaDataContext getMetaDataContext(KernelControllerContext context)
                       {
                       //TODO: Hardcoding this doesn't feel right...
                       ControllerContext repCtx = context.getController().getContext("Repository", ControllerState.INSTALLED);
                      
                       if (repCtx == null)
                       {
                       log.warn("You have defined annotations for bean '" + context.getName() + "', but no KernelRepository has been installed under the name 'Repository'");
                       return null;
                       }
                      
                       KernelRepository repository = (KernelRepository)repCtx.getTarget();
                       MetaDataContextFactory metaFactory = context.getBeanInfo().getMetaDataContextFactory();
                       MetaDataContext metaCtx = metaFactory.getMetaDataContext(repository, context.getName());
                      
                       context.setMetaDataContext(metaCtx);
                      
                       return metaCtx;
                       }
                      


                      • 8. Re: Injection of MBeanServer
                        Brian Stansberry Master

                        Thanks. I saw the Repository bean in the example, but didn't really think that it was appropriate for the -beans.xml for the Tomcat clustering cache to be deploying what looks to be the singleton AOPKernelRepository for the entire appserver.

                        • 9. Re: Injection of MBeanServer
                          Kabir Khan Master

                          I am writing some tests for trying this out in a running jboss instance. I will need to add the jboss-aop-mc-int.jar to the jboss/lib (or server/xxx/lib) folder for this to work, so that either a proxy or a woven class is returned.

                          One thing that still is wooly, is where the repository comes from. The repository has not been finalized yet, and there is still some work that needs doing on it: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3982960#3982960
                          BTW the class to be used is now

                           <bean name="Repository" class="org.jboss.metadata.plugins.repository.basic.BasicMetaDataRepository"/>
                          


                          • 10. Re: Injection of MBeanServer
                            Scott Stark Master

                            Right, its not. Add it to the server conf/deployer-beans.xml for now.

                            • 11. Re: Injection of MBeanServer
                              Scott Stark Master

                               

                              "kabir.khan@jboss.com" wrote:
                              I am writing some tests for trying this out in a running jboss instance. I will need to add the jboss-aop-mc-int.jar to the jboss/lib (or server/xxx/lib) folder for this to work, so that either a proxy or a woven class is returned.

                              One thing that still is wooly, is where the repository comes from. The repository has not been finalized yet, and there is still some work that needs doing on it: http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3982960#3982960
                              BTW the class to be used is now
                               <bean name="Repository" class="org.jboss.metadata.plugins.repository.basic.BasicMetaDataRepository"/>
                              


                              Ok, that was my next question: how does this tie into the current metadata work. We should probably keep the conf/deployer-beans.xml minimal (and rename this to bootstrap-beans.xml) and introduce the aop integration as part of the deployers/* level.


                              • 13. Re: Injection of MBeanServer
                                Manik Surtani Master

                                 


                                The JMX integration should be a layer independent of the core class.


                                Definitely a +1. Hate the hard-coded MBean interfaces in the 1.x series. :-)


                                Manik, one thing this implies is a compile-time dependency in JBC on the microcontainer jars. I think that was an inevitability anyway. We could avoid this by having the JMX integration in the AS cluster module or the fledgling cluster project, but that seems ugly.


                                Yes, I see this as an inevitability too.


                                There's still legacy code in TreeCache that let's TreeCache register itself w/ JMX; I'll remove that tomorrow once others get a chance to read this thread and express any opinions.


                                +1 from me.



                                • 14. Re: Injection of MBeanServer
                                  Brian Stansberry Master

                                  There are still issues with registering a beans.xml pojo in JMX with the @JMX annotation. See http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3985286#3985286 . This is holding me up from converting cluster-service.xml to a cluster-beans.xml. I need to get a working cache for the cluster-x.xml services or I can't even minimally test the various AS code conversions to the 2.0 API.

                                  To get around this, I'm going to go ahead and implement http://jira.jboss.com/jira/browse/JBCACHE-832, which will allow me to create a 2.0 cache service in the AS using a -service.xml file. Then I'll leave HAPartition et al in a cluster-service.xml until the @JMX issues are resolved.