|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| Coding your own standard and dynamic MBeans
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:
- Instrumentation
- Agent
- 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
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
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
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:
- Start MBeanServer.
- Register the MBeans managed with MBeanServer.
- 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:
You should see an agent-produced page similar to Figure 4:
Figure 4. Main agent view page for HTML protocol
adapter
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
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 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.
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 Sing 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. |
|
|