 |
Why aren't MXBeans OpenMBeans?
Posted by emcmanus on September 16, 2005 at 07:08 AM | Comments (10)
In a
comment on my last entry, rgreig asks:
One thing that struck me about MXBeans is that they are
really fusion of standard MBeans and OpenMBeans, since they only
use standard types. However they don't actually conform to
OpenMBean conventions.
Why was the decision taken not to make MXBeans OpenMBeans?
(i.e. return an OpenMBeanInfo from getMBeanInfo())
Therein lies a tale!
MXBeans really are OpenMBeans. But as you note they don't
return OpenMBeanInfo. However, in Mustang, all the same information that would have been in the OpenMBeanInfo is present via
Descriptors.
Instead of...
MBeanInfo mbi = mbeanServer.getMBeanInfo(objectName);
MBeanAttributeInfo mbai = mbi.getAttributes()[0];
OpenMBeanAttributeInfo ombai = (OpenMBeanAttributeInfo) mbai;
OpenType ot = ombai.getOpenType();
...you can use...
MBeanInfo mbi = mbeanServer.getMBeanInfo(objectName);
MBeanAttributeInfo mbai = mbi.getAttributes()[0];
Descriptor d = mbai.getDescriptor();
OpenType ot = (OpenType) d.getFieldValue("openType");
This fusion of OpenMBeanInfo functionality into plain MBeanInfo
means that you can have OpenModelMBeans and other strange
beasts.
Nevertheless, we did originally plan for MXBeans to return
OpenMBeanInfo. The reason they don't is subtle.
In the original incarnation of MXBeans, in
java.lang.management, we wanted to use the type
long[] in the
ThreadMXBean. But OpenTypes didn't support arrays of
primitive types - they would only have supported
Long[], substantially less efficient. So we avoided
using OpenMBeanInfo in Tiger with the intent
of fixing this problem in Mustang.
It now is possible to have an
array of primitive type as an OpenType, so we could now
describe the ThreadMXBean with an OpenMBeanInfo. However, there
are some interoperability concerns that we didn't foresee.
Suppose you have a Tiger client, say
jconsole running on Tiger, talking to a Mustang server. Since
long[] didn't exist as an OpenType in Tiger, if we
sent an OpenMBeanParameterInfo with type
long[] to a Tiger, it will see it as if its type
were Long[]. Suppose it lets the user
call a method like
ThreadMXBean.getThreadInfo(long[] ids)
If jconsole saw an OpenMBeanParameterInfo for a
Long[] then it would expect the signature array in
MBeanServerConnection.invoke to contain
Long[].class.getName(),
i.e. "[Ljava.lang.Long;". But since the
parameter is really a long[], it should be
long[].class.getName(), i.e. "[J".
If you pass the wrong signature, the method invocation will
fail.
We could have envisaged various hacks to work around this
problem, but we decided it would be simpler to continue to use
MBeanParameterInfo rather than
OpenMBeanParameterInfo, with the Descriptor
containing the OpenType. In the example at hand, we'll have an
MBeanParameterInfo where
getDescriptor().getFieldValue("openType") returns
ArrayType.getPrimitiveArrayType(long[].class). On
Tiger, there's no such OpenType, but there's no Descriptor in
MBeanParameterInfo either so the inconsistency
evaporates. The Tiger client sees just the
MBeanParameterInfo.getType(), which is
"[J" as required.
For what it's worth, our implementation does use an
OpenMBeanParameterInfo when it doesn't contradict
the constraints I mentioned. In particular, if your attribute
or parameter is a CompositeData then even a Tiger
client will be able to see the corresponding
CompositeType using OpenMBeanParameterInfo.getOpenType().
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Thanks for the detailed response. I think I might have been tempted to employ a hack to work around the problem (e.g. have an annotation for "Tiger compatibility" that automagically creates an additional method for arrays of primitives that has arrays of appropriate Object as the argument) since the status of OpenMBeans is now slightly weakened. But I can see your dilemma.
I originally started thinking at this because I had looked at WebLogic 9.0 and was very impressed by its JMX support (compared with earlier versions). BEA appears to have implemented something very similar to MXBeans - it is interesting to note that they don't conform to OpenMBean exactly either but do the type morphing. I haven't checked whether they put a similar amount of extra info into the Descriptor (which they definitely augment).
The other useful thing that BEA adds is hierarchy. I think that most people will end up with a hierarchy of MBeans. I am not yet sure whether some kind of system support for hierarchies would be useful (it may in fact be trivial) but I suspect it might be.
Thanks again for the interesting blog entry.
Posted by: rgreig on September 16, 2005 at 12:49 PM
-
There are some very smart people at BEA working on JMX technology. The idea of
inter-MXBean references came from one of them, Charles Paclat, who is a member of the JSR 255 Expert Group.
By hierarchy are you talking about inheritance? For example if I have this...
public interface ProductMXBean {
public ModuleMXBean[] getModules();
}
...then some of the returned ModuleMXBeans might actually be PersistentModuleMXBean, say. On the client, if you a proxy for ProductMXBean and it calls getModules(), then in the returned array some of the proxies would actually be PersistentModuleMXBean proxies.
The standard MXBean framework in Mustang doesn't support this. There are some fairly tricky issues involved. In order to know that your remote ModuleMXBean is actually a PersistentModuleMXBean, you have to call getMBeanInfo on it, or hardwire some ObjectName convention. In either case it will presumably tell you the name of the subinterface ("PersistentModuleMXBean"), but what ClassLoader do you use to resolve that name?
Posted by: emcmanus on September 20, 2005 at 09:38 AM
-
Personally I feel the JMX legacy makes this way to bloated. Downsizing is required.
I dream about defining some basic data types for "open ness" and otherwise having only descriptor driven access (with a default reflection description for simple static beans).
So this means: no matter what kind of bean you have, it is interoperable if you stick to supported open data types.
No mattter how your bean is implemented (getter/setter, xml descriptor or dynamic getter/setter/invoker) you always use it the same way (vie the descriptor).
A "interface" based access may be optional. I dont really see static usages of the beans, often. Most of the clients do dynmic discovery and introspection.
Gruss
Bernd
Posted by: ecki on September 20, 2005 at 05:01 PM
-
Bernd, unfortunately our backward compatibility requirements make it very hard to downsize the API. But I'd certainly be interested in suggestions as to how it might be simplified by unifying existing concepts or introducting new powerful concepts and migrating the existing stuff to them.
I'm not sure what you're suggesting to do with descriptors. Is it something like Model MBeans? Perhaps you could give a little more detail here, or through mail to jmx-spec-comments@sun.com.
Posted by: emcmanus on September 21, 2005 at 09:15 AM
-
It was what you call "inter-MXBean references" that originally grabbed me in WebLogic 9.0 - at that point I didn't realise that Sun had come up with what you call MXBeans.
I was not thinking of something quite so sophisticated as inheritance although I can see that would be useful. (But to answer your question could you not either have some restriction that says that all MXBeans in a hierarchy must be loaded by the same classloader or put a name for the classloader in the description in MBeanInfo?)
I was actually just thinking about the fact that in WebLogic (for want of a better example) the hierarchy is basically done by convention using a comma separated list in the mbean name, e.g. com.bea:parent1,parent2,parent3 etc. I imagine a lot of clients will want to get the parents on startup and provide a tree-style view to allow navigation. If this were able to be done in a consistent, standardized way it might make these tools more valuable.
It would also be interesting to know what annotation, helpers and code generators the BEA guys wrote while building WLS 9.0.
Posted by: rgreig on September 27, 2005 at 02:10 PM
-
My idea is this, a management bean is essentially described by a Descriptor Instance (which implements the interface for enumerating and describing properties and methods). So yes somehow I mean JMX will only specify the API for model beans but provide common adapters for more specific implementations.
The key point of interfaction is the descrption of the bean instance:
description = bean.getDescriptor();
descriptor.invoke(methodname, args)
decriptor.get(propertyname)
descriptor.set(propertyname, value)
The data types supported by getters, setters and invoke are limtied to a portable subset.
the jmx implementation would provide an abstract descriptor with subclasses for accessing POJP or model beans. So you can still have simple or complex implementations on the backend, the spec does not describe the differences.
Bean implementors must only implement the descriptor which can be a total dynamic one or pick a sample one:
PojoMbean {
public MbeanDescriptor getDescriptor() {
return new PojoDescriptor(this); // lists properties by reflection
}
}
This covers implementation side of the beans. the user of the beans can dynamically interfact via descriptor interface. However a Factory which provides a implementation or a dynamic proxy could be provided:
PojoIntf pi = (PojoIntf)ProxyFactory.getProxy(descriptor, PojoIntf.class);
This is however a common helper which would be documented in spec appendix only (like the PojoDescriptor).
This way the API will only describe the interface of the descriptor interface.
I mean a major part o the jmx spec is describing x different types of beans with minimal differences... as you can see i dont have the names and sematics right now in my mind.
Sorry for the brainstorming without checking back with the exact terminology, I hope my idea is understandable anyway. If i have some time to show samples i will send them by mail..
- one dynamic interface used by provider/consumer
- limited data types for the getters/setter/operations
- helpers to implement and consume the dynamic interface backed up by a static interface
Gruss
Bernd
--
http://bernd.eckenfels.net
Posted by: ecki on September 27, 2005 at 05:13 PM
-
rgreig, the
JMX Best Practices document defines a convention for expressing containment in ObjectNames, which is what you are talking about I believe.
Posted by: emcmanus on September 28, 2005 at 11:18 AM
-
Bernd, this might have been a better approach if we were inventing the JMX API today. But I'm afraid we're not. :-)
I think the existing API works well enough, but it is true that there are too many types of MBean. This is a documentation problem as much as anything else, in that much of the existing documentation tends to launch straight into a discussion of MBean types, when really all you care about is Standard MBeans (including the javax.management.StandardMBean class) and, now, MXBeans. Dynamic MBeans are interesting but rarely useful except in the most advanced uses. Open MBeans are superseded by MXBeans. Model MBeans are mainly interesting for Descriptors, but in Mustang all MBeans have Descritpors so you get nothing extra from Model MBeans.
Descriptors also supersede OpenMBeanInfo and the rest, since information about OpenTypes is expressible in all types of MBeans via Descriptor entries. See the documentation for
javax.management.openmbean in Mustang.
Posted by: emcmanus on September 28, 2005 at 11:25 AM
-
Thanks for the link to the Best Practices document. I had not read it and it does contain roughly what I am looking for.
However, it does appear that JConsole (and the paltform MXBeans) don't have the same view of the world as the Best Practices document, at least around hierarchy naming conventions.
For example, in the java.lang domain we have beans without a name in the objectname and where the type is used as the "name", and also where the type is used as you would expect.
Examples:
java.lang:type=Compilation
java.lang:type=GarbageCollector,name=Copy
Should all MXBeans not have a type and a name in the object name?
If I create an MXBean that adheres (or at any rate that I think adheres!) to the guidelines, JConsole gets the tree wrong. For example:
my.domain:name=kermit,runtimeService=runtime01,type=runtimeService.broker
Comparing against the examples, that to me looks like it should have a broker called kermit at the leaf of a tree, yet JConsole puts it at the root.
Are there any plans to make 1.6 comply with the best practices guide? Or am I misunderstanding it?
Posted by: rgreig on October 06, 2005 at 09:31 AM
-
jconsole currently constructs its tree based on the order in which the keys appear in the ObjectName. So if you changed your name to this:
my.domain:type=runtimeService.broker,runtimeService=runtime01,name=kermit
then you would see the tree you expect.
I'm not sure this is the ideal behaviour, since the order of keys in an ObjectName is not supposed to be significant. We are looking into ways of changing this in a future version of jconsole, for example by allowing you to specify explicitly the order in which keys should be considered.
Posted by: emcmanus on October 07, 2005 at 09:40 AM
|