> Anyhow, I'm still working on the
> compliance/introspection and interceptor stuff I was
> talking about before - this time taking into account
> model mbeans.
> I'm approaching it from a particular angle that I
> need to check with you as being sane.
> First - a dynamic mbean is something which is a bit
> like a mini MBeanServer without a registry. i.e. the
> dmbean is responsible for describing and acting on a
> mgmt interface (invoke get|setAttribute etc).
> Second - as a convenience jmx gives you standard and
> model mbeans. As far as the exposed management
> interface goes, I see these two types of MBean as two
> different implementations of the same thing. They
> both effectively dispatch calls on the DynamicMBean
> interface to a target object according to rules set
> out in a descriptor. The difference is that model
> mbeans use a dynamic descriptor while standard mbeans
> have a compiled descriptor (XXXMBean interface).
> As such, the code I've been banging on is taking a
> shape where the end of the standard MBean invocation
> chain is pretty much identical to the end of the
> ModelMBean's invocation chain.
Right, however the current ModelMBeanInterceptor is a little misleading as its not strictly a correct implementation (need to fix that). The direct mapping of mgmt operations to a resource object's method is correct. However it should only be applied to mgmt attributes if their setMethod and getMethod descriptors are correctly set. However...
> It feels right but I need to know if you think there
> are any architectural gotchas in this approach
> (before I completely balls-up the code).
I've been thinking we should do away with the notion of different types of MBeans in the server altogether (as much as we can).
Standard MBeans are a convenience for the developer to automate the metadata generation. Today we already can feed a Java class (interface) using the Standard MBean naming conventions to the XMBean implementation and reuse the StandardMetaData class (implements MetaDataBuilder) to generate the same metadata.
The difference between the MBean type to the *client* is in MBeanInfo and all the metadata classes -- whether they implement the DescriptorAccess interface or not (which is a bit unfortunate IMHO, all meta data classes should implement this interface by default but that's not how it stands in the spec).
Given the above, why don't we internally (in the server) create Model MBeans also for the Standard MBeans. Create them with the Standard MetaDataBuilder and initialize with the default interceptor stack. To mimic the spec kludge with DescriptorAccess interface we need to make a copy of the ModelMBeanInfo and turn it into MBeanInfo in case the client originally registered the MBean as a Standard, instead of Model MBean (a field we need to store in the MBeanEntry?)
Having to deal with just one MBean type would simplify the implementation somewhat. What do you think?
> Right, however the current ModelMBeanInterceptor is a
> little misleading as its not strictly a correct
> implementation (need to fix that). The direct mapping
> of mgmt operations to a resource object's method is
> correct. However it should only be applied to mgmt
> attributes if their setMethod and getMethod
> descriptors are correctly set. However...
I've not looked but are you also catering for multiple target objects?
> I've been thinking we should do away with the notion
> of different types of MBeans in the server altogether
> (as much as we can).
> Standard MBeans are a convenience for the developer
> to automate the metadata generation. Today we already
> can feed a Java class (interface) using the Standard
> MBean naming conventions to the XMBean implementation
> and reuse the StandardMetaData class (implements
> MetaDataBuilder) to generate the same metadata.
We're on the same page as far as intent but I haven't gone down the route you specify.
> The difference between the MBean type to the *client*
> is in MBeanInfo and all the metadata classes --
> whether they implement the DescriptorAccess interface
> or not (which is a bit unfortunate IMHO, all meta
> data classes should implement this interface by
> default but that's not how it stands in the spec).
> Given the above, why don't we internally (in the
> server) create Model MBeans also for the Standard
> MBeans. Create them with the Standard MetaDataBuilder
> and initialize with the default interceptor stack. To
> mimic the spec kludge with DescriptorAccess interface
> we need to make a copy of the ModelMBeanInfo and turn
> it into MBeanInfo in case the client originally
> registered the MBean as a Standard, instead of Model
> MBean (a field we need to store in the MBeanEntry?)
I see what you mean. Let me explain where I am right now, perhaps it's a good enough starting point.
IMHO the only reason we have different MBean types is because for two of them (model and standard) we have to dispatch DynamicMBean calls to a target object(s).
The way I've gone is that there is an MBeanTarget object which implements Invoker and is the last invoker in the chain. Its constructor takes an argument of something that implements DynamicMBean.
For true DynamicMBeans the mbean instance is passed as the argument for the MBeanTarget constructor.
For standard MBeans (and modelmbean internals) an MBeanAdapter (which implements DynamicMBean) is used. The adapter's constructor takes a MetaMapper object as an argument.
The MetaMapper is used to lookup *something* that can act on a single attribute or operation via reflection.
The idea is that for standard mbeans you create a MetaMapper from the XXXMBean class while for ModelMBeans you create the MetaMapper from *Info and Descriptors.
I figured that the RequiredModelMBean (or whatever impl there is) would create a MetaMapper and an MBeanAdapter to call directly.
The important thing is that *creation* of the MetaMapper is undefined but the usage after creation is always the same.
> Having to deal with just one MBean type would
> simplify the implementation somewhat. What do you
I agree. When I'm done I'll package up my stuff and mail it to you to see if it makes a good starting point.
> I've not looked but are you also catering for
> multiple target objects?
No, didn't go that far yet. Do you have that already? We will need it eventually.
> I agree. When I'm done I'll package up my stuff and
> mail it to you to see if it makes a good starting
unless you see fundamental problems with the code I sent please hold off on the alpha release until I can integrate it.
I'm nearly certain that it will improve performance because there is no runtime reliance on *Info to make decisions on how to dispatch calls.
I've got the MBeanAdapter, AttributeProvider and OperationProvider sorted (including exception handling). Also, take a look at the Providers - they already cater for different target objects at dispatch time, as per ModelMBeans (it'll need new create() methods to set them up tho - the current ones are only for std mbeans).
If I do a late-nighter tonight I can get it integrated for standard MBeans by tuesday AM (GMT).
ModelMBeans can come after - I don't think my changes will break them in the interim. Come to think of it though - once I check in the core classes, changes to the ModelMBean impls can run in parallel if you want to work on it.
Do I have a go?
tomorrow it is.
I'm finishing some stuff with the class loader repository and mlets, will check the new classes after that.
Although I think they most likely are good. So go.
I really was thinking a lot about the JMX framework and the usage we do of it in JBoss. I think the classloaders should rely on the UCL framework for a way to share the classes across not only the implementation of the services but also the applications.
Finally when do we move the stack of interceptors as a "ModelMBean" with "stacking" in it... it would be fairly expensive and wont' make it by next week but definitely for JBoss3.2
> I really was thinking a lot about the JMX framework
> and the usage we do of it in JBoss. I think the
> classloaders should rely on the UCL framework for a
> way to share the classes across not only the
> implementation of the services but also the
Can you explain this in a bit more detail?
Application meaning a J2EE application, in other words distributed across nodes... so should the UCL framework share classes across nodes? Or is this something else?
> > way to share the classes across not only the
> > implementation of the services but also the
> > applications.
> Can you explain this in a bit more detail?
> Application meaning a J2EE application,
Yes, one of the key things is that any service is seen by any application and vice versa. Very useful for the simple service that ships an EJB and an ejb that uses the service. All through the UCL. If you start introducing your own Classloaders this is no good, you will break the visibility scope. Use UCL as much as you can within your repositories, they are full fledged URLCL and will make you work with the others.
> framework share classes across nodes? Or is this
This is local to one vm
ok, so UCL != URLCL
where's my codebook?
ok, think I got it now,
you're talking about the scoped loader right? That visibility.
I am talking about the UnifiedClassLoader.
I have no problem with the "DefaultRepositoryLoader" if you are using "UnifiedClassLoaders" otherwise we can't deploy the services and have them transparently seen by the applications as well.
org.jboss.system.UnifiedClassLoader, the old scoped stuff without the scope :) by the way is the MLET way of looking up classes by version mandatory? I saw this semantics in your MLEt stuff for the class
> I have no problem with the "DefaultRepositoryLoader"
> if you are using "UnifiedClassLoaders" otherwise we
> can't deploy the services and have them transparently
> seen by the applications as well.
The default loader repository can be configured to use any LoaderRepository implementation. It doesn't use any classloaders itself. You can restrict the classloaders to UCL based loaders in the specific repository implementation.
> stuff without the scope :) by the way is the MLET way
> of looking up classes by version mandatory? I saw
> this semantics in your MLEt stuff for the class
well... hmmm... yup.
what is the semantic of the MLET on the following
Reload of classes from a given URL, (new classes), how is the cycling done. If a class asks for class A and class A has been reloaded, which class do you get.
If class A talks to B using class C, A and B are loaded through different MLets (MLA, MLB) and both A and B contain references to C which they exchange. Imagine both URL contain the class C, which class will prevail? C loaded by the MLA or C loaded by MLB? who resolves the conflict of classes? which one is loaded across the stacks?
Is this behavior deterministic in the spec?
The JMX spec doesn't really define the classloader behaviour in the server at all. The dynamic classloading part of the spec uses its three pages mostly on describing the MLET tag.
> Reload of classes from a given URL, (new classes),
> how is the cycling done. If a class asks for class A
> and class A has been reloaded, which class do you
Depends on the LoaderRepository implementation in this case. A simplistic implementation (BasicLoaderRepository and the RI implementation) is undeterministic, you get which ever classloader is found first in the internal collection when DLR.loadClass() is called.
A different implementation of loader repository can store additional information with the loader, perhaps the version number, and load classes with "latest version first" policy. However, if there's a need for a more specific loading behaviour (I don't know if there is, such as "always load version 1.4 of class A") then the
DLR API needs to be bypassed by registering the LoaderRepository as an MBean and going by the JMX server invoke(). The only control DLR allows for classloading is the loadClassWithout(CL cl) method.
> If class A talks to B using class C, A and B are
> loaded through different MLets (MLA, MLB) and both A
> and B contain references to C which they exchange.
Right, this is the normal case for a ClassCastException and its not addressed by the spec. For this to work the MBean loaders (MLA & MLB) must share their classes in the common "pool", similar to what you implement in ServiceLibraries. This is where the MBean server and the LoaderRepository need to be working together. Registering a classloader MBean with the JMX server will result in a call to LoaderRepository.addClassLoader() which in case of the UCL is done by the classloader itself. For a similar functionality in The JBossMX server this registration should be left to the MBeanServerImpl which passes the UCL to the LoaderRepository which then sets itself as the delegate for the given UCL (so the UCLLoaderRepository here is the equivalent of ServiceLibraries). The UCLLoaderRepository can enforce a specific type of classloader to be registered in the system.
Working with the JBossMX API, this would require an addition of
in the UCL API which sets what is now the 'libraries' reference in UCL. The LoaderRepository API can be modified with an addition of a callback method
ClassLoader createClassLoader(ClassLoader cl)
which allows the LoaderRepository to control the type of classloaders that are registered to it. For example, if the javax.management.MLet URLClassLoader is registered a UCLRepository may return a copy of the URLClassloader
The MBean classloading in javax.management.MLet is done by giving the object name of the classloader explicitly, which in this case would be the object name for an UCL loader and therefore delegated to the UCLRepo (== ServiceLibs).
This requires a small change in the MBeanEntry when classloaders are referenced by object name but should be doable. It might even work..
> Imagine both URL contain the class C, which class
> will prevail? C loaded by the MLA or C loaded by
If the classes are part of the same package version, can't either one be dropped without a problem? If they're different package implementation version, then I think both should prevail. Which one is returned on the loadClass() call depends on the policy of the LoaderRepository ("always load latest version") or if an explicit version of a package is required then that class instance should be loaded.
> which one is loaded across the stacks?
This behavior is determined by the LoaderRepository implementation. As the stack is part of the ModelMBean implementation the classloader used is then the one used to load the ModelMBean (which in UCLRepository case would then be a UCLCL delegating to repository).
> Is this behavior deterministic in the spec?
PS. Writing forum posts into this small text area is somewhat annoying. Is there anyway the Post a Reply page TEXTAREA could be made to adjust to the width of the browser window, or made bigger by default?