Java Dynamic Management Kit 5.0 Tutorial

Connector Clients

The manager application interacts with a connector client to access an agent through an established connection. Through its implementation of the RemoteMBeanServer interface, a connector client provides methods to handle the connection and access the agent. This interface specifies nearly all of the same methods as the MBeanServer interface, meaning that an agent is fully manageable from a remote application.

Through the connector, the management application sends management requests to the MBeans located in a remote agent. Components of the management application access remote MBeans by calling the methods of the connector client for getting and setting attributes and calling operations on the MBeans. The connector client then returns the result, providing a complete abstraction of the communication layer.

By default, a connector client uses the default host name, InetAddress.getLocalHost().getHostName()

Multihome Interfaces

The multihome interfaces introduced in Java DMK 5.0 enable you to select the interfaces for the different network protocols used by connector clients.

An HTTP(S) client enables you to select a local interface to receive notifications from a server. This user-specific local interface address is sent to a server and is then used by that server to push notifications. The interface address can be specified as either an IPv4 or an IPv6 address, or as a host name.

An RMI connector client does not need to specify a local interface, except when a Java DMK 5.0 client needs to connect to a server from Java DMK 4.2.

RemoteMBeanServer Interface

All connector clients implement the RemoteMBeanServer interface to expose the methods needed to access and manage the MBeans in a remote agent. This interface allows all management operations that would be possible directly in the agent application. In fact, the methods of the connector client for accessing MBeans remotely have exactly the same name and signature as their equivalent methods in the MBeanServer interface.

Table 10–1 lists the methods that are defined identically in both the MBeanServer and the RemoteMBeanServer interfaces:

Table 10–1 Shared Methods

Type 

Signature 

* void

addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, java.lang.Object handback)

ObjectInstance

createMBean(*) – All four overloaded forms of this method

* java.lang.Object

getAttribute(ObjectName name, java.lang.String attribute)

* AttributeList

getAttributes(ObjectName name, java.lang.String[] attributes)

java.lang.String

getDefaultDomain()

java.lang.Integer

getMBeanCount()

* MBeanInfo

getMBeanInfo(ObjectName name)

ObjectInstance

getObjectInstance(ObjectName name)

* java.lang.Object

invoke(ObjectName name, java.lang.String operationName, java.lang.Object[] params, java.lang.String[] signature)

boolean

isInstanceOf(ObjectName name, java.lang.String className)

boolean

isRegistered(ObjectName name)

java.util.Set

queryMBeans(ObjectName name, QueryExp query)

java.util.Set

queryNames(ObjectName name, QueryExp query)

* void

removeNotificationListener(ObjectName name, NotificationListener listener)

* void

setAttribute(ObjectName name, Attribute attribute)

* AttributeList

setAttributes(ObjectName name, AttributeList attributes)

* void

unregisterMBean(ObjectName name)

* These methods are defined in the ProxyHandler interface (see Local and Remote Proxies).

Components of a management application that rely solely on this common subset of methods can be instantiated in either the agent or the manager application. Such components are location-independent and can be reused either locally or remotely as management solutions evolve. This symmetry also allows the design of advanced management architectures where functionality can be deployed either in the agent or in the manager, depending on runtime conditions.

The other, unshared methods of the RemoteMBeanServer interface are used to establish and monitor the connection. Establishing a Connection shows how to establish a connection and access MBeans directly through the connector client.Heartbeat Mechanism, shows how to monitor a connection and detect when it is lost.

Establishing a Connection

The target of a connection is identified by a protocol-specific implementation of the ConnectorAddress interface. This object contains all the information that a connector client needs to establish a connection with the target agent. All address objects specify a host name and port number. An RMI address adds the required service name, and HTTP-based addresses have an optional authentication field (see Password-Based Authentication). In addition, the ConnectorType string identifies the protocol without needing to introspect the address object.

In our example, the target of the connection is an active RMI connector server identified by an RmiConnectorAddress object. We use the default constructor to instantiate a default address object, but otherwise, these parameters can be specified in a constructor or through setter methods. The default values of the information contained in the RmiConnectorAddress object are the following:

The RmiConnectorAddress object is used as the parameter to the connect method of the RmiConnectorClient instance. This method tries to establish the connection and throws an exception if there is a communication or addressing error. Otherwise, when the connect method returns, the connector client is ready to perform management operations on the designated agent.


Example 10–3 Establishing a Connection

echo("\t>> Instantiate the RMI connector client...");
connectorClient = new RmiConnectorClient();

echo("\t>> Instantiate a default RmiConnectorAddress object...");
RmiConnectorAddress address = new RmiConnectorAddress();

// display the default values
echo("\t\tTYPE\t= "   + address.getConnectorType());
echo("\t\tPORT\t= "   + address.getPort());
echo("\t\tHOST\t= "   + address.getHost());
echo("\t\tSERVER\t= " + address.getName());
echo("\t<< done <<");

echo("\t>> Connect the RMI connector client to the agent...");
try {
     connectorClient.connect( address );

} catch(Exception e) {
     echo("\t!!! RMI connector client could not connect to the agent !!!");
     e.printStackTrace();
     System.exit(1);
}

Managing MBeans Remotely

Once the connection to an agent is established, the management application can access that agent's MBeans through the RemoteMBeanServer interface of the connector client. Invoking these methods has exactly the same effect as calling the equivalent methods directly on the MBean server instance.

It is possible to restrict access to certain methods of the MBean server when they are called through the connector client, but this is performed by a security mechanism in the connector server. See Context Checking for more details.

Creating and Unregistering MBeans in the Agent

We use the createMBean method to instantiate and register an object from its class name. This class must already be available in the agent application's classpath, or you can use the createMBean method that takes the name of a class loader (see M-Let Loading From a Manager for more details).


Example 10–4 Creating and Unregistering an MBean Remotely

private void doWithoutProxyExample(String mbeanName) {

    try {

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

        // create and register an MBean in the MBeanServer of the agent
        //
        echo("\nCurrent MBean count in the agent = "+
             connectorClient.getMBeanCount());
        echo("\n>>> CREATE the " + mbeanName +
             " MBean in the MBeanServer of the agent:");
        String mbeanClassName = mbeanName;

        ObjectInstance mbeanObjectInstance =
        connectorClient.createMBean( mbeanClassName, mbeanObjectName );

        echo("\tMBEAN CLASS NAME      = " +
             mbeanObjectInstance.getClassName() );
        echo("\tMBEAN OBJECT NAME     = " +
             mbeanObjectInstance.getObjectName() );
        echo("\nCurrent MBean count in the agent = "+
             connectorClient.getMBeanCount() );

        [...] // Retrieve MBeanInfo and access the MBean (see below)

        // unregister the MBean from the agent 
        //
        echo("\n>>> UNREGISTERING the "+ mbeanName +" MBean");
        connectorClient.unregisterMBean(
            mbeanObjectInstance.getObjectName() );

        [...]

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

Example 10–4 shows the use of other calls to the remote agent, such as getDefaultDomain and getMBeanCount that have the same purpose as in an agent application.

Accessing MBean Attributes and Operations

Once you can access the object names for MBeans in the agent, you can know their management interface from their MBeanInfo object. The code in Example 10–5 is actually called in between the MBean creation and unregistration shown in Example 10–4.


Example 10–5 Retrieving the MBeanInfo Object

ObjectName mbeanObjectName = mbeanObjectInstance.getObjectName();

echo("\n>>> Getting the management information of the MBean");
MBeanInfo info = null;
try {

    info = connectorClient.getMBeanInfo( mbeanObjectName );

} catch (Exception e) {
    echo("\t!!! Could not get MBeanInfo object for "+ mbeanObjectName );
    e.printStackTrace();
    return;
}

// display content of MBeanInfo object
//
echo("\nCLASSNAME: \t"+ info.getClassName());
echo("\nDESCRIPTION: \t"+ info.getDescription());
echo("\nATTRIBUTES");
MBeanAttributeInfo[] attrInfo = info.getAttributes();
if ( attrInfo.length>0 ) {
    for( int i=0; i<attrInfo.length; i++ ) {
        echo(" ** NAME: \t"+ attrInfo[i].getName());
        echo("    DESCR: \t"+ attrInfo[i].getDescription());
        echo("    TYPE: \t"+ attrInfo[i].getType() +
             "\tREAD: "+ attrInfo[i].isReadable() +
             "\tWRITE: "+ attrInfo[i].isWritable());
    }
} else echo(" ** No attributes **");

[...]

It is then straightforward to perform management operations on MBeans through the connector client. As in an agent, we call the generic getters, setters, and call methods with the object name of the MBean, the name of the attribute or operation, and any parameters. As in the methods of the MBean server, we need to use the Attribute and AttributeList classes to pass attributes as name-value pairs.


Example 10–6 Accessing an MBean Through the Connector Client

try {
    // Getting attribute values
    String State = (String)
        connectorClient.getAttribute( mbeanObjectName, "State" );
    Integer NbChanges = (Integer)
        connectorClient.getAttribute( mbeanObjectName, "NbChanges" );
    echo("\tState     = \"" + State + "\"");
    echo("\tNbChanges = " + NbChanges);

    // Setting the "State" attribute
    Attribute stateAttr = new Attribute("State", "new state from client");
    connectorClient.setAttribute(mbeanObjectName, stateAttr);

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

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

All other MBean access methods are available in the same manner, such as bulk getters and setters, and the query methods.

Creating and Accessing Dynamic MBeans

In the first run of the example, the management application creates, manages, and unregisters a standard MBean in the remote agent. However, standard and dynamic MBeans are designed to be managed through the same methods, both in the MBeanServer and in the RemoteMBeanServer interfaces.

As shown in Example 10–4, the subroutine of the example application takes only a single class name parameter. The first time this subroutine is called, the example passes the class name of a standard MBean, and the second time, that of a dynamic MBean. For the example to run, the two MBeans must have an identical management interface. By extension of this special case, we see that the connector client can manage dynamic MBeans through the same methods as it manages standard MBeans, without making any distinction between the two.

Running the SimpleClients Example

The examplesDir/SimpleClients directory contains all of the files for three sample managers, a base agent, and some MBeans to manage. In this chapter, we run the ClientWithoutProxy application that demonstrates simple operations on MBeans through an RMI connector.

To Run the Simple Client Example
  1. Compile all files in this directory with the javac command.

    For example, on the Solaris platform with the Korn shell, type:


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

    We do not need all the files for this chapter, but they are used in Chapter 11, MBean Proxies. In this demonstration, we only need the BaseAgent and ClientWithoutProxy applications, as well as the standard and dynamic MBeans.

  2. Start the agent in another terminal window on the same host with the following command:


    $ java -classpath classpath BaseAgent
    

    The agent creates an HTML protocol adaptor and an RMI connector server to which the client application establishes a connection, and then it waits for management operations.

  3. Wait for the agent to be completely initialized, then start the manager with the following command:


    $ java -classpath classpath ClientWithoutProxy
    

    The client application creates the RMI connector client and establishes the connection to base agent.

  4. Press Enter in the manager window to step through the example.

    The management application instantiates both types of MBeans, looks at their metadata, and performs management operations on them. The results of each step are displayed in the terminal window.

  5. At any time, you can view the agent through its HTML adaptor and interact with the MBeans created by the management application.

    For example, immediately after the manager creates an MBean, you could modify its attributes and see this change reflected when the connector client access the new values.

  6. Press Enter in both windows to stop the agent and manager applications.