当您使用
ModelMBean
实现时,唯一必需的工作就是向
ModelMBean
“封装器”实例提供合适的
ModelMBeanInfo
结构。清单 8 显示了来自
BaseModAgent
类的摘录:
清单 8. BaseModAgent.java 中 RequiredModelMBean 的运行时挂接
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;
}
|
在清单 8 中,通过对本地
createMBeanInfo() 方法的调用对
javax.management.modelmbean.RequiredModelMBean 进行实例化。这种方法将创建描述由 MBean 公开的属性、操作和事件的元数据。另外请注意我们调用了
RequiredModelMBean 的
setManagedResource() 方法,向它提供
ClickMeterMod 这一“要封装的类”的引用。事实上,通过使用 JMX 参考实现,该引用还可以是 RMI 引用或 CORBA IOR - 允许使用
ModelMBean 方便地“工具化”远程资源。最后,请注意当我们在 MBeanServer 上调用
registerMBean() 时,我们注册的是
RequiredModelMBean 封装器实例,而不是非 MBean 的
ClickMeterMod 。图 6 显示了
RequiredModelMBean 在运行时期间是如何工作的:
图 6. RequiredModelMBean 的运行时操作
图 6 说明了代理层如何只与
RequiredModelMBean 实例一起工作,而
RequiredModelMBean 实例又依次将属性的访问和操作映射到真正封装的
ClickMeterMod 类。这就减轻了对部分封装类的 JMX 相关性的任何要求。
实例化
RequiredModelMBean 实例时会向其提供元数据描述符。该描述符是
javax.management.modelmbean.ModelMBeanInfo 类的实例。它包含关于封装类公开的属性、操作和事件的全部信息(而且,更重要的是,还包含
RequiredModelMBean 应如何访问它们的信息)。
RequiredModelMBean 将在运行时生成它自己的元数据以代表封装类支持
DynamicMBean 接口。清单 9 显示了
createMBeanInfo() 方法中的这段代码:
清单 9. 在 createMBeanInfo() 方法中创建 ModelMBean 元数据
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);
}
|
在清单 9 中要注意的重要特性是
javax.management.modelmbean.ModelMBeanInfoSupport 类如何提供现成可用的
MBeanInfo 实现。事实上,整个方法都在处理这个支持类实例的实例化工作。要对它适当进行实例化,您必须提供封装类的完全限定名称以及描述,然后是指定将要公开的属性、构造器、操作和事件的四个附加参数。该方法的大多数代码主要是创建
ModelMBeanAttributeInfo 、
ModelMBeanConstructorInfo 和
ModelMBeanOperationInfo 数组,这些数组都是
ModelMBeanInfoSupport 类构造器的参数。请注意,用于
PanelValue 属性的 getter 方法和 setter 方法在操作的元数据中被再次定义。这是必需的,因为在封装类中不要求遵循词法模式(命名约定)。另外,
RequiredModelMBean 信任所提供的元数据并且将不在封装类上执行额外的内省(如果引用是远程的或是基于 CORBA 的,那么这个操作甚至是不可能的)。
使用 compile.bat 文件编译模型 MBean 示例,或者执行下列命令行:
javac -classpath
<jmx install dir>\lib\jmxri.jar;
<jmx install dir>\lib\jmxtools.jar
-d classes src\dwjmxservice\basic\*.java
|
使用 runmod.bat 文件运行模型 MBean 示例,或者从代码子目录执行下列命令行:
java -classpath
<jmx install dir>\lib\jmxri.jar;
<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeterMod
|
当您使用 HTTP 协议适配器测试这个 MBean 时,请注意从代理操作的角度来看,它几乎没什么不同。唯一的区别是,用于
PanelValue 的 getter 方法和 setter 方法操作还可以通过 Web 页面独立地使用。
不必使用
RequriedModelMBean 类对 JMX 执行“快速修改”,您可以通过对
DynamicMBean 接口直接编码来创建灵活得多的动态 MBean。
不用 RequiredModelMBean 来实现 DynamicMBean
将动态 MBean 工具添加到
ClickMeter 类是有关实现
javax.management.DynamicMBean 接口的所有方法的问题。我们创建名为
ClickMeterDyn 的
ClickMeterInstrm 子类来做到这一点。清单 10 显示了
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);
}
}
|
这里要注意的第一件事是,
ClickMeterDyn 按要求的那样直接实现了
DynamicMBean 接口。我们还可以看到动态 MBean 通过对
getMBeanInfo() 方法的调用获得元数据信息。该方法的代码和我们在模型 MBean 例子中看到的很类似,但不完全一样。主要的区别是我们不必将
PanelValue 属性的 getter 方法和 setter 方法重新定义为公开的操作的一部分。
针对属性的 getter/setter 方法,将入站属性的名称与我们唯一的属性
PanelValue 进行比较,并相应地从
ClickPanelModel 读写值。
invoke() 方法通过比较入站操作的名称和我们所支持的两个操作(
incPanelValue 或
decPanelValue )来进行处理。由于这些操作不使用入站参数且不返回值,因此进行匹配时我们只需调用
ClickMeterInstrm 类中相应的
incPanelValue() 方法或
decPanelValue() 方法。
请注意,在清单 10 中
ClickMeterDyn 实际上使用了
BaseStdAgent 作为其 JMX 代理。这是因为使用动态 MBean 或标准 MBean 时从代理的角度来看,没有操作上的区别。同样,JMX 体系结构给予它最大的灵活性和可扩展性。
使用 compile.bat 文件编译动态 MBean 示例,或者执行下列命令行:
javac -classpath
<jmx install dir>\lib\jmxri.jar;
<jmx install dir>\lib\jmxtools.jar
-d classes src\dwjmxservice\basic\*.java
|
使用 rundyn.bat 文件运行动态 MBean 示例,或者在代码子目录中执行下列命令行:
java -classpath
<jmx install dir>\lib\jmxri.jar;
<jmx install dir>\lib\jmxtools.jar;
classes dwjmxservice.basic.ClickMeterDyn
|
当您测试动态 MBean 时,请注意它是如何完全像标准 MBean 示例运行的。
当您将工具添加到现有的设备或软件服务中时,您通常可选择使用标准 MBean 或动态 MBean(包括模型 MBean)。标准 MBean 适合用于快速工具,但是不适合用于更改。动态 MBean 对于公开的属性、操作和事件的更改是有“弹性”的;但是, 对它们进行编程需要做更多的工作。使用模型 MBean 则取两家之长,支持自适应更改而无需大量编码和测试。
在本系列即将推出的最后一篇文章中,我们将了解 JMX MBean 和代理如何用于实际的网络管理系统。请静候下文!
- 下载本文的
源代码和脚本文件。
- 有关网络和企业管理的简介,请阅读本 JMX 1.1 系列的第一篇文章“
From black boxes to enterprises, Part 1: Management, JMX 1.1 style”(
developerWorks,2002 年 9 月)。
- 可从
Java Management Extensions (JMX)下载最新的 JMX 规范、参考实现和兼容性测试套件。
- 有关 JMX 1.1 的完整开放源码的实现及 Jakarta Tomcat 所使用的最新 JMX,请查看
MX4J项目。
- 有关 SNMP 的更多信息,请参考
IETF RFC 1157或查阅
SNMP V3的最新进展。
- 如果您对 CIM/WBEM 感兴趣,请浏览
分布式管理任务组(Distributed Management Task Force)网站以了解详细信息和最新进展。
- 可从
Jakarta 项目下载通过使用 JMX 1.1“工具化”的 Tomcat 4.1.x 服务器的最新版本。还可获取源代码分发版。
- 有关正在进行的 JMX 分布式服务、协议适配器和连接器规范的工作,请参阅
JSR 160 JMX Remoting 1.2、
JSR 146 WBEM Services和
JSR 70 IIOP Protocol Adapter for JMX。
- JMX 以代理连接器/适配器体系结构为特色,类似于
J2EE 连接器体系结构。
- J2EE 1.4 将以完全“工具化”的 JMX 容器为特色。请下载新出现的
J2EE 1.4 规范的最新版本。
-
IBM 的
Tivoli软件以安全的企业管理解决方案为特色,这些方案支持各种现有的和新出现的网络管理标准,包括
TMX4J(一个可从 alphaWorks 获取的兼容 JMX 的实现)。
- 请一定要访问最新的 IBM 产品园地的
Tivoli Developer Domain以获取关于 Tivoli 软件和安全性产品的技术信息。

Sing Li 是 Early Adopter JXTA 和 Professional Jini以及 Wrox Press 出版的许多其它书籍的作者。他定期为技术杂志撰稿,并且是 P2P 发展的积极传道者。Sing 是咨询顾问和自由作家,可以通过 westmakaha@yahoo.com与他联系。