The Source for Java Technology Collaboration
User: Password:



Eamonn McManus

Eamonn McManus's Blog

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)

JConsole proposing ThreadMXBean operations

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 del.icio.us Digg Digg DZone DZone Furl Furl Reddit 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





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds