Java Dynamic Management Kit 5.0 Tutorial

Generic Proxies

Because dynamic MBeans only expose their management at runtime, it is impossible to generate a specific proxy object for them. Instead, we use the GenericProxy object which can be bound to any dynamic MBean, and whose generic methods take the name of the attribute or operation being accessed. Therefore, to access a dynamic MBean through generic proxy you call exactly the same methods as those of the DynamicMBean interface.

Just as the MBean server's generic methods can access both standard and dynamic MBeans, generic proxies can also be bound to standard MBeans. You lose the specificity and simplicity of a standard proxy, but a generic proxy is always available in any Java dynamic management application, and it never needs regenerating.

The management application in this example shows how generic proxies can be used to access both standard and dynamic MBeans. The application contains the following subroutine that takes the class name of an MBean, creates that MBean in the agent, and instantiates a generic proxy to access the MBean.

In fact, the subroutine instantiates two generic proxies for the MBean, one using the GenericProxy class constructor that also binds the proxy, the other bound in a second, separate call to its setServer method. This demonstrates that it is possible to have two distinct proxy instances coexisting simultaneously for the same MBean.


Example 11–5 Accessing Standard and Dynamic MBeans Using Generic Proxies

private void doGenericProxyExample( String mbeanName ) {

    try {
        // build the MBean ObjectName instance
        ObjectName mbeanObjectName = null;
        String domain = connectorClient.getDefaultDomain();
        mbeanObjectName = new ObjectName( domain +
                                          ":type=" + mbeanName);

        // create the MBean in the MBeanServer of the agent
        String mbeanClassName = mbeanName;
        ObjectInstance mbeanObjectInstance =
            connectorClient.createMBean( mbeanClassName, mbeanObjectName );

        // create and bind a generic proxy instance for the MBean
        Proxy proxy = new GenericProxy(
                              mbeanObjectInstance, connectorClient );

        echo("\tPROXY CLASS NAME  = " +
              proxy.getClass().getName());
        echo("\tMBEAN OBJECT NAME = " +
              proxy.getMBeanObjectInstance().getObjectName());
        echo("\tCONNECTOR CLIENT  = " +
              proxy.getServer().getClass().getName());

        // An alternate way is to first instantiate the generic proxy,
        // and then to bind it to the connector client:
        Proxy proxy2 = new GenericProxy( mbeanObjectInstance );
        proxy2.setServer( connectorClient );

        echo("\tPROXY CLASS NAME  = " +
              proxy2.getClass().getName());
        echo("\tMBEAN OBJECT NAME = " +
              proxy2.getMBeanObjectInstance().getObjectName());
        echo("\tCONNECTOR CLIENT  = " +
              proxy2.getServer().getClass().getName());

        // we no longer need proxy2, so we unbind it
        proxy2.setServer(null);

        [...] // Accessing the MBean through its generic proxy (see below)

        // When done with the MBean, we unbind the proxy
        // and unregister the MBean
        //
        proxy.setServer(null);
        connectorClient.unregisterMBean( mbeanObjectName );

    } catch (Exception e) {
        echo("\t!!! Error instantiating or binding proxy for " + 
              mbeanName );
        e.printStackTrace();
    }
}

The standard and dynamic MBean classes used in this example have exactly the same management interface, and therefore, we can use the same code to access both of them. The manager application does this by calling the above subroutine twice, once with the class name of the standard MBean, once with that of the dynamic MBean:

manager.doGenericProxyExample("SimpleStandard");
manager.doGenericProxyExample("SimpleDynamic");

Because the two MBeans have the same behavior, they produce the same results when accessed through their proxy. The only difference is that the dynamic MBean can expose a description of its management interface in its MBeanInfo object. As expected, accessing a standard MBean through a generic proxy also produces the same result as when it is accessed through a standard proxy (compare the following with Example 11–4).


Example 11–6 Accessing an MBean Through its Generic Proxy

try {

    // cast Proxy to GenericProxy
    GenericProxy genericProxy = (GenericProxy) proxy;

    // Get the MBean's metadata through the proxy
    MBeanInfo info = genericProxy.getMBeanInfo();

    // display content of the MBeanInfo object
    echo("\nCLASSNAME: \t"+ info.getClassName() );
    echo("\nDESCRIPTION: \t"+ info.getDescription() );
    [...] // extract all attribute and operation info

    // Change the "State" attribute
    Attribute stateAttr = new Attribute( "State", "new state from client");
    genericProxy.setAttribute( stateAttr );

    // Get and display the new attribute values
    String state =
        (String) genericProxy.getAttribute("State");
    Integer nbChanges =
        (Integer) genericProxy.getAttribute("NbChanges");
    echo("\tState     = \"" + state + "\""); 
    echo("\tNbChanges = " + nbChanges); 

    // Invoke the "reset" operation
    Object[] params = new Object[0];
    String[] signature = new String[0];
    genericProxy.invoke("reset", params, signature );

} catch (Exception e) {
    echo("\t!!! Error accessing proxy for " + 
          proxy.getMBeanObjectInstance().getObjectName() );
    e.printStackTrace();
}

Example 11–6 shows how the generic methods are called with the names of attributes and operations, and how required parameters can be constructed.


Running the Generic Proxy Example

The ClientGenericProxy application, also located in the examplesDir/SimpleClients directory, demonstrates the use of generic proxies.

To Run the Generic Proxy Example
  1. Compile all files in this directory with the javac command, if you have not done so already. For example, on the Solaris platform with the Korn shell, type:


    $ cd examplesDir/SimpleClients/
    $ javac -classpath classpath *.java
    

    Because generic proxies do not need to be generated, this example does not need the proxygen tool. The GenericProxy class is available in the usual classpath for the product's runtime libraries.

  2. If it is not already running on your host, start the base agent in a terminal window with the following command:


    $ java -classpath classpath BaseAgent
    

    The agent creates the RMI connector server to which the client application will establish a connection, and then it waits for management operations.

  3. Wait for the agent to be completely initialized, then start the management application in another window on the same host:


    $ java -classpath classpath ClientGenericProxy
    
  4. Press Enter in the manager window to step through the example.

    As seen in the code examples, the client application instantiates generic proxy objects to access both a standard and dynamic MBean that it creates in the base agent. The only difference between the two is the user-provided information available in the dynamic MBean's metadata.

  5. Press Enter in both windows to exit the base agent and manager applications.