Chapter 8. JMX Client Implementation

JMX Clients work with MBeans and/or MBeanServerConnections. An MBeanServerConnection is an interface. The underlying object could be a remote Connector connection to a MBeanServer, or it could be a local MBeanServer. The JMX Client itself is often (usually) also an MBean.

There are a few different ways for a JMX Client to get an MBeanServer/MBeanServerConnection handle. Most commonly, a local MBean would implement javax.management.MBeanRegistration, and would get access to an MBeanServer in that way. Any remote JMX Client or MBean will have access to an MBeanServerConnection. An MBeanServerConnection could also be passed as a constructor or method argument. (An MBeanServer could also be passed this way, but always use an MBeanServerConnection where possible).

From the client-programmer's perspective, the most important functional difference between an MBeanServer and an MBeanServerConnection is, there is a method MBeanServer.registerMBean(), and there is no corresponding method for MBeanServerConnection. Since a remote JMX Client may be running in a different JVM, it is generally impossible to register an existing, local object. Therefore, MBeanServerConnections must use the method createMBean() to both instantiate and register an MBean object on the server-side.

An example of a Local JMX Client could be a class to provide persistence for MBeans. It would store or retrieve based on notification methods or method calls from the Agent or some other JMX Client class.

Sun JMX users need JMXRMT_HOME/jmxremote_optional.jar if using a Generic remote protocol such as jmxmp.

If you are going to be coding JMX Clients, you need to learn how to use the following classes from the API.

In particular, look over all of the methods in MBeanServerConnection. Many of them are essential to typical uses of a JMX Client, including the methods createMBean, getAttribute, setAttribute, and invoke, which is how clients invoke MBean constructors and methods. (You can alternatively use MX4J delegation stubs, in a similar manner to Axis SOAP delegation stubs).

In this document, there are examples of JMX Clients in the Distributed Services and Connectors chapter and the Agent Implementation chapter.

Most of the MBean lookup methods use an ObjectName structure. An ObjectName represents an MBean Name or a wildcard for MBean Name(s). I find JMX Client code easier to understand if you do your normally work with Strings and convert to/from ObjectNames when you need to. For example

    mBeanServerConnection.someMethod(new ObjectName("dom:key=val1,key=val2"));

Wildcards work just as you would want them to.

    mBeanServerConnection.queryMBeans(
    new ObjectName("do*:*"), null);

Behind the scenes there are awkward structures to assemble these queries. You would think that with all the attention Sun pays to them, that they would be powerful, but they only support simple, restricted queries. These work fine for the simple purpose of looking up MBeans. You can work with these structures yourself, but if you really wanted to do complex regex work, you'd be better off to use a real regex facility rather than this half-assed, inelegant implementation. Just pass null as the second argument to MBeanServerConnection.queryMBeans() and .queryNames().

To keep the Agent example simple, I used the 2-argument createMBean call. To invoke a constructor with argument(s) for an underlying MBean, you have to pass those arguments to JMX. In many cases, the classes are in classloader scope, and it would be much safer and convenient to specify a Class array (just like some java.lang.Class methods use), but JMX always requires a String array to specify the constructor signature. Instead of { String.class com.admc.util.AClass.class } , you have to use { "java.lang.String", "AClass" } . Note that, besides loss of elegance and consistency, you always have to specify the package (i.e., you can't rely on default package names or imports). Here's an example instantiating of an MBean instantiation in JmxHtmlAdaptor that uses a 2-argument constructor.

        ObjectName htmlAdaptorName = new ObjectName(
                "JmxHtmlAdaptor:class=com.admc.jmx.JmxHtmlAdaptor,id=1");
        ...
        Object[] oa2 = { new Boolean(true), new Boolean(false) };
        String[] sa2 = { "boolean", "boolean" };
        mbc.invoke(htmlAdaptorName, "start", oa2, sa2);