14 Replies Latest reply on Nov 12, 2006 8:21 PM by brian.stansberry

    Injection of MBeanServer

    brian.stansberry

      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
          starksm64

          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

            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
              starksm64

               

              "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

                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
                  starksm64

                  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

                    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
                      alesj

                      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

                        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
                          kabirkhan

                          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
                            starksm64

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

                            • 11. Re: Injection of MBeanServer
                              starksm64

                               

                              "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.


                              • 12. Re: Injection of MBeanServer
                                kabirkhan

                                I'm moving the discussion of the integration here:
                                http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3983882#3983882

                                • 13. Re: Injection of MBeanServer
                                  manik

                                   


                                  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

                                    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.