IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Java technology
developerWorks
From black boxes to enterprises, Part 2: Beans, JMX 1.1 style
code67KBe-mail it!
Contents:
A sample application
Planning instrumentation
A standard MBean
Creating a simple JMX agent
Connecting to the JMX agent
Dynamic MBeans
ModelMBean
Using ModelMBean
Run-time hook up of a model MBean in a JMX agent
Implementing DynamicMBean without RequiredModelMBean
Conclusions
Resources
About the author
Rate this article
Related content:
Management application programming
Web services for J2EE
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
Coding your own standard and dynamic MBeans

Level: Intermediate

Sing Li (mailto:westmakaha@yahoo.com?cc=&subject=Beans, JMX 1.1 style)
Author, Wrox Press
30 October 2002

JMX is a popular new standard extension to the Java platform that enables devices, applications, and services to be managed, controlled, and monitored through modern Network Management Systems or Enterprise Management Systems. In this second article of his three-part series on JMX, consultant and popular author Sing Li demonstrates how to rapidly add instrumentation code to a Java-based application.

In Part 1 of this series, we covered the evolution of network management from the early days of simple device-banks management to today's complex-yet-powerful Network Management Systems (NMS) and Enterprise Management Systems (EMS). JMX has come of age, extending the Java platform with manageability features. It allows Java platform-based software applications, services, and devices to be managed by NMS, EMS, and other management/control applications. JMX's modern architecture is both layered and component-based, with all functionality blocks separated by well-defined programming interfaces (see the Resources section).

This approach takes advantage of the best practices in modern software architectural designs today and delivers a compatible, extensible, and robust solution to Java software manageability at a low implementation cost. JMX is being adopted rapidly, with some modern open source server products already in second generation JMX integration. JMX is also becoming an integral part of almost all server/service components described in the J2EE 1.4 draft specifications.

Recall that JMX architecture can be broken into three levels:

  1. Instrumentation
  2. Agent
  3. Distributed Services

Only the instrumentation level and part of the agent level are defined in the latest available JMX specifications (1.1 at the time of writing). Detailed specifications for the rest of the JMX architecture is still a work in progress.

In this article, we will work with the JMX 1.1 reference implementation to add instrumentation to an existing software application.

A simple GUI application: ClickMeter
Our sample application, ClickMeter, is a Swing-based GUI utility that features a classic MVC design. It displays a "numeric meter" on its GUI and two buttons. Click the + button to increase the number displayed, or click the - button to decrease the number displayed. Table 1 lists the files in the application:

Table 1. Files in the ClickMeter GUI application
Filename Description
ClickMeter.java The class with the static main method that we will execute; creates the GUI frame, centers it, and displays it
ClickFrame.java The frame container that holds ClickPanel
ClickPanel.java The single source file that contains three classes: ClickPanelModel (the model), ClickPanel (the view), and ClickPanelController (the controller) for our GUI application

The view class responsible for GUI presentation is ClickFrame, a subclass of javax.swing.JPanel. It creates the GUI elements, lays them out on the panel, and manages the user's interactions with the GUI. The MVC action of ClickMeter is illustrated in Figure 1:

Figure 1. MVC interactions of ClickMeter
Figure 1. MVC interactions of ClickMeter

Download the source

To work along with the examples in this article, make sure you download the source code. In addition, you should also download and install the JMX 1.1 reference implementation (see the Resources section for all download information). Of course, we assume that you already have JDK 1.4 or later installed and running.

In Figure 1, the ClickPanelModel (the model) maintains one single int value (called val) that represents the instantaneous value of the meter. To access this value, you must go through the methods of the ClickPanelModel class. These methods include set(), get(), increment(), and decrement() for the val variable. ClickPanel is a classic Observer of ClickPanelModel. Whenever the value of ClickPanelModel changes, it notifies ClickPanel of the changes with a call to the NotifyUpdate() method.

At this time, ClickPanel fetches the changed value of the model and redisplays it on the GUI panel that holds the value. This ensures that the value displayed in ClickPanel is always consistent with the value of ClickPanelModel. To complete the loop, ClickPanel manages the user interactions with the GUI (such as clicking on one of the two buttons), then forwards any action to ClickPanelController (using the onIncButtonClicked or onDecButtonClicked methods). ClickPanelController coordinates the GUI action with the desired meter operation by modifying the values of ClickPanelModel. This is done by calling the incPanelValue() and decPanelValue() methods of ClickPanelController.

Trying out ClickMeter: JMX free
Use the compile.bat batch file supplied in the code distribution to compile the application, or execute the following command line from the code subdirectory:


javac -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar 
-d classes src\dwjmxservice\basic\*.java

Use the runmeter.bat file to run the application, or execute the following command line from the code subdirectory:


java -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeter

Figure 2 shows the application running. You can click on the two buttons to increase or decrease the meter value at any time.

Figure 2. The ClickMeter GUI application
Figure 2 The ClickMeter GUI application

One important thing to note is that the entire application is designed without manageability in mind. That is, there is absolutely no reference to any JMX classes and it is not structured in any manner that makes addition of JMX code any easier or more difficult. Simply put, it is reflective of a well-designed Java GUI application -- without concern for adaptability to JMX operations. And this is the essence of JMX: it can be easily added to any application or software server/service to make them instantly manageable. This "easy add" feature of JMX results in very low implementation development costs. Next, you'll see how you can quickly add instrumentation to the ClickMeter app.

Planning instrumentation
Instrumentation can be added to any Java program, including any software service, server, or applications. Instrumentation refers to manageable attributes (properties), operations (methods), and events that may be exposed to the JMX agents (and to EMS or the management application through these agents). The JMX designer must first decide on the instrumentation to add.

Attributes type

When you add attribute instrumentation to a Java application, use only Java object data types and not primitive data types (for instance, use instead of int). The reference implementation does not work well with primitive types.

You can readily add instrumentation to manage networking devices and software services/servers. For a networking device, attributes could be the IP address and port of the device used, the protocols that are supported, the parameters for the protocols, and so on. Operations on a device may include a reset to factory default, a reboot, a firmware upgrade, and so on. For a Web application server, attributes may be the total number of hits per unit time, the amount of CPU time utilized on the server, or the mix of applications executed on the server. Operations on an application server may include reset, reboot, and application loads and unloads on the server.

But our primary concern is with ClickMeter. What should be managed for ClickMeter? Table 2 offers some answers:

Table 2. Managed elements
Managed elements Type Description
PanelValue attribute The instantaneous value of the meter; same as the value maintained by ClickPanelModel
incPanelValue operation Increments the meter value by 1; same action as the user clicking the + button
decPanelValue operation Decrements the meter value by 1; same action as the user clicking the - button

The first step to add instrumentation is to make sure the manageable elements are easily accessible. To facilitate this, we'll add a few methods to the ClickMeter class. To preserve the ClickMeter application -- leaving it free of JMX code altogether -- we create a subclass of ClickMeter, called ClickMeterInstrm. The methods for this class are shown in Table 3:

Table 3. Methods exposing attributes and operations for ClickMeterInstrm
Method Description
getPanelValue() Obtains the current value of the meter through the model (ClickPanelModel)
setPanelValue() Sets the current value of the meter by using the model to set the value, since we know that the MVC pattern design will ensure that all views synchronize with the model
incPanelValue() Increments the value of the meter by 1 -- through the model
decPanelValue() Decrements the value of the meter by 1 -- through the model

Listing 1 shows the ClickMeterInstrm class implementation:

Listing 1. ClickMeterInstrm code


package dwjmxservice.basic;

public class ClickMeterInstrm extends ClickMeter {

  public ClickMeterInstrm() {
  }

  // code added to instrument for JMX Instrumentation
  public void setPanelValue(Integer val) {
      frame.clickPanel.myModel.setVal(val.intValue());
  }
  public Integer getPanelValue() {
   return new Integer(frame.clickPanel.myModel.getVal());

  }
  public void incPanelValue() {
  frame.clickPanel.myModel.incVal();

  }
  public void decPanelValue() {
  frame.clickPanel.myModel.decVal();
  }
}

Notice how the implementation of the new methods shown in Listing 1 uses ClickPanelModel to change the meter's value. The setPanelValue() and getPanelValue() methods/operations provide the JavaBeans-compliant naming convention that exposes a PanelValue property/attributes. This will become important shortly as we add standard MBean support.

The original GUI application, ClickMeter, is still completely intact and unaffected by this addition.

Now that we have added logic to support access of the single attribute and two operations, we can add the mechanism to expose them to management agents. To accomplish this, we add JMX MBean (managed bean) support to our ClickMeter application. As we learned in Part 1, there are at least two different major styles of implementation for MBeans, as shown in Table 4:

Table 4. Two different styles of MBean implementation
MBean Implementation Description
Standard All attributes, operations, and events are defined at compile time by a fixed management interface
Dynamic The managed attributes, operations, and events supported by the MBean is not determined until run time -- and can dynamically change between invocation or even during a single management session

The quickest and simplest way to add instrumentation to ClickMeter is to use a standard MBean implementation.

Implementing a standard MBean
In a standard MBean, all of the attributes, operations, and events that are exposed to management agents are specified in a fixed interface. The name of this interface must follow the lexical pattern <class name of the service/application/Device>MBean.

In our example, we have created a ClickMeterInstrm subclass called ClickMeterStd that will contain our ClickMeter application with standard MBean instrumentation. Because the name of the application is ClickMeterStd, the standard MBean instrumentation must follow the lexical pattern and be named ClickMeterStdMBean. Listing 2 defines the interface for ClickMeterStdMBean.java (available in the source code distribution):

Listing 2. ClickMeterStdMBean management interface


package dwjmxservice.basic;

public interface ClickMeterStdMBean {
  public void setPanelValue(Integer inVal);
  public Integer getPanelValue();
  public void incPanelValue();
  public void decPanelValue();
}

In Listing 2, the exposed attributes are listed as public getter and setter methods (for our PanelValue attribute), and the operations are also public methods (our incPanelValue() and decPanelValue() operations).

The JMX agent will use standard Java introspection to determine the attributes and operations supported by the MBean during run time. Now we'll create a simple JMX agent.

Creating a simple JMX agent
A JMX agents loads MBeans through MBeanServer (whose interface is defined in JMX specs). It also provides a set of required agent services (see Part 1 of this series for more details), as well as protocol adapters or connectors to connect to JMX managers or EMS/NMS directly.

The emergence of increasingly intelligent network devices, PCs, and peripherals has created a demand for more and more intelligence in the daily management and monitoring of these endpoints. Furthermore, the increasing demand to conduct business over the Internet has created a new breed of endpoints for EMS to support -- that of intelligent software servers/services.

Figure 3 should remind you of the componentized composition of a JMX agent. In the JMX architecture, the agent layer aggregates MBeans and exposes attributes, operations, and events for the distributed services layer to manage. An agent can either pass through the manageable elements from the MBeans that it aggregates directly, or provide value-added features and exposures to its own set of manageable elements.

Figure 3. Composition of a JMX agent
Figure 3. Composition of a JMX agent

The reference implementation provides all the required elements of a simple agent. However, the only connection to the outside world that is fully implemented is an HTML protocol adapter. This protocol adapter allows a Web browser to view and access the manageable elements from all the MBeans managed by the agent.

Let's add code to configure the agent and work with its protocol adapter. We add support for starting the JMX reference implementation agent into ClickMeterStd. Listing 3 shows the code responsible for instantiating and starting the agent:

Listing 3. Code to instantiate and start a JMX agent


    BaseStdAgent myAgent = new BaseStdAgent();
    myAgent.startAgent((Object) cms);

Notice the use of a BaseStdAgent class (see BaseStdAgent.java in the source distribution). Essentially, the logic in the agent includes the following procedural steps:

  1. Start MBeanServer.
  2. Register the MBeans managed with MBeanServer.
  3. Start the protocol adapters and connectors.

In production coding, most agent services required by JMX specifications are also loaded as MBeans. This means that Step 2 will also register all the agent service's MBeans. In fact, in the case of the HTML protocol adapter that we work with here, it is also an MBean. Listing 4 shows the code in BaseStdAgent.java that performs Step 1:

Listing 4. Code in BaseStdAgent to create and start MBeanServer


System.out.println("Creating the MBeanServer....");
  MBeanServer server = MBeanServerFactory.createMBeanServer();

Listing 5 shows the code that performs Step 2. In this case, the first MBean is passed into BaseStdAgent as the inMBean parameter. We also give it a user-readable ObjectName.

Listing 5. Registering managed MBeans with MBeanServer


  try {
        ObjectName tpMBeanName = new ObjectName("MBean:name=ClickMeter");
        server.registerMBean(inMBean, tpMBeanName);
      } catch (Exception e) {
         System.out.println("Cannot register ClickMeter MBean!");
         e.printStackTrace();
         return;
      }

The last portion of code in BaseStdAgent starts the HTML protocol adapter, located in the com.sun.jdmk.comm.HtmlAdaptorServer class. Listing 6 shows how to set up and start the protocol adapter. By default, it monitors port 8082 for HTML browser connects. Note the use of the server.registerMBean() method to register the HTML protocol adapter, which itself is an MBean.

Listing 6. Creating and starting the HTML protocol adapter


  System.out.println("Creating an HTML protocol adaptor..");
  HtmlAdaptorServer hadaptor = new HtmlAdaptorServer();
  ObjectName adaptorName = null;
  try {
      adaptorName = new ObjectName("Adaptor:name=hadaptor,port=8082");
      server.registerMBean(hadaptor, adaptorName);
  } catch(Exception e) {
      System.out.println("Cannot create the HTML protocol adaptor!");
      e.printStackTrace();
      return;
  }
  hadaptor.start();

That is all the code in our simple agent. If we were to support more agent services, they would be registered with MBeanServer the same way as the HTML protocol adapter.

One thing to note is that the simple JMX agent code is written independently of the MBean that it is to manage (both ClickMeterStd and HtmlAdaptorServer). In the same way, the MBean code was written independently of the agent that may eventually be used to manage it. This is the essence of JMX's multi-level architecture. The MBeans at the instrumentation level are designed to be loosely decoupled to the agent logic at the agent level.

Connecting to the JMX agent through the HTML protocol adapter
Use the compile.bat file to compile the ClickMeterStd application with full instrumentation and agent support, or execute the following command line from the code subdirectory:


javac -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar 
-d classes src\dwjmxservice\basic\*.java

Use the runstd.bat file to start the ClickMeterStd application, or execute the following command line from the code subdirectory:


java -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeterStd

This command starts the ClickMeter application as well as the JMX agent. Try the buttons on the ClickMeter application. Because we did not modify a single line of ClickMeter code when we added JMX instrumentation, the ClickMeter still works identically as before. However, the standard MBean for ClickMeter has been loaded into the JMX agent and the HTML adapter has been started. This allows us to access the agent immediately. Start your browser and point it to:


http://localhost:8082/

You should see an agent-produced page similar to Figure 4:

Figure 4. Main agent view page for HTML protocol adapter
Figure 4. Main agent view

We can see all the MBeans managed by this agent. Click name=ClickMeter. You should see a page similar to Figure 5:

Figure 5. Detailed ClickMeter MBean view for HTML protocol adapter
Figure 5. Detailed ClickMeter MBean view

Notice the PanelValue attribute that is exposed by the MBean, as well as the incPanelValue and decPanelValue operations. If you set a reload time, the client-side JavaScript code from the agent will poll the value of the PanelValue attribute regularly and update the displayed value. Try a reload time of 5 to 10 seconds and see the update. You can also click the GUI buttons on ClickMeter to change the value.

Next, try the following:

  • Click the incPanelMeter operation to increase the meter value. Note how we can easily access this operation -- as a JMX management application may do through the agent.

  • Click the decPanelMeter operation.

  • Set the value of the PanelValue attribute. Note how it is updated in ClickMeter immediately.

While we use the HTML protocol adapter in this case, other protocol adapters or connectors can readily be used (such as SNMP) and will make our ClickMeter manageable through other applications or EMS.

Recall that we did not have to tell the agent explicitly about the attributes and operations that are supported by the ClickMeterStd MBean. The agent actually discovered that itself by introspecting the ClickMeterStdMBean interface during run time. This is the standard operation of a JMX operation when working with a standard MBean. The agent locates this management interface during run time using introspection (via the required standard MBean lexical naming pattern).

Dynamic MBeans
A dynamic MBean is an MBean that implements the java.management.DynamicMBean interface. Table 5 shows the methods that must be implemented for this interface:

Table 5. DynamicMBean interface methods
Method Name Description
getAttribute() Gets the name of an attribute, then returns its current value as a Java object
getAttributes() Gets the names of a list of attributes, then returns their current values as Java objects if available
setAttribute() Sets an attribute with the specified value
setAttributes() Sets the values of a list of attributes
invoke() Invokes a specified operation; parameters are provided and the return value is supported if applicable

Unlike the standard MBean, an agent relies on the DynamicMBean interface to obtain exposed attributes, operations, and an event's metadata information from the MBean during run time. This means that it is not necessary to follow the lexical pattern (JavaBeans coding convention) when you add instrumentation to an application. An agent does not need to perform introspection on the MBean when working with a dynamic MBean. It trusts the metadata received from the bean from the getMBeanInfo() call. Because the MBean manufactures this data during run time, it is possible for that to change without having to recode any statically defined interface. The quickest way to start to work with a dynamic MBean is to use ModelMBean.

Instant dynamic MBean support: ModelMBean
ModelMBean is a required default MBean implementation that exists in all JMX implementations. The JMX specs precisely specify how to access an instance of ModelMBean. Because it is fully implemented by the JMX implementation, the model MBean's advantage lies in its ease of use and adaptability. Typically at run time, the application, service, server, or device can instantiate an instance of ModelMBean to be its representation to the other JMX levels.

A model MBean is always a dynamic MBean (it has to be because there is no way it will know in advance who its user is, which means no advance knowledge of the attributes, operations, and events exposed is possible). In addition, a model MBean provides a ready-to-use, MBean facade (or wrapper) for any software application, service, server, or device. And it's guaranteed to be compatible because it is part of the implementation's own code.

Using ModelMBean to add instrumentation
Let's examine how to quickly add dynamic MBean instrumentation to ClickMeter using ModelMBean. We create a new subclass of ClickMeterInstrm called ClickMeterMod. Listing 7 shows the code for this class:


public class ClickMeterMod extends ClickMeterInstrm  {

  public ClickMeterMod() {
  }
  public static void main(String[] args) {

    setLandF();
    ClickMeterMod cms = new ClickMeterMod();
    BaseModAgent myAgent = new BaseModAgent();
    myAgent.startAgent((Object) cms);

  }

}

Note in Listing 7 that the ClickMeterMod class does not implement any special interfaces. It is completely decoupled from any compile-time JMX requirements. This is because we will hook it up to JMX during run time using a model MBean implementation that is already in the JMX reference implementation. This is actually performed in the agent represented by the BaseModAgent class.

Run-time hook up of a model MBean in a JMX agent
When you use the ModelMBean implementation, the only work that is necessary is to provide a proper ModelMBeanInfo structure to the ModelMBean "wrapper" instance. Listing 8 shows an excerpt from the BaseModAgent class:


    try {
        ObjectName tpMBeanName = new ObjectName("MBean:name=ClickMeter");
        RequiredModelMBean modelmbean = 
          new   RequiredModelMBean(createMBeanInfo());
        modelmbean.setManagedResource(inManagedObj, "objectReference");
        server.registerMBean(modelmbean, tpMBeanName);
      } catch (Exception e) {
         System.out.println("Cannot register ClickMeter MBean!");
         e.printStackTrace();
         return;
      }

In Listing 8, the javax.management.modelmbean.RequiredModelMBean class is instantiated with a call to the local createMBeanInfo() method. This method will create the metadata that describes the attributes, operations, and events that are exposed by the MBean. Note in addition that we make a call to the setManagedResource() method of the RequiredModelMBean to give it our reference of the ClickMeterMod "class to wrap." In fact, with the JMX reference implementation, this reference can also be an RMI reference or a CORBA IOR -- allowing remote resources to be instrumented readily using ModelMBean. Finally, notice that when we call registerMBean() on the MBeanServer, it is the RequiredModelMBean wrapper instance that we register, and not the non-MBean ClickMeterMod. Figure 6 shows how the RequiredModelMBean works during run time:

Figure 6. Run-time operation of RequiredModelMBean
Figure 6. Run-time operation of RequiredModelMBean

Figure 6 illustrates how the agent layer works exclusively with the RequiredModelMBean instance, while the RequiredModelMBean instance in turn maps the attributes' accesses and operations to the actual wrapped ClickMeterMod class. This alleviates any requirement for JMX dependency on the part of the wrapped class.

Filling in ModelMBean metadata
The RequiredModelMBean instance is supplied with a metadata descriptor when instantiated. This descriptor is an instance of the javax.management.modelmbean.ModelMBeanInfo class. It contains complete information on the attributes, operations, and events exposed by the wrapped class (and, more importantly, how RequiredModelMBean should access them). RequiredModelMBean will generate its own metadata at run time to support the DynamicMBean interface on behalf of the wrapped class. Listing 9 shows this code in the createMBeanInfo() method:


private ModelMBeanInfo createMBeanInfo() {
    Descriptor atDesc = new DescriptorSupport(new String[] {
                 "name=PanelValue",
                 "descriptorType=attribute",
                 "default=0",
                 "displayName=Value of the Panel",
                 "getMethod=getPanelValue",
                 "setMethod=setPanelValue"
                }
                );

    ModelMBeanAttributeInfo [] mmbai = new ModelMBeanAttributeInfo[1];
    mmbai[0] = new ModelMBeanAttributeInfo("PanelValue","java.lang.Integer",
      "The ClickMeter Value",  true,true, false, atDesc);

    ModelMBeanOperationInfo [] mmboi = new ModelMBeanOperationInfo[4];

    mmboi[0] = new ModelMBeanOperationInfo("incPanelValue", 
    "increment the meter value", null, "void", ModelMBeanOperationInfo.ACTION
    );

    mmboi[1] = new ModelMBeanOperationInfo("decPanelValue", 
    "decrement the meter value", null, "void", ModelMBeanOperationInfo.ACTION
    );

    mmboi[2] = new ModelMBeanOperationInfo("getPanelValue", 
    "getter for PanelValue", null,"Integer", ModelMBeanOperationInfo.INFO);

    MBeanParameterInfo [] mbpi = new MBeanParameterInfo[1];
    mbpi[0] =  new MBeanParameterInfo("inVal", "java.lang.Integer", 
      "value to set");
    mmboi[3] = new ModelMBeanOperationInfo("setPanelValue",
      "setter for PanelValue", mbpi, "void", ModelMBeanOperationInfo.ACTION);


    ModelMBeanConstructorInfo [] mmbci = new ModelMBeanConstructorInfo[1];
    mmbci[0] = new ModelMBeanConstructorInfo("ClickMeterMod", 
    "constructor for Model Bean Sample", null);

    return new ModelMBeanInfoSupport("dwjmxservice.basic.ClickMeterMod",
    "dw ModelMBean example", mmbai, mmbci, mmboi, null);
    }

The important feature to notice in Listing 9 is how the javax.management.modelmbean.ModelMBeanInfoSupport class provides a ready-to-use MBeanInfo implementation. In fact, the entire method deals with instantiating an instance of this support class. To instantiate it properly, you must supply the fully qualified name of the wrapped class, a description, and then four additional parameters that specify the attributes, constructors, operations, and events that are to be exposed. Most of the code in this method centers on creating the ModelMBeanAttributeInfo, ModelMBeanConstructorInfo, and ModelMBeanOperationInfo arrays that are parameters to the constructor of the ModelMBeanInfoSupport class. Notice that the getter and setter methods on the PanelValue attribute is defined again in the operation's metadata. This is necessary because lexical patterns (naming conventions) are not required to be followed in the wrapped class. In addition, the RequiredModelMBean trusts the metadata supplied and will not perform additional introspection on the wrapped class (it may not even be possible if the reference is remote or CORBA-based).

Testing model MBean-based instrumentation
Use the compile.bat file to compile the model MBean example, or execute the following command line:


javac -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar 
-d classes src\dwjmxservice\basic\*.java

Use the runmod.bat file to run the model MBean example, or execute the following command line from the code subdirectory:


java -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeterMod

When you test this MBean using the HTTP protocol adapter, notice how it is almost indistinguishable from the agent operation point of view. The only difference is that the getter and setter operations for the PanelValue are also accessible independently through the Web page.

Instead of performing a "quick adaptation" to JMX using the RequriedModelMBean class, you can create a substantially more flexible dynamic MBean by programming directly to the DynamicMBean interface.

Implementing DynamicMBean without RequiredModelMBean
Adding dynamic MBean instrumentation to the ClickMeter class is a matter of implementing all the methods of the javax.management.DynamicMBean interface. We create a subclass of ClickMeterInstrm called ClickMeterDyn to do this. Listing 10 shows the code for ClickMeterDyn:


package dwjmxservice.basic;

import javax.management.MBeanInfo;
import javax.management.DynamicMBean;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanInfo;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanOperationInfo;

public class ClickMeterDyn extends ClickMeterInstrm implements DynamicMBean {

  public ClickMeterDyn() {
  }

  public static void main(String[] args) {
   setLandF();
   ClickMeterDyn cms = new ClickMeterDyn();
    // can use standard MBean agent - same logic
    BaseStdAgent myAgent = new BaseStdAgent();
    myAgent.startAgent((Object) cms);

  }

// implements the dynamic MBean interface

public Object getAttribute(String inAttrName) {
  if (inAttrName.equals("PanelValue"))
               return ((Object) getPanelValue());
  else
           return null;
}

    public void setAttribute(Attribute attribute) {
      if (attribute.getName().equals("PanelValue"))
        setPanelValue((Integer)  attribute.getValue());
}

      public AttributeList getAttributes(String[] attributeNames) {
  AttributeList resultList = new AttributeList();

  for (int i=0 ; i<attributenames.length ; i++){
      try {

    resultlist.add(new attribute(attributenames[i],
                (object) getattribute( (string) attributenames[i])
                ));
      } catch (exception e) {
    e.printstacktrace();
      }
  }
  return(resultlist);

    }
    public attributelist setattributes(attributelist attributes) {
  attributelist resultlist="new" attributelist();

  for (int i="0;" i<attributes.size(); i++) {
      attribute attr="(Attribute)" attributes.get(i);
      try {
    setattribute(attr);
    string name="attr.getName();"

    resultlist.add(new attribute(name,
                (object) getattribute(name)));
      } catch(exception e) {
    e.printstacktrace();
      }
  }
  return(resultlist);
  }

  public object invoke(string opname, object params[], string signature[]) {

  if (opname.equals("incPanelValue")){
      incPanelValue();

  } else {

        if (opname.equals("decPanelValue")) {
            decPanelValue();
            }
      }
      return null;
  }
  public mbeaninfo getmbeaninfo() {
     mbeanattributeinfo [] mbai="new" mbeanattributeinfo[1];
      mbai[0]="new" mbeanattributeinfo("panelvalue",
            "java.lang.integer",
            "the panel value",
            true,
            true,
            false);

    mbeanconstructorinfo [] mbci="new" mbeanconstructorinfo[1];
    mbci[0]="new" mbeanconstructorinfo("clickmeterdyn", 
    "dynamic mbean click meter", null);

    mbeanoperationinfo [] mboi="new" mbeanoperationinfo[2];
    mboi[0]="new" mbeanoperationinfo("incpanelvalue", 
    "increment the meter value", null, "void", mbeanoperationinfo.action);
    mboi[1]="new" mbeanoperationinfo("decpanelvalue", 
    "decrement the meter value", null, "void", mbeanoperationinfo.action);
    return  new mbeaninfo("dwjmxservice.basic.clickmeterdyn",
           "mbean:click meter",
           mbai,
           mbci,
           mboi,
           null);
    }

  }

The first thing to notice here is that ClickMeterDyn implements the DynamicMBean interface directly, as required. We can also see that the dynamic MBean gets its metadata information from a call to the getMBeanInfo() method. The code in this method is similar to what we saw in the model MBean case, but not quite the same. The main difference is that we do not have to redefine the getter and setter methods of the PanelValue attribute as part of the operations exposed.

For the attribute getter/setter methods, we compare the incoming attribute name with our only attribute, PanelValue, and set or get the value from ClickPanelModel accordingly. The invoke() method is handled by comparing the name of the incoming operation with the two operations that we support: incPanelValue or decPanelValue. Because these operations use no incoming parameters and do not return values, we simply invoke the corresponding incPanelValue() method or decPanelValue() method in the ClickMeterInstrm class when a match is made.

Testing the dynamic MBean
Notice in Listing 10 that ClickMeterDyn actually uses BaseStdAgent as its JMX agent. This is because there is no operational difference from an agent perspective when working with dynamic MBeans or standard MBeans. Again, this is the aspect of the JMX architecture that gives it maximum flexibility and extensibility.

Use the compile.bat file to compile the dynamic MBean example, or execute the following command line:


javac -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar 
-d classes src\dwjmxservice\basic\*.java

Use the rundyn.bat file to run the dynamic MBean example, or execute the following command line in the code subdirectory:


java -classpath <jmx install dir>\lib\jmxri.jar;<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeterDyn

When you test the dynamic MBean, notice how it behaves exactly like the standard MBean example.

Don't miss the rest of this series

Part 1, "Management, JMX 1.1 style" (September 2002)

Part 3, "Hands-on JMX integration" (December 2002)

Conclusions
When you add instrumentation to an existing device or software service, you typically have a choice of using a standard MBean or dynamic MBeans, including model MBeans. Standard MBeans are great for quick instrumentation, but not adaptable to changes. Dynamic MBeans are resilient to change of attributes, operations, and events exposed; however, programming them requires a little more effort. Using model MBeans gives the best of both worlds by enabling adaptive change without extensive coding and testing.

In the upcoming final article of this series, we will take a look at how JMX MBeans and agents work with a real-life Network Management System. Stay tuned!

Resources

  • Download the source code and script files for this article.

  • The latest JMX specification, reference implementation, and compatibility test suite can be downloaded from Java Management Extensions (JMX).

  • For a completely open source implementation of JMX 1.1 and the current JMX used by Jakarta Tomcat, check out the MX4J project.

  • For more information on SNMP, consult the IETF RFC 1157 or see the latest developments in SNMP Version 3.

  • If you're interested in CIM/WBEM, take a look through the Distributed Management Task Force Web site for detailed information and the latest developments.

  • You can download the latest version of the Tomcat 4.1.x server, instrumented using JMX 1.1, from The Jakarta Project. Source code distribution is also available.

  • For ongoing work on the specification of JMX distributed services, protocol adapters, and connectors, see JSR 160 JMX Remoting 1.2, JSR 146 WBEM Services, and JSR 70 IIOP Protocol Adapter for JMX.

  • JMX features an agent connector/adapter architecture similar to the J2EE Connector architecture.

  • J2EE 1.4 will feature completely JMX-instrumented containers. Download the latest version of the emerging J2EE 1.4 specification.

  • Tivoli software from IBM features secure enterprise management solutions that support a wide variety of existing and emerging network management standards, including TMX4J, a JMX-compatible implementation, available from alphaWorks.

  • Be sure to visit the newest IBM product domain Tivoli Developer Domain for technical information about Tivoli software and security products.

About the author
Photo of Sing LiSing Li is the author of Early Adopter JXTA and Professional Jini, as well as numerous other books with Wrox Press. He is a regular contributor to technical magazines, and is an active evangelist of the P2P evolution. Sing is a consultant and freelance writer, and can be reached at westmakaha@yahoo.com.


code67KBe-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Comments?



developerWorks > Java technology
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact