The Source for Java Technology Collaboration
User: Password:



Eamonn McManus

Eamonn McManus's Blog

Cascading: It's all done with mirrors

Posted by emcmanus on February 01, 2007 at 08:27 AM | Comments (10)

One of the features planned for version 2.0 of the JMX API is cascading, also known as federation. Here's what it is, and how you can build a simplified form of the same thing without waiting for 2.0.

Update: a subset of the Java DMK product has been released as open source. Daniel Fuchs explains how to use the Cascading API from Open DMK. I would recommend using this in production if you need Cascading.

Cascading

The basic idea behind cascading is that you can "import" MBeans from one MBean Server into another MBean Server. In the picture here, the top MBean Server (labeled Master Agent) imports MBeans from two other MBean Servers (Subagent 1 and Subagent 2).

A mirror MBean forwards everything to another, remote MBean

The different MBean Servers could be in the same Java VM, or more likely they could be in different VMs, possibly on different machines.

By "importing", I mean the Master Agent has a "mirror" for each of the imported MBeans. This mirror shows exactly the same MBean interface as the MBean it reflects. An operation on the mirror is forwarded to the remote MBean.

So for example suppose the middle MBean in Subagent 1 has attributes "Size" and "Capacity" and an operation "reset". Its mirror in the Master Agent will have the same attributes and the same operation. If I get the "Size" attribute from the mirror, it will forward the request to the remote MBean, and return the result it gets back. If I invoke the "reset" operation on the mirror, it will forward that request to the remote MBean, which will do the real "reset" operation.

Getting Size attribute from mirror forwards to remote MBean

The end result is that a client of the Master Agent (such as JConsole) doesn't have to know about the other MBean Servers at all. It can just interact with the mirror MBeans, and the result will be the same as if it had interacted with the corresponding MBeans in the other MBean Servers.

Some of the MBeans in the subagents might themselves be mirrors for "subsubagents", so you could have a multilevel hierarchy. This is where the name "cascading" comes from.

(Cascading has existed for years as part of Sun's Java Dynamic Management Kit product (Java DMK), and you can read about how it works there in the tutorial.)

So what's it for?

There are several cases where cascading is useful.

The most obvious case is where you have a number of different MBean Servers with interesting MBeans and you want to be able to manage them all. You can do this by importing the MBeans into a single MBean Server and attaching a management client like JConsole to this MBean Server.

This is much simpler for the client than having to connect separately to each MBean Server. It might even be that the links between the Master Agent and the Subagents are over a private network that is not accessible to the client, so it couldn't connect directly to the Subagents even if it wanted to.

A second case where cascading could come in handy is if you don't want to expose all of the MBeans in an MBean Server to a particular client. You can create a Master Agent that only imports the subset of MBeans that you do want to expose, and let the client connect to that.

A related case is where you want to give the MBeans different names. There's no requirement that the mirror MBean have the same name as the original MBean in the subagent. You can construct a new MBean model by importing MBeans and giving them different names. Of course, you don't have to import all the MBeans, and you don't have to import them all from the same place. So this is quite a general mechanism.

A simple implementation

Let's look at how we might implement a basic form of cascading. The idea is to have a class MBeanMirrorFactory that allows us to create mirror MBeans. After creating a mirror MBean, we can register it in the Master Agent under whatever name we've chosen.

To show how this works, suppose we want to create an MBean Server that contains all the same MBeans as the Platform MBean Server, but where every MBean's name starts with "mirror/". So the MBean called "java.lang:type=Runtime" in the Platform MBean Server will have a mirror called "mirror/java.lang:type=Runtime" in the new MBean Server. Here's the code to do that using MBeanMirrorFactory:

        MBeanServer platformMBS =
                ManagementFactory.getPlatformMBeanServer();
        
        MBeanServer mirrorMBS =
                MBeanServerFactory.newMBeanServer();
        
        Set<ObjectName> names = platformMBS.queryNames(null, null);
        for (ObjectName name : names) {
            ObjectName mirrorName = new ObjectName("mirror/" + name);
            MBeanMirror mirror =
                    MBeanMirrorFactory.newMBeanMirror(platformMBS, name);
            mirrorMBS.registerMBean(mirror, mirrorName);
        }

As another example, here's how we might set up a configuration like the one in the picture above, except that all MBeans from both subagents are imported. The MBeans from Subagent 1 will be prefixed with "subagent1/" and the ones from Subagent 2 with "subagent2/". So we will have mirror MBeans called "subagent1/java.lang:type=Runtime" and "subagent2/java.lang:type=Runtime", for example.

    	...
        JMXServiceURL url1 =
                new JMXServiceURL("service:jmx:rmi:///jndi/rmi://oneman:8888/jmxrmi");
        JMXServiceURL url2 =
                new JMXServiceURL("service:jmx:rmi:///jndi/rmi://oneman:9999/jmxrmi");

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        importAll(url1, "subagent1/", mbs);
        importAll(url2, "subagent2/", mbs);
    	...

    private static void importAll(
            JMXServiceURL url, String prefix, MBeanServer localMBS)
    throws IOException {
        JMXConnector conn = JMXConnectorFactory.connect(url);
        MBeanServerConnection remoteMBS = conn.getMBeanServerConnection();

        Set<ObjectName> names = remoteMBS.queryNames(null, null);
        for (ObjectName name : names) {
            try {
                ObjectName mirrorName = new ObjectName(prefix + name);
                MBeanMirror mirror =
                        MBeanMirrorFactory.newMBeanMirror(remoteMBS, name);
                localMBS.registerMBean(mirror, mirrorName);
            } catch (Exception e) {
                // log the exception and skip this MBean
            }
        }
    }

The JMXServiceURLs are just examples, of course. (oneman is the anagrammatic name of my workstation.)

If we attach JConsole to the Master Agent here, we'll see something like this:

JConsole attached to master agent shows subagent mirrors

The attributes shown are those of the MBean "subagent1/java.lang:type=ClassLoading" and are the same as we would see if we attached directly to Subagent 1 and looked at its MBean "java.lang:type=ClassLoading".

Mirror MBean implementation

The mirror MBean implementation is actually quite simple. The same class can implement a mirror for any MBean. The secret is that we do not have to know the management interface at compile time. We can discover the interface at run time and implement a Dynamic MBean that forwards every operation on the mirror to the remote MBean.

Here's a first attempt for the implementation class:

// First attempt.  THIS DOES NOT COMPILE.
public class PlainMBeanMirror implements DynamicMBean {
    private final MBeanServerConnection mbsc;
    private final ObjectName objectName;
    
    public PlainMBeanMirror(MBeanServerConnection mbsc, ObjectName objectName) {
        this.mbsc = mbsc;
        this.objectName = objectName;
    }

    public Object getAttribute(String name) {
    	return mbsc.getAttribute(objectName, name);
    }
    
    public void setAttribute(Attribute attr) {
	mbsc.setAttribute(objcetName, attr);
    }
    
    public AttributeList getAttributes(String[] names) {
	return mbsc.getAttributes(objectName, names);
    }

    public AttributeList setAttributes(AttributeList attrs) {
    	return mbsc.setAttributes(objectName, attrs);
    }

    public Object invoke(String opName, Object[] args, String[] sig) {
    	return mbsc.invoke(objectName, opName, args, sig);
    }

    public MBeanInfo getMBeanInfo() {
    	return mbsc.getMBeanInfo(objectName);
    }
}

Each of the six methods of the DynamicMBean is forwarded to the corresponding method in the MBeanServerConnection interface. The MBeanServerConnection methods have an extra ObjectName parameter, which here is the name of the remote MBean.

This is just a little too good to be true, and indeed if we try compiling it we will get errors, because we haven't considered exceptions carefully enough.

Exceptions

If we look at a method in the DynamicMBean interface, say getAttribute, and the corresponding method in the MBeanServerConnection interface, we will see that DynamicMBean.getAttribute throws AttributeNotFoundException, MBeanException, and ReflectionException. MBeanServerConnection.getAttribute throws the same exceptions, but also InstanceNotFoundException and IOException. It is the same story for the other five DynamicMBean methods.

This makes sense. If we invoke getAttribute on a mirror MBean, it will invoke getAttribute on the remote MBean. If that gets AttributeNotFoundException, then the mirror MBean can simply throw the same exception. But there are two other ways we could get an exception. One is if the remote MBean does not exist. The other is if we get a communication failure, for example because the remote machine is not reachable.

So we need to rewrite PlainMirrorMBean.getAttribute to take these extra exceptions into account. Happily, the exception MBeanException exists precisely to wrap these general sorts of exception. So here's what the new version looks like:

    public Object getAttribute(String name)
    throws AttributeNotFoundException, MBeanException, ReflectionException {
        try {
            return mbsc.getAttribute(objectName, name);
        } catch (IOException e) {
            throw new MBeanException(e);
        } catch (InstanceNotFoundException e) {
            throw new MBeanException(e);
        }
    }

We put in the throws clause the exceptions declared by DynamicMBean.getAttribute. And we catch the two other exceptions from MBeanServerConnection.getAttribute and wrap them in MBeanException. We can handle setAttribute and invoke in the same way.

But that still leaves three other DynamicMBean methods that don't throw MBeanException. How do we handle those?

For getAttributes and setAttributes, the answer is simple. These methods are supposed to return an AttributeList containing all the attributes that were successfully got or set. If the attempt to get any given attribute produces an error, then that attribute is simply omitted from the returned list. If you want to know what the error was, you have to call getAttribute or setAttribute (rather than get/setAttributes) with just the attribute in question and see what exception it produces.

So if we get an IOException or an InstanceNotFoundException when forwarding the getAttributes or setAttributes call to the remote MBean, we can simply consider that every attribute produced an error, and return an empty AttributeList.

Here's what the rewritten getAttributes looks like:

     public AttributeList getAttributes(String[] names) {
        try {
            return mbsc.getAttributes(objectName, names);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            return new AttributeList();
        }
    }

Since DynamicMBean.getAttributes doesn't declare any checked exceptions, we catch and rethrow RuntimeException, then catch Exception, which is then all checked exceptions. This is easier than catching the three checked exceptions that MBeanServerConnection.getAttributes declares.

We can rewrite setAttributes the same way. So that just leaves one method from DynamicMBean, getMBeanInfo.

getMBeanInfo()

DynamicMBean.getMBeanInfo does not declare any checked exceptions, so we can't wrap an IOException or InstanceNotFoundException in an MBeanException as we did for getAttribute and co. We could try returning a special "empty" MBeanInfo, but that is hacky. We could also wrap the exception in a RuntimeException, which is less hacky but still not very satisfactory. No RuntimeExceptions are mentioned in the specification of MBeanServerConnection.getMBeanInfo so callers won't necessarily be prepared to deal with them.

I think the best solution is to get the MBeanInfo once when the mirror is created and then simply return this value forever after from the getMBeanInfo() method. This has a number of advantages.

  • If the remote MBean is nonexistent or inaccessible, you might as well find out at once when you try to create the mirror, rather than waiting until the first time you use it.
  • The getMBeanInfo() method will always be called at least once anyway, when the MBean is registered. This is because MBeanServer.registerMBean returns an ObjectInstance, which is an ObjectName plus a class name. The class name is the value of MBeanInfo.getClassName() for the MBean.
  • If the Java VM where the mirror is registered is running with a SecurityManager then every operation on the mirror MBean will need MBeanInfo.getClassName() in order to construct the MBeanPermission that will be checked. If we don't keep a copy of the MBeanInfo within the mirror, then every MBean operation will require two round trips to the remote MBean, one to get the MBeanInfo, and one to do the actual operation.

The principal disadvantage of this solution is that the MBeanInfo of the remote MBean could change, and the mirror will never show that. It is rare to have MBeans where the MBeanInfo changes, and if you do then you can always override PlainMBeanMirror.getMBeanInfo() to fetch the remote MBeanInfo when appropriate.

So here's the new constructor that caches the MBeanInfo, and the new, trivial getMBeanInfo() method that returns it:

public class PlainMBeanMirror implements DynamicMBean {
    private final MBeanServerConnection mbsc;
    private final ObjectName objectName;
    private final MBeanInfo mbeanInfo;

    public PlainMBeanMirror(MBeanServerConnection mbsc, ObjectName objectName)
    throws IOException, InstanceNotFoundException, IntrospectionException {
        this.mbsc = mbsc;
        this.objectName = objectName;
        try {
            this.mbeanInfo = mbsc.getMBeanInfo(objectName);
        } catch (ReflectionException e) {
            // Callers cannot possibly care about the difference between
            // IntrospectionException and ReflectionException
            IntrospectionException ie = new IntrospectionException(e.getMessage());
            ie.initCause(e);
            throw ie;
        }
    }

    public MBeanInfo getMBeanInfo() {
        return mbeanInfo;
    }

    ...
}

Notifications

Another thing we'd like to be able to do with a mirror MBean is receive notifications that were sent by the original MBean. That is, if we call MBeanServerConnection.addNotificationListener on the mirror MBean, we'd like our listener to receive the same notifications as if we had called addNotificationListener on the remote MBean.

We can do this just by implementing NotificationEmitter (or its parent NotificationBroadcaster) and forwarding its methods in the same way as we did for the methods in DynamicMBean. However, it is better not to implement NotificationEmitter if the MBean does not in fact emit notifications. A client should be able to tell whether addNotificationListener is allowed using isInstanceOf(mirrorName, NotificationBroadcaster.class.getName()). In other words, we should have one sort of mirror for MBeans that are NotificationBroadcasters and another sort for MBeans that are not.

The obvious way to achieve this is to have a subclass of PlainMBeanMirror, say NotifyingMBeanMirror, that implements NotificationEmitter, in the same way as StandardEmitterMBean subclasses StandardMBean in Java SE 6. But the drawback of that is that if we subclass PlainMBeanMirror for another reason, for example to override getMBeanInfo as we saw above, then we will usually need to subclass NotifyingMBeanMirror as well and duplicate the same code in the two subclasses.

An alternative that avoids this problem is to use delegation instead of subclassing. The idea is that a NotifyingMBeanMirror wraps a PlainMBeanMirror and delegates the methods of DynamicMBean to it.

For this to work cleanly, we define an interface that will be implemented by both PlainMBeanMirror and NotifyingMBeanMirror.

public interface MBeanMirror extends DynamicMBean {
    public MBeanServerConnection getMBeanServerConnection();
    public ObjectName getRemoteObjectName();
}

The methods in this interface are useful for code that has created a mirror to register it in the MBean Server. They are also useful to NotifyingMBeanMirror because it can use the interface for its delegation rather than hardwiring the concrete class PlainMBeanMirror.

You might also have noticed earlier that MBeanMirrorFactory.newMBeanMirror returns an MBeanMirror. The idea is that this method returns a NotifyingMBeanMirror if the remote MBean is a NotificationEmitter, and otherwise a PlainMBeanMirror:

public class MBeanMirrorFactory {
    private MBeanMirrorFactory() {} // there are no instances of this class

    public static MBeanMirror newMBeanMirror(
            MBeanServerConnection mbsc,
            ObjectName objectName)
    throws IOException, InstanceNotFoundException, IntrospectionException {
        MBeanMirror mirror = new PlainMBeanMirror(mbsc, objectName);
        if (mbsc.isInstanceOf(objectName, NotificationBroadcaster.class.getName()))
            mirror = new NotifyingMBeanMirror(mirror);
        return mirror;
    }
}

The code of NotifyingMBeanMirror is straightforward but a bit tedious. For the addNotificationListener and removeNotificationListener methods from NotificationEmitter, we again have a problem with exceptions like IOException and InstanceNotFoundException, and here we don't have a much better solution than wrapping them in a RuntimeException. (Daniel Fuchs has suggested using UndeclaredThrowableException here.)

Here's the outline of NotifyingMBeanMirror:

public class NotifyingMBeanMirror implements MBeanMirror, NotificationEmitter {
    private final MBeanMirror mirror;

    public NotifyingMBeanMirror(MBeanMirror mirror) {
        this.mirror = mirror;
    }

    public Object getAttribute(String name)
    throws AttributeNotFoundException, MBeanException, ReflectionException {
        return mirror.getAttribute(name);
    }

    ...same for the other five methods from DynamicMBean...

    public void addNotificationListener(
            NotificationListener listener,
            NotificationFilter filter,
            Object handback) {
        try {
            mirror.getMBeanServerConnection().addNotificationListener(
                    mirror.getRemoteObjectName(), listener, filter, handback);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    ...similar for the other three methods from NotificationEmitter...
}

Further work

One thing that the Cascading Service from Java DMK does in addition to mirroring is to track the creation and deletion of remote MBeans. If you import "java.lang:*" from Subagent 1, say, and a new MBean appears in Subagent 1 called "java.lang:type=New", then a new mirror will appear automatically in the Master Agent. Conversely, if an imported MBean disappears from the subagent then its mirror automatically disappears too. This works by using a listener on the MBeanServerDelegate to learn of remote creations and deletions.

Another interesting question is whether ObjectNames should sometimes be rewritten. If I subscribe to notifications from "subagent1/java.lang:type=Runtime", what will the source of the notifications be? Using the design above, it will be "java.lang:type=Runtime", which might be unexpected. The Cascading Service from Java DMK would rewrite the source to be "subagent1/java.lang:type=Runtime". This discussion can go much further if we think about whether ObjectName attributes and parameters should also be rewritten.

The version of Cascading in version 2.0 of the JMX API will probably be based on Virtual MBeans, and the details will look quite different from what I've described here. But it will solve the same problems.

I haven't talked at all about security, not because it is unimportant but because there's too much to say. Another day perhaps. The basic question is, how does the Master Agent connect securely to each Subagent? And is there a way to have different access to the Subagent MBeans for different users that might be connected to the Master Agent?

The source code

The source code for the classes I've described above is in mirrormbean.zip, along with what may be the most twisted unit test you have ever seen.


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

  • Hi

    I have a question regarding the implementation of queryNames and getMBeanCount methods in the MASTER AGENT.
    Would the MASTER AGENT need to call the SUBAGENTS - possible running on a remote JVM in order to perform these methods.
    I guess not - that would be a big advantage of mirrors.

    Best Regards,
    Enno

    Posted by: ennofolkerts on March 09, 2007 at 05:09 AM

  • Enno,

    As you say, using mirrors means the query is answered entirely on the master agent. This does mean that the master agent's view of the current set of MBeans can be out of date with respect to the real contents of the subagents. You might need to poll the subagents periodically if MBeans can come and go to make their mirrors come and go too. Or you could remotely subscribe to the MBeanServerDelegate in each subagent to get informed when MBeans come and go.

    The Cascading solution we are planning for version 2.0 of the JMX API does not use mirrors, and queries will be forwarded to the subagent. But we also introduce a hierarchical naming scheme, similar to filesystem directories, so it will always be obvious when this might happen.

    Posted by: emcmanus on March 09, 2007 at 05:55 AM

  • Eamonn, many thanks for the quick reply. You hit exactly, what I was curius about. Do you know anyone planning to implement mirrors? Why do you rather go for the cascading solution? I guess, it is less dangerous.
    Why do I ask all this? I know of two Java EE 5 implementations, where queryNames produces a lot of cluster messages. These implementations decide about remote node search via a special keyfield in the ObjectName. When the old ( = 1.5) version of wildcard machanism is used, it can be difficult, not the search the whole cluster with * in the ObjectName. Maybe, using the new ( =1.6) wildcard mechanism is all I really need...

    Posted by: ennofolkerts on March 12, 2007 at 02:09 AM

  • Thanks for the very useful article.
    I implemented the classes in you example (MBeanMirrorFactory, MBeanMirror, PlainMBeanMirror and NotifyingMBeanMirror).
    I register a simple MBean to a remote server using ConnectorServerFactoryBean.

    In my client, I used the importAll method to get all the MBeans registered on the remote MBean server and mirror/register them to my client(Master) MBean server.
    In the client I attach to the HTTP Adaptor to view my beans.
    I check in my client code to see if the given bean is registered on the remote MBean server, and it is.
    The problem is when I am running the following code:

    Set<ObjectName> names = remoteMBS.queryNames(null, null);
    for (ObjectName name : names) {
    try {
    ObjectName mirrorName = new ObjectName(prefix + name);

    MBeanMirror mirror =
    MBeanMirrorFactory.newMBeanMirror(remoteMBS, name);
    );
    localMBS.registerMBean(mirror, mirrorName);

    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    when I am looping through the ObjectNames returned by the remoteMBS.queryNames, I see my MBean is returned. But when the code attempts to create the mirror I get the following exception:


    javax.management.NotCompliantMBeanException: The MBeanInfo returned is null
    javax.management.NotCompliantMBeanException: The MBeanInfo returned is null
    at com.sun.jmx.mbeanserver.BaseMetaDataImpl.getMBeanClassName(BaseMetaDataImpl.java:186)
    at com.sun.jmx.mbeanserver.MetaDataImpl.getMBeanClassName(MetaDataImpl.java:185)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:347)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:515)
    at com.interface21.spring.jmx.basic.ClientDemo.importAll(ClientDemo.java:53)
    at com.interface21.spring.jmx.basic.ClientDemo.main(ClientDemo.java:125)


    Any help would be greatly appreciated.

    Posted by: spoulos on July 19, 2007 at 03:29 PM

  • spoulos, when you say you "implemented the classes" do you mean you copied the code into your own classes? If so could you try using the source code in the zip I posted instead?

    The exception you are seeing indicates that the MBeanMirror is returning null from its getMBeanInfo() method. The only way I can see that that would happen is if the call to mbsc.getMBeanInfo in the PlainMBeanMirror constructor returned null, which would indicate a bug in the remote MBean or in the connector. You could try adding a check for non-null immediately after the assignment to mbeanInfo in the PlainMBeanMirror constructor.

    Posted by: emcmanus on July 20, 2007 at 02:38 AM

  • Eamon,
    Thanks so much for the information and code samples regarding cascading. I need to do exactly this. I implemented the code samples you posted (PlainMBeanMirror, MBeanMirror, MBeanMirrorFactory and NotifyingMBeanMirror) and used them in my client. However, I am having a problem in my client when I try to create the mirror via:MBeanMirror mirror = MBeanMirrorFactory.newMBeanMirror(remoteMBS, name);
    I am getting the error: javax.management.NotCompliantMBeanException: The MBeanInfo returned is null.
    I successfully register my bean (simple MBean - POJO) on my server. I do this remotly using SPRING'S ConnectorServerFactoryBean, and MBeanExporter. When I connect to the remote server in the client, I am using SPRING'S MBeanServerConnectionFactoryBean, and MBeanProxyFactoryBean.In my client, I check to see the bean is registered on the remote server, and it is.
    When the client loops through the MBeans on the remote server, my bean shows up. Set names = remoteMBS.queryNames(null, null); It is the mirror creation I mentioned above that is the problem.
    Do my remote beans need to be dynamic?

    Thanks very much!
    Sue Poulos

    Posted by: spoulos on July 20, 2007 at 07:17 AM

  • Eamon, Thanks very much! Sorry for the duplicate comment. I tried using the code in your zip file, but it was pretty much what I had, and I am still getting the same error when trying to create a mirror. Does my bean on the remote server need to be dynamic? I am using SPRING's ConnectorServerFactoryBean along with SPRING'S MBeanExporter to register the bean on the server using the rmi connector. On the client I am accessing the bean with SPRING'S MBeanServerConnectionFactoryBean and the MBeanProxyFactoryBean.

    Thanks again for all your help and the super fast response.

    Posted by: spoulos on July 20, 2007 at 07:40 AM

  • Eamonn,
    I got the model you presented working beautifully. Thanks again.
    However, now I want to be able to have my client dynamically discover MBean servers on a given port.
    Currently, I created several servers which register MBeans (using JSR-160 rmi/jndi) to different MBean servers on different boxes.
    I then use cascading on my client to connect to the remote MBean servers and register the Mirror MBeans to my local MBean server.
    In doing this, I hard code the location of my remote MBean server connections (JMXServiceURL url2 = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://dappa4:8999/myconnector");
    Instead of hard coding the connectors, is there any way to only use a port and dynamically look up all the running connectors on that port and attach to them?
    Is this possible?
    On my server sides, I am using springs ConnectorServerFactoryBean (jndi/rmi) to create a JSR-160 JMXConnectorServer and register my beans as MBeans.
    On the client side, I use your importAll method and I pass in the url which I registered using Spring's MBeanServerConnectionFactoryBean.

    Any help or direction would be greatly appreciated.

    Thanks much
    Sue.

    Posted by: spoulos on August 09, 2007 at 02:50 PM

  • I want to make cascading froma Jboss JMX application server, so how do I discover and register remote MBeans like you do in the code:

    Set<ObjectName> names = remoteMBS.queryNames(null, null);
    for (ObjectName name : names) {
    try {
    ObjectName mirrorName = new ObjectName(prefix + name);
    MBeanMirror mirror =
    MBeanMirrorFactory.newMBeanMirror(remoteMBS, name);
    localMBS.registerMBean(mirror, mirrorName);
    } catch (Exception e) {

    Posted by: sbonino on December 06, 2007 at 05:45 AM

  • sbonino, if your JBoss app server is exporting a JMX Connector Server (as specified by the JMX Remote API, JSR 160), then you just need to find the address of that server and give it to JMXConnectorFactory.connect as shown. If it is not exporting a standard JMX Connector Server, then it is probably possible to get an MBeanServerConnection object through some JBoss-specific API. I would suggest you ask your question on a JBoss forum.

    Posted by: emcmanus on December 07, 2007 at 08:01 AM



Only logged in users may post comments. Login Here.


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