Java Dynamic Management Kit 5.1 Tutorial

14.2 Cascaded MBeans in the Master Agent

Once the the cascading service has mounted a source MBean server in the target MBean server, you can interact directly through the target MBean server with the target MBeans representing the subagent's MBeans. You can access and manage these MBeans as if you were connected to the subagent and accessing or managing the original MBeans. The target MBeans that you interact with are in fact CascadingProxy MBean objects registered in the master agent's target MBean server with the same object name as the source MBean, but with a domain that is prefixed by the target path used in the mount operation.

All management operations that you can perform on the original MBean can be performed identically through the target MBeanServer, using that target's object name. You can modify attributes, invoke operations and add or remove listeners, all with exactly the same result as if the manager were connected to the subagent when performing the action.

The behavior of a target CascadingProxy MBean is to transmit the action transparently to the subagent's MBean and return with an answer or result. The actual computation is performed by the original MBean running in its own source MBean server.

In Example 14–4, there is a timer MBean that was created in the subagent. Once the subagent has been mounted in the target MBean server, the timer is operated through its local target CascadingProxy MBean. It is not possible to have the direct reference to a source MBean, but it is possible to obtain a local proxy using the MBeanServerInvocationHandler class, as if it were a local MBean registered in the target MBean server. The fact that the operations are actually routed to a subagent through a JMXConnector remains hidden.


Example 14–4 Managing Cascaded MBeans

    private void doCascadingOperations() {

        echo("\nPress Enter to continue...\n");
        waitForEnterPressed();
        printline();
        try {
             if (! cascadingService.isMounted(mountPoints[0])) {
		            echo(mountPoints[0] + ": \n\t" + "not mounted! ");
		            echo("Cannot do cascading operations.");
		            return;
	            }
            
             ObjectName timerName =
                new ObjectName("subagents/agent1/ExportDomain:type=Timer");
	             echo(">>> Get Timer MBean \""+timerName+"\"");
             TimerMBean timer = (TimerMBean) MBeanServerInvocationHandler.
               newProxyInstance(server, timerName, TimerMBean.class, true);

            echo("\n>>> Ask the Timer MBean to send a " +
                 "Timer Notification every 3 seconds");
            Date currentDate = new Date();
                  
            timer.addNotification("Timer","Message",null,
                                  new Date(currentDate.getTime() + 
                                  2),3000);

            timer.start();

            echo("\n>>> Add listener to the Timer MBean");
            server.addNotificationListener(timerName, this, null, null);
            echo("\tListener added successfully");
            echo("\nPress Enter to remove the listener from the " +
		             "Timer MBean...");
            waitForEnterPressed();

	    	      if (cascadingService.isMounted(mountPoints[0])) {
		             try {
                    server.removeNotificationListener(timerName, 
                    this);
		             } catch (Exception x) {
                    echo("Unexpected exception while unregistering 
                         listener:");
		                 echo("\tError is: " + x);
		             }
	            } else {
                 echo(mountPoints[0] + ": \n\t" + "already 
                      unmounted! ");
	            }

	        } catch (Exception e) {

            e.printStackTrace();
            System.exit(1);
        }
    }

Example 14–4 obtains a TimerMBean proxy for the Timer MBean from the subagent #1 ExportedDomain, and then performs operations on it. In particular, it registers for timer notifications and starts the timer.

To the managing application, the target MBean in the master agent target MBean server is the MBean. Unregistering a cascaded MBean in the master agent will not unregister the cascaded MBean in the subagent, but will only unregister the CascadingProxy from the target MBean server. You should not attempt to unregister MBeans mounted from a source MBean server through the target MBean server. If you want to create or unregister MBeans in a subagent, you should not do so through the CascadingService, but should use a JMXConnector directly connected to the subagent.

The cascading is almost totally transparent. A manager has no direct way of knowing whether an object is a cascaded object or not. It can attempt to guess the topology of the cascading hierarchy by examining the domain path of the object names, provided that the subagents have been mounted using a meaningful and coherent target path, but the underlying connectivity is completely transparent. The managing application can however be informed of failed or closed mount points by registering for notifications with the CascadingServiceMBean.

Likewise, some operations might fail due to the fact that the CascadingProxy object registered in the target MBean server is not the real source MBean. For example, unregistering the CascadingProxy will not cause the original source MBean to be unregistered. The CascadingProxy might reappear later if an external event makes the CascadingService update its view of the subagents. Similarly, trying to call addNotificationListener(ObjectName,ObjectName,...) with the object name of a target CascadingProxy as listener (namely the second parameter) will fail, because this operation cannot be routed to the source MBean.

14.2.1 Class of a Cascaded MBean

Proxy MBeans registered in the target MBeanServers when mounting source MBean servers are implemented as instances of the CascadingProxy class. The CascadingProxy MBean is locally registered in the target MBean server, and has the same MBeanInfo as its source MBean. In particular, if the source MBean is a model MBean, the MBeanInfo exposed by its CascadingProxy is ModelMBeanInfo. The exposed MBean information also contains the class name of the original MBean, and not the class name of the CascadingProxy. Exposing this borrowed MBeanInfo guarantees that the cascading service is as transparent as possible.

The symmetry of the Java dynamic management architecture means that this cascading mechanism is scalable to any number of levels. The cascaded object of a cascaded object is again an instance of the CascadingProxy class, and it borrows the same MBeanInfo. Any operation on the top target object is propagated to its source subagent, where the intermediate cascaded object will send it to its own source subagent, and so forth. The cost of cascading is the cost of accessing the subagents. The depth of your cascading hierarchy should be adapted to your management solution.

Because the cascading service MBean instantiates and controls all cascaded MBeans, the CascadingProxy class should never be instantiated through a management operation, nor by the code of the agent application. It is described here only to provide a better understanding of the internal behavior of the cascading service.

14.2.2 Cascading Issues

In this section, we explain some of the design issues that are determined by the implementation of the cascading service.

14.2.2.1 Dynamic Cascading

When an MBean is unregistered from the subagent, the cascading service automatically removes its corresponding target CascadingProxy MBean from the master agent's target MBean server. When a new MBean is registered in the subagent's source MBean server, the cascading service registers a new CascadingProxy mirroring this source MBean with the master agent's MBean server. Note that if an ObjectName pattern was provided when performing the mount operation, only those source MBeans whose source ObjectName satisfy that ObjectName pattern are considered.

Both these mechanisms scale to cascading hierarchies. Adding or removing an MBean in the subagent will trigger a notification that any cascading service connected to the subagent will receive. This will start a chain reaction up to the top of the hierarchy. Removing an MBean from the middle of a hierarchy also triggers a similar reaction up to the top target MBean, which is finally removed. However, as explained in the previous section, corresponding source MBeans that are lower in the hierarchy will not be affected. The cascading service reflects the content of a source MBean server into a target MBean server, but it cannot be used to create or remove MBeans in the source MBean server. Calls to createMBean, registerMBean, and unregisterMBean only affect the local target MBean server.

14.2.2.2 MBean Patterns and Filtering

When the cascading service MBean is instantiated, you can pass it an object name pattern. This object name pattern is applied to the list of MBeans in the subagent's source MBean server to determine those MBeans that are to be cascaded into the master agent's target MBean server. The filtering is activated for the life of the of the mount operation, namely, until unmount is called for that mount point. Care must be taken when using the ObjectName pattern, so as not to implement cascading hierarchies that are not analogous to File System mount operations.

The object name pattern is used to filter any new MBean that is registered in the source MBean server. If the new MBean meets the filter criteria, it will become visible and be cascaded into the target MBean server.

14.2.2.3 Using Target Paths

Although the API also allows you to implement different cascading schemes, your applications should only implement those schemes that can be compared to a regular File System mount, as follows.

The present implementation does not enforce those rules, but applications that are concerned with naming consistency and coherency should make sure to respect them.