I'm looking for help from someone with some experience deploying
DynamicMBeans to Tomcat.
In short, my questions boil down to some very basic information gaps:
once we have a DynamicMBean,
(1) What do we need to add to the server.xml file?
(2) What other configuration file(s) need to be created/edited?
(3) What are the contents of those files?
Please feel free to tell me to "Read The Fine Manual" ... but I've had
some trouble locating meaningful docs. If the answers I seek are
documented somewhere, a pointer to those docs would be greatly
appreciated. Otherwise, I would be happy to put something together,
maybe a small how-to, once I have things working. I think a step-by-step
set of instructions around a concrete (if very simple) example would be
useful to others trying to do similar things.
Let me share what I've learned so far:
According to the "MBean Descriptor How To"
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/mbeans-descriptor-howto.html
Once we have an MBean, it looks like we need to create a
mbean-descriptor.xml and add it to the list of "descriptors" in the
ServerLifecycleListener tag. Something like:
<Listener
className="org.apache.catalina.mbeans.ServerLifecycleListener"
descriptors="/scratch/mbean-descriptor.xml"
debug="0"/>
I have tried this and get a very curious error:
org.xml.sax.SAXParseException: The processing instruction target
matching "[xX][mM][lL]" is not allowed.
Should it be the "GlobalResourcesLifecycleListener" tag? Using that
seems to avoid the stack-trace, but then it doesn't look like the custom
DynamicMBean is being instantiated, so if this is correct, there's
something else missing.
I found one reference to someone else having similar confusion but was
not able to use the information to good advantage:
http://www.junlu.com/msg/93635.html
I didn't see a description the "Engine" tag suggested in this thread.
Assuming we are supposed to create "mbean-descriptor.xml" files (and the
SAXParseException can be over-come) ... are these files usually packaged
up in the jar file (with the MBean class files) deployed to server/lib?
That's where I've put it, for the moment, but I am not sure this is a
good practice. It doesn't seem right to package JMX Agent specific files
inside the jar; a different file is needed with JBoss, for instance.
I have not seen a good example of what this descriptor file is expected
to contain, especially for DynamicMBean where the attributes my not be
known at deployment time. If you know of an example, please post the
url.
Next the Descriptor How To suggests that "You may also add MBean
descriptions for custom components in
org.apache.catalina.mbeans.mbeans-descriptor.xml file." After some
searching, I think this file is normally only contained in the
catalina.jar file in the server/lib directory. This feels like messing
with the Tomcat internals. Ideally, I wouldn't want our new MBeans
exposed as part of Tomcat itself. So, I don't understand when or why we
should modify that file.
To provide an DynamicMBean deployment example, I've attached a simple
"LightBulb" class to be managed, as well as a very naive DynamicMBean to
manage it. If we really had an application this simple, we probably
wouldn't be using a DynamicMBean, but I've tried to create something
simple enough to let us focus on the deployment issues.
Any input (kind or cruel) is welcome.
Cheers,
-- Eric
--
Eric Herman, Software Developer
MySQL AB, www.mysql.com
Office: +1 206 720 1724
Are you MySQL certified? www.mysql.com/certification
package scratch;
import java.lang.reflect.Constructor;
import java.util.*;
import javax.management.*;
import com.mysql.management.util.*;
/** @author Eric Herman <[EMAIL PROTECTED]> */
public class LightBulbDynamicMBean implements DynamicMBean {
private LightBulb lightBulb;
private MBeanConstructorInfo[] consInfo;
private MBeanOperationInfo[] opsInfo;
private MBeanNotificationInfo[] notesInfos;
public LightBulbDynamicMBean() {
this.lightBulb = new LightBulb("white");
this.notesInfos = new MBeanNotificationInfo[0];
initConstructors();
initOperations();
}
private void initConstructors() {
Constructor con = getClass().getConstructors()[0];
consInfo = new MBeanConstructorInfo[1];
consInfo[0] = new MBeanConstructorInfo("Light Bulb", con);
}
private MBeanAttributeInfo[] getAttributeInfos() {
List attInfs = new ArrayList();
Iterator iter = lightBulb.getOptions().entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
String attName = (String) entry.getKey();
String description = "";
attInfs.add(new MBeanAttributeInfo(attName, String.class.getName(),
description, true, true, false));
}
return (MBeanAttributeInfo[]) attInfs
.toArray(new MBeanAttributeInfo[attInfs.size()]);
}
private void initOperations() {
this.opsInfo = new MBeanOperationInfo[2];
setOnOpInfo();
opsInfo[1] = new MBeanOperationInfo("report", "Report",
new MBeanParameterInfo[0], String.class.getName(),
MBeanOperationInfo.ACTION);
}
private void setOnOpInfo() {
opsInfo[0] = new MBeanOperationInfo("on", "Switch On",
new MBeanParameterInfo[0], "void", MBeanOperationInfo.ACTION);
}
private void setOffOpInfo() {
opsInfo[0] = new MBeanOperationInfo("off", "Switch Off",
new MBeanParameterInfo[0], "void", MBeanOperationInfo.ACTION);
}
public synchronized Object invoke(String methodName, Object args[],
String types[]) throws ReflectionException {
if (methodName.equals("on")) {
lightBulb.on();
setOffOpInfo();
return null;
}
if (methodName.equals("off")) {
lightBulb.off();
setOnOpInfo();
return null;
}
if (methodName.equals("report")) {
return lightBulb.report();
}
String msg = methodName + " not implemented";
throw new ReflectionException(new NoSuchMethodException(msg), msg);
}
public synchronized Object getAttribute(String attributeName)
throws AttributeNotFoundException {
if (!lightBulb.getOptions().containsKey(attributeName)) {
throw new AttributeNotFoundException(attributeName);
}
return lightBulb.getOptions().get(attributeName);
}
public synchronized AttributeList getAttributes(String[] attributeNames) {
AttributeList list = new AttributeList(attributeNames.length);
for (int i = 0; i < attributeNames.length; i++) {
String attName = attributeNames[i];
Object attValue = lightBulb.getOptions().get(attName);
Attribute attr = new Attribute(attName, attValue);
list.add(attr);
}
return list;
}
public synchronized MBeanInfo getMBeanInfo() {
return new MBeanInfo(this.getClass().getName(), "MySQL MBean",
getAttributeInfos(), consInfo, opsInfo, notesInfos);
}
public synchronized void setAttribute(Attribute attribute)
throws AttributeNotFoundException {
String name = attribute.getName();
if (!lightBulb.getOptions().containsKey(attribute.getName())) {
throw new AttributeNotFoundException(name);
}
lightBulb.getOptions().put(name, attribute.getValue());
}
public synchronized AttributeList setAttributes(AttributeList attributes) {
for (int i = 0; i < attributes.size(); i++) {
Attribute att = (Attribute) attributes.get(i);
try {
setAttribute(att);
} catch (Exception inconceivable) {
throw new Exceptions().toRuntime(inconceivable);
}
}
return attributes;
}
}package scratch;
import java.util.*;
import java.util.Map;
public class LightBulb {
boolean on = false;
private Map options = new HashMap();
public LightBulb(String color) {
options.put("color", color);
}
public Map getOptions() {
return options;
}
public void off() {
on = false;
}
public void on() {
on = true;
}
public String report() {
return (on) ? options.get("color") + " light" : "darkness";
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]